order_base.go 9.3 KB
package domain

import (
	"time"

	"github.com/shopspring/decimal"
)

const (
	OrderReal         = iota + 1 //实发订单
	OrderIntention               //意向订单
	OrderTypeBestShop            //来自小程序海鲜干货的订单
)

func GetOrderBaseTypeName(orderType int) string {
	var name string
	switch orderType {
	case OrderReal:
		name = "自建订单"
	case OrderTypeBestShop:
		name = "小程序订单"
	case OrderIntention:
		name = "意向订单"
	}
	return name
}

const (
	OrderDisableNot = iota //订单未关闭
	OrderDisableYes        //订单已关闭
)

//Buyer 买家
type Buyer struct {
	//买家姓名
	BuyerName string `json:"buyerName"`
	//联系方式
	ContactInfo string `json:"contactInfo"`
	//收获地址
	ShippingAddress string `json:"shippingAddress"`
	//买家备注
	Remark string `json:"remark"`
}

type OrderCompute struct {
	//合伙人应收分红
	PlanPartnerBonus float64 `json:"planPartnerBonus"`
	//调整后的合伙人应收分红 (初始值=-1);
	//业务判定时0是有效值,
	//所以用空串表示无值,转换到数据库中为负值
	UsePartnerBonus float64 `json:"usePartnerBonus"`
	//合伙人已收分红
	PartnerBonusHas float64 `json:"partnerBonusHas"`
	//合伙人未收分红
	PartnerBonusNot float64 `json:"partnerBonusNot"`
	//合伙人分红支出
	PartnerBonusExpense float64 `json:"partnerBonusExpense"`
	//业务员抽成
	SalesmanBonus float64 `json:"salesmanBonus"`
	//预计的订单内货品总数
	PlanOrderCount int `json:"planOrderCount"`
	//预计的订单的总金额
	PlanOrderAmount float64 `json:"planOrderAmount"`
	//按需使用的订单内货品总数 (初始值=-1)
	//业务判定时0是有效值,
	//所以用空串表示无值,转换到数据库中为负值
	UseOrderCount int `json:"useOrderCount"`
	//按需使用的订单内货总金额 (初始值=-1)
	//业务判定时0是有效值,
	//所以用空串表示无值,转换到数据库中为负值
	UseOrderAmount float64 `json:"useOrderAmount"`
}

type OrderBaseRemark struct {
	RemarkBonus string `json:"remarkBonus"`
}

//OrderBase 订单基础
type OrderBase struct {
	//表id
	Id int64 `json:"id"`
	//订单类型
	OrderType int `json:"orderType"`
	//订单编号
	OrderCode string `json:"orderCode"`
	//交货编号
	DeliveryCode string `json:"deliveryCode"`
	//买家
	Buyer Buyer `json:"buyer"`
	//订单区域信息
	RegionInfo RegionInfo `json:"regionInfo"`
	//订单对应的合伙人
	PartnerId   int64   `json:"partnerId"`
	PartnerInfo Partner `json:"partnerInfo"`
	//业务员抽成比例
	SalesmanBonusPercent float64 `json:"salesmanBonusPercent"`
	//订单的创建时间
	CreateTime time.Time `json:"createTime"`
	//发货时间
	DeliveryTime time.Time `json:"deliveryTime"`
	//更新时间
	UpdateTime time.Time `json:"updateTime"`
	//货品
	Goods []OrderGood `json:"goods"`
	//核算订单相关数据
	OrderCompute OrderCompute `json:"orderCompute"`
	//是否关闭订单
	IsDisable int `json:"isDisable"`
	//分红支付状态
	BonusStatus int `json:"bonusStatus"`
	//公司
	CompanyId int64 `json:"companyId"`
	//数据来源
	DataFrom OrderDataFrom `json:"dataFrom"`
	//备注
	Remark OrderBaseRemark `json:"remark"`

	PartnerCategory PartnerCategory `json:"partnerCategory"`
}

