package domain import ( "errors" "github.com/shopspring/decimal" ) //分红状态 type OrderGoodBonusStatus interface { //状态变更为待支付 WartPayPartnerBonus(orderGood *OrderGood) error //状态变更为已支付 PayPartnerBonus(orderGood *OrderGood) error } //货单的支付状态 const ( //待支付 OrderGoodWaitPay int = 1 //已支付 OrderGoodHasPay int = 2 ) //OrderGood 订单中的货品 type OrderGood struct { //货品id Id int64 `json:"id"` //所属订单id OrderId int64 `json:"orderId"` //货品名称 长度可能较长 GoodName string `json:"goodName"` //预计的货品数量 PlanGoodNumber int `json:"planGoodNumber"` //调整后的货品数量 //业务判定时0是有效值, //所以用空串表示无值,转换到数据库中为负值 UseGoodNumber int `json:"useGoodNumber"` //货品单价 Price float64 `json:"price"` //合伙人分红比例 PartnerBonusPercent float64 `json:"partnerBonusPercent"` //分红支付状态 BonusStatus int `json:"bonusStatus"` //备注信息 Remark string `json:"remark"` //当前分红支付状态 CurrentBonusStatus OrderGoodBonusStatus `json:"-"` ///核算订单相关数据 GoodCompute GoodCompute `json:"goodCompute"` } type GoodCompute struct { //预计的货品总额 PlanAmount float64 `json:"planAmount"` //调整后的货品总额 (初始值=-1) //业务判定时0是有效值, //所以用空串表示无值,转换到数据库中为负值 UseAmount float64 `json:"useAmount"` //预计的合伙人分红 PlanPartnerBonus float64 `json:"planPartnerBonus"` //合伙人应收分红调整 (初始值=-1), //业务判定时0是有效值, //所以用空串表示无值,转换到数据库中为负值 UsePartnerBonus float64 `json:"usePartnerBonus"` //合伙人已收分红 PartnerBonusHas float64 `json:"partnerBonusHas"` //合伙人未收分红 PartnerBonusNot float64 `json:"partnerBonusNot"` //合伙人分红支出 PartnerBonusExpense float64 `json:"partnerBonusExpense"` } //OrderGoodBonusWaitPay 货品分红待支付 type OrderGoodBonusWaitPay struct{} var _ OrderGoodBonusStatus = (*OrderGoodBonusWaitPay)(nil) //OrderGoodBonusHasPay 货品分红已支付 type OrderGoodBonusHasPay struct{} var _ OrderGoodBonusStatus = (*OrderGoodBonusHasPay)(nil) func (waitPay OrderGoodBonusWaitPay) WartPayPartnerBonus(good *OrderGood) error { good.GoodCompute.PartnerBonusExpense = 0 good.GoodCompute.PartnerBonusHas = 0 //初始状态为待支付时 ,合伙人未收分红等于合伙人应收分红(或者调整的) if good.UseGoodNumber < 0 { //数量没有调整,未收等于预计应收分红 good.GoodCompute.PartnerBonusNot = good.GoodCompute.PlanPartnerBonus } else { //数量有调整,未收等于调整后的应收分红 good.GoodCompute.PartnerBonusNot = good.GoodCompute.UsePartnerBonus } good.CurrentBonusStatus = OrderGoodBonusWaitPay{} return nil } func (waitPay OrderGoodBonusWaitPay) PayPartnerBonus(good *OrderGood) error { //待支付状态转支付时 //合伙人已收收分红等于合伙人应收分红(或者调整的) //计算已支付 if good.UseGoodNumber < 0 { //数量没有调整,已收等于预计应收分红 good.GoodCompute.PartnerBonusHas = good.GoodCompute.PlanPartnerBonus } else { //数量有调整,已收等于调整后的应收分红 good.GoodCompute.PartnerBonusHas = good.GoodCompute.UsePartnerBonus } good.GoodCompute.PartnerBonusExpense = 0 good.GoodCompute.PartnerBonusNot = 0 good.CurrentBonusStatus = OrderGoodBonusHasPay{} return nil } func (hasPay OrderGoodBonusHasPay) PayPartnerBonus(good *OrderGood) error { //已支付的值保持不变 //未支付的值保持不变 //计算分红支出 //分红支出=应收分红(有出现调整,则取调整后的应收分红)和已收分红的差额 if good.UseGoodNumber >= 0 { //有数量调整,分红支出等于 已支付分红-调整后的已收分红 good.GoodCompute.PartnerBonusExpense = good.GoodCompute.PartnerBonusHas - good.GoodCompute.UsePartnerBonus } good.CurrentBonusStatus = OrderGoodBonusHasPay{} return nil } func (hasPay OrderGoodBonusHasPay) WartPayPartnerBonus(good *OrderGood) error { return errors.New("已支付的货单不能将状态回退为待支付") } //NewOrderGood 初始值设定 func NewOrderGood() OrderGood { return OrderGood{ UseGoodNumber: -1, BonusStatus: OrderGoodWaitPay, GoodCompute: GoodCompute{ UsePartnerBonus: -1, UseAmount: -1, }, CurrentBonusStatus: OrderGoodBonusWaitPay{}, } } //Compute 数据汇总核算 func (good *OrderGood) Compute() error { //计算预计货品总值 //计算预计合伙人分红 price := decimal.NewFromFloat(good.Price) planamount := price.Mul(decimal.NewFromInt(int64(good.PlanGoodNumber))) //price*planGoodNumber //price*useGoodNumber planPartnerBonus := planamount.Mul(decimal.NewFromFloat(good.PartnerBonusPercent)).Div(decimal.NewFromInt(100)) //price*planGoodNumber*PartnerBonusPercent good.GoodCompute.PlanAmount, _ = planamount.Round(2).BigFloat().Float64() good.GoodCompute.PlanPartnerBonus, _ = planPartnerBonus.Round(2).BigFloat().Float64() if good.UseGoodNumber < 0 { //没有出现数量调整 good.GoodCompute.UsePartnerBonus = -1 good.GoodCompute.UseAmount = -1 } else { //计算调整后的货品总值 //计算调整后的合伙人分红 useamount := price.Mul(decimal.NewFromInt(int64(good.UseGoodNumber))) //price*useGoodNumber/price*useGoodNumber usePartnerBonus := useamount.Mul(decimal.NewFromFloat(good.PartnerBonusPercent)).Div(decimal.NewFromInt(100)) //price*useGoodNumber*PartnerBonusPercent good.GoodCompute.UsePartnerBonus, _ = usePartnerBonus.Round(2).BigFloat().Float64() good.GoodCompute.UseAmount, _ = useamount.Round(2).BigFloat().Float64() } return nil } type OrderGoodFindQuery struct { OrderId int64 Offset int Limit int } type OrderGoodRepository interface { Save(order []OrderGood) error Find(queryOptions OrderGoodFindQuery) ([]OrderGood, int, error) Remove(orderid int64, ids ...int64) error }