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 ) //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 } //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("已支付的货单不能将状态回退为待支付") } //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 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 }