//GetCurrentPartnerBonus 获取当前合伙人应收分红
func (order *OrderBase) GetCurrentPartnerBonus() float64 {
	if order.OrderCompute.UsePartnerBonus >= 0 {
		return order.OrderCompute.UsePartnerBonus
	}
	return order.OrderCompute.PlanPartnerBonus
}

//GetCurrentOrderCount 获取当前订单商品总数
func (order *OrderBase) GetCurrentOrderCount() int {
	if order.OrderCompute.UseOrderCount >= 0 {
		return order.OrderCompute.UseOrderCount
	}
	return order.OrderCompute.PlanOrderCount
}

// GetCurrentOrderAmount 获取当前订单的总额
func (order *OrderBase) GetCurrentOrderAmount() float64 {
	if order.OrderCompute.UseOrderAmount >= 0 {
		return order.OrderCompute.UseOrderAmount
	}
	return order.OrderCompute.PlanOrderAmount
}

//Update 更新订单数据
//orderData 订单数据
//goodsMap 货品的数据,以货品的id做键,map[id]map[string]interface{}
func (order *OrderBase) Update(orderData map[string]interface{}, goodsMap map[int64]map[string]interface{}) error {
	if v, ok := orderData["OrderCode"]; ok {
		order.OrderCode = v.(string)
	}
	if v, ok := orderData["DeliveryCode"]; ok {
		order.DeliveryCode = v.(string)
	}
	if v, ok := orderData["Buyer"]; ok {
		order.Buyer = v.(Buyer)
	}
	if v, ok := orderData["SalesmanBonusPercent"]; ok {
		order.SalesmanBonusPercent = v.(float64)
	}
	if v, ok := orderData["DeliveryTime"]; ok {
		order.DeliveryTime = v.(time.Time)
	}
	if v, ok := orderData["IsDisable"]; ok {
		order.IsDisable = v.(int)
	}
	for i := range order.Goods {
		goodId := order.Goods[i].Id
		if _, ok := goodsMap[goodId]; !ok {
			continue
		}
		if err := order.Goods[i].Update(goodsMap[goodId]); err != nil {
			return err
		}
	}
	err := order.Compute()
	return err
}

func (order *OrderBase) AddGoods(goods []OrderGood) {
	order.Goods = append(order.Goods, goods...)
	order.Compute()
}

func (order *OrderBase) DeleteGoods(goodIds []int64) {
	var newGoods []OrderGood
	for i := range order.Goods {
		for _, goodId := range goodIds {
			order.Goods[i].Id = goodId
			continue
		}
		newGoods = append(newGoods, order.Goods[i])
	}
	order.Goods = newGoods
	order.Compute()
}

//Compute 数据汇总核算
func (order *OrderBase) Compute() error {
	planPartnerBonus := decimal.NewFromFloat(0)
	planOrderAmount := decimal.NewFromFloat(0)
	var (
		planOrderCount   int  = 0
		useOrderCount    int  = 0
		HasUseOrderCount bool = false
	)
	usePartnerBonus := decimal.NewFromFloat(0)
	var hasUsePartnerBonus bool = false
	useOrderAmount := decimal.NewFromFloat(0)
	var hasUseOrderAmount bool = false
	partnerBonusHas := decimal.NewFromFloat(0)
	partnerBonusNot := decimal.NewFromFloat(0)
	partnerBonusExpense := decimal.NewFromFloat(0)
	//初始订单的支付状态
	order.BonusStatus = OrderGoodWaitPay
	//统计所以货品的值
	for i := range order.Goods {
		if order.Goods[i].BonusStatus == OrderGoodHasPay {
			//确定订单的支付状态
			order.BonusStatus = OrderGoodHasPay
		}
		planPartnerBonus = planPartnerBonus.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PlanPartnerBonus))
		planOrderAmount = planOrderAmount.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PlanAmount))
		planOrderCount += order.Goods[i].PlanGoodNumber
		goodUseAmount := decimal.NewFromFloat(order.Goods[i].GoodCompute.UseAmount)
		if goodUseAmount.GreaterThanOrEqual(decimal.NewFromFloat(0)) {
			//调整值非负值得情况
			hasUseOrderAmount = true
			useOrderAmount = useOrderAmount.Add(goodUseAmount)
		} else {
			useOrderAmount = useOrderAmount.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PlanAmount))
		}
		goodUsePartnerBonus := decimal.NewFromFloat(order.Goods[i].GoodCompute.UsePartnerBonus)
		if goodUsePartnerBonus.GreaterThanOrEqual(decimal.NewFromFloat(0)) {
			hasUsePartnerBonus = true
			usePartnerBonus = usePartnerBonus.Add(goodUsePartnerBonus)
		} else {
			usePartnerBonus = usePartnerBonus.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PlanPartnerBonus))
		}
		if order.Goods[i].UseGoodNumber >= 0 {
			HasUseOrderCount = true
			useOrderCount += order.Goods[i].UseGoodNumber
		} else {
			useOrderCount += order.Goods[i].PlanGoodNumber
		}
		partnerBonusHas = partnerBonusHas.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PartnerBonusHas))
		partnerBonusNot = partnerBonusNot.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PartnerBonusNot))
		partnerBonusExpense = partnerBonusExpense.Add(decimal.NewFromFloat(order.Goods[i].GoodCompute.PartnerBonusExpense))
	}
	//汇总赋值
	order.OrderCompute.PartnerBonusExpense, _ = partnerBonusExpense.Round(2).BigFloat().Float64()
	order.OrderCompute.PartnerBonusHas, _ = partnerBonusHas.Round(2).BigFloat().Float64()
	order.OrderCompute.PartnerBonusNot, _ = partnerBonusNot.Round(2).BigFloat().Float64()
	order.OrderCompute.PlanPartnerBonus, _ = planPartnerBonus.Round(2).BigFloat().Float64()
	order.OrderCompute.PlanOrderAmount, _ = planOrderAmount.Round(2).BigFloat().Float64()
	order.OrderCompute.PlanOrderCount = planOrderCount

	if hasUsePartnerBonus {
		order.OrderCompute.UsePartnerBonus, _ = usePartnerBonus.Round(2).BigFloat().Float64()
	} else {
		order.OrderCompute.UsePartnerBonus = -1
	}
	if hasUseOrderAmount {
		order.OrderCompute.UseOrderAmount, _ = useOrderAmount.Round(2).BigFloat().Float64()
		//计算业务员的抽成
		order.OrderCompute.SalesmanBonus, _ = useOrderAmount.
			Mul(decimal.NewFromFloat(order.SalesmanBonusPercent)).
			Div(decimal.NewFromInt(100)).
			Round(2).BigFloat().Float64()
	} else {
		order.OrderCompute.UseOrderAmount = -1
		order.OrderCompute.SalesmanBonus, _ = planOrderAmount.
			Mul(decimal.NewFromFloat(order.SalesmanBonusPercent)).
			Div(decimal.NewFromInt(100)).
			Round(2).BigFloat().Float64()
	}
	if HasUseOrderCount {
		order.OrderCompute.UseOrderCount = useOrderCount
	} else {
		order.OrderCompute.UseOrderCount = -1
	}
	return nil
}

type OrderBaseFindOneQuery struct {
	OrderId   int64
	CompanyId int64
}

type OrderBaseFindQuery struct {
	PartnerId    int64
	OrderCode    string
	DeliveryCode string
	Offset       int
	Limit        int
	OrderType    int
	CompanyId    int64
}

type OrderBaseRepository interface {
	Save(order *OrderBase) error
	FindOne(qureyOptions OrderBaseFindOneQuery) (*OrderBase, error)
	Find(queryOptions OrderBaseFindQuery) ([]OrderBase, int, error)
	Remove(id int64, companyId int64) error
}