package domain import ( "errors" "fmt" "github.com/shopspring/decimal" ) //分红状态 type OrderGoodBonusStatus interface { //状态变更为待支付 WartPayPartnerBonus(orderGood *OrderGood) error //状态变更为已支付 PayPartnerBonus(orderGood *OrderGood) error //变更货品数量 ModifyOrderGoodNumber(good *OrderGood, number int, orderType int) error //变更合伙人分红比例 ModifyPertnerBonusPercent(good *OrderGood, percent float64, orderType int) error } //货单的支付状态 const ( //待支付 OrderGoodWaitPay int = 1 //已支付 OrderGoodHasPay int = 2 ) //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"` } type OrderGoodRemarkReason struct { ModifyGoodNumber string `json:"modifyGoodNumber"` //货品数量变更的理由 ModifyPartnerBonusPercent string `json:"modifyPartnerBonusPercent"` //合伙人分红比例变更的理由 } //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"` //公司 CompanyId int64 `json:"companyId"` //原因备注 RemarkReason OrderGoodRemarkReason `json:"remarkReason"` DataFrom OrderDataFrom `json:"data_from"` } //GetCurrentGoodNumber 获取当前的商品数量 func (good OrderGood) GetCurrentGoodNumber() int { if good.UseGoodNumber >= 0 { return good.UseGoodNumber } return good.PlanGoodNumber } //GetCurrentAmount 获取当前的商品总额 func (good OrderGood) GetCurrentAmount() float64 { if good.GoodCompute.UseAmount >= 0 { return good.GoodCompute.UseAmount } return good.GoodCompute.PlanAmount } //GetCurrentAmount 获取当前的商品合伙人分红 func (good OrderGood) GetCurrentPartnerBonus() float64 { if good.GoodCompute.UsePartnerBonus >= 0 { return good.GoodCompute.UsePartnerBonus } return good.GoodCompute.PlanPartnerBonus } //GetCurrentAmount 获取当前的商品合伙人分红 func (good *OrderGood) ModifyOrderGoodNumber(number int, orderType int) error { if good.PlanGoodNumber < number { return fmt.Errorf("修改数量不能大于初始值:%d", good.PlanGoodNumber) } err := good.CurrentBonusStatus.ModifyOrderGoodNumber(good, number, orderType) return err } func (good *OrderGood) ModifyPertnerBonusPercent(percent float64, orderType int) error { err := good.CurrentBonusStatus.ModifyPertnerBonusPercent(good, percent, orderType) return err } //Update 更新商品相关的数据 func (good *OrderGood) Update(m map[string]interface{}) error { if v, ok := m["GoodName"]; ok { good.GoodName = v.(string) } if v, ok := m["PlanGoodNumber"]; ok { good.PlanGoodNumber = v.(int) } if v, ok := m["UseGoodNumber"]; ok { good.UseGoodNumber = v.(int) } if v, ok := m["Price"]; ok { good.Price = v.(float64) } if v, ok := m["PartnerBonusPercent"]; ok { good.PartnerBonusPercent = v.(float64) } if v, ok := m["Remark"]; ok { good.Remark = v.(string) } if v, ok := m["RemarkReason"]; ok { good.RemarkReason = v.(OrderGoodRemarkReason) } err := good.Compute() return err } //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{} good.BonusStatus = OrderGoodWaitPay 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{} good.BonusStatus = OrderGoodHasPay 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{} good.BonusStatus = OrderGoodHasPay return nil } func (hasPay OrderGoodBonusHasPay) WartPayPartnerBonus(good *OrderGood) error { return errors.New("已支付的货单不能将状态回退为待支付") } func (hasPay OrderGoodBonusHasPay) ModifyOrderGoodNumber(good *OrderGood, number int, orderType int) error { //规则描述: //实际自建订单(orderType==1),已支付分红状态下“可以”修改货品数量 //香米小程序订单(orderType==3),已支付分红状态下“不可以”修改货品数量 switch orderType { case OrderReal: good.UseGoodNumber = number //待支付状态计算 err := good.Compute() if err != nil { return errors.New("核算商品数据失败" + err.Error()) } case OrderTypeBestShop: return errors.New("小程序订单里已支付分红的货品订单,不能修改货品数量") } good.CurrentBonusStatus.PayPartnerBonus(good) return nil } func (waitPay OrderGoodBonusWaitPay) ModifyOrderGoodNumber(good *OrderGood, number int, orderType int) error { //规则描述: //实际自建订单(orderType==1),未支付分红状态下“可以”修改货品数量 //香米小程序订单(orderType==3),未支付分红状态下“可以”修改货品数量 good.UseGoodNumber = number //待支付状态计算 err := good.Compute() if err != nil { return errors.New("核算商品数据失败" + err.Error()) } good.CurrentBonusStatus.WartPayPartnerBonus(good) return nil } func (waitPay OrderGoodBonusWaitPay) ModifyPertnerBonusPercent(good *OrderGood, percent float64, orderType int) error { //规则描述: //实际自建订单(orderType==1),未支付分红状态下“不可以”修改合伙人分红比例 //香米小程序订单(orderType==3),未支付分红状态下“可以”修改合伙人分红比例 switch orderType { case OrderReal: return errors.New("自建订单不能修改合伙人分红比例") case OrderTypeBestShop: good.PartnerBonusPercent = percent //待支付状态计算 err := good.Compute() if err != nil { return errors.New("核算商品数据失败" + err.Error()) } err = good.CurrentBonusStatus.WartPayPartnerBonus(good) if err != nil { return errors.New("核算商品数据失败" + err.Error()) } } return nil } func (hasPay OrderGoodBonusHasPay) ModifyPertnerBonusPercent(good *OrderGood, percent float64, orderType int) error { //规则描述: //实际自建订单(orderType==1),已支付分红状态下“不可以”修改合伙人分红比例 //香米小程序订单(orderType==3),已支付分红状态下“不可以”修改合伙人分红比例 return errors.New("已支付分红的货品订单,不能修改合伙人分红比例") } //NewOrderGood 初始值设定 func NewOrderGood() OrderGood { return OrderGood{ UseGoodNumber: -1, BonusStatus: OrderGoodWaitPay, PartnerBonusPercent: -1, GoodCompute: GoodCompute{ UsePartnerBonus: -1, UseAmount: -1, }, CurrentBonusStatus: OrderGoodBonusWaitPay{}, } } //Compute 数据汇总核算 func (good *OrderGood) Compute() error { //计算预计货品总值 //计算预计合伙人分红 price := decimal.NewFromFloat(good.Price) planGoodNumber := good.PlanGoodNumber if good.PlanGoodNumber < 0 { planGoodNumber = 0 } planamount := price.Mul(decimal.NewFromInt(int64(planGoodNumber))) //price*planGoodNumber var partnerBonusPercent float64 if good.PartnerBonusPercent < 0 { partnerBonusPercent = 0 } else { partnerBonusPercent = good.PartnerBonusPercent } //price*useGoodNumber planPartnerBonus := planamount.Mul(decimal.NewFromFloat(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(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 CompanyId int64 } type OrderGoodFindOneQuery struct { GoodId int64 } type OrderGoodRepository interface { Save(order []OrderGood) error Find(queryOptions OrderGoodFindQuery) ([]OrderGood, int, error) FindOne(queryOptions OrderGoodFindOneQuery) (OrderGood, error) Remove(orderid int64, companyId int64, ids ...int64) error }