package scheduler import ( "errors" "fmt" "time" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/globals" ) const ( StoreDeliveryTypeCrowdSourcing = 0 //缺省,平台众包配送,可转自送 StoreDeliveryTypeByPlatform = 1 //平台专送 StoreDeliveryTypeByStore = 2 //完全门店自送 ) const ( TimerStatusTypeUnknown = -1 TimerStatusTypeOrder = 0 TimerStatusTypeWaybill = 1 ) const ( TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置 TimerTypeByPass = 1 TimerTypeBaseNow = 2 TimerTypeBaseStatusTime = 3 TimerTypeBaseExpectedDeliveredTime = 4 // 如果是定时达,以expected delivery time倒推的时间当成statusTime(之后与TimerTypeBaseStatusTime一样),否则与TimerTypeBaseStatusTime相同 ) var ( CurrentScheduler Scheduler ) var ( ErrStatusIsNotOKForOperation = errors.New("当前状态操作无效") ErrCanNotCreateAtLeastOneWaybill = errors.New("一个运单都不能创建") ErrCanNotFindOrder = errors.New("不能找到订单(一般是由于事件错序)") ErrCanNotFindWaybill = errors.New("不能找到运单(一般是由于事件错序)") ErrOrderIsNotSolid = errors.New("订单是临时订单,不完整,不能用于创建运单") ) type DeliveryPlatformHandlerInfo struct { Handler partner.IDeliveryPlatformHandler Use4CreateWaybill bool } type Scheduler interface { RegisterPurchasePlatform(vendorID int, handler partner.IPurchasePlatformHandler) RegisterDeliveryPlatform(vendorID int, handler partner.IDeliveryPlatformHandler, isUse4CreateWaybill bool) // 以下是订单 OnOrderNew(order *model.GoodsOrder, isPending bool) (err error) OnOrderStatusChanged(status *model.OrderStatus, isPending bool) (err error) // 以下是运单 OnWaybillStatusChanged(bill *model.Waybill, isPending bool) (err error) } type BaseScheduler struct { PurchasePlatformHandlers map[int]partner.IPurchasePlatformHandler DeliveryPlatformHandlers map[int]*DeliveryPlatformHandlerInfo IsReallyCallPlatformAPI bool } func (c *BaseScheduler) Init() { c.PurchasePlatformHandlers = make(map[int]partner.IPurchasePlatformHandler) c.DeliveryPlatformHandlers = make(map[int]*DeliveryPlatformHandlerInfo) } func (c *BaseScheduler) RegisterPurchasePlatform(vendorID int, handler partner.IPurchasePlatformHandler) { if !(vendorID >= model.VendorIDPurchaseBegin && vendorID <= model.VendorIDPurchaseEnd) { panic(fmt.Sprintf("purchase vendor:%d is illegal", vendorID)) } if _, ok := c.PurchasePlatformHandlers[vendorID]; ok { panic(fmt.Sprintf("purchase vendor:%d, already exists", vendorID)) } c.PurchasePlatformHandlers[vendorID] = handler } func (c *BaseScheduler) RegisterDeliveryPlatform(vendorID int, handler partner.IDeliveryPlatformHandler, isUse4CreateWaybill bool) { if !(vendorID >= model.VendorIDDeliveryBegin && vendorID <= model.VendorIDDeliveryEnd) { panic(fmt.Sprintf("delivery vendor:%d is illegal", vendorID)) } if _, ok := c.DeliveryPlatformHandlers[vendorID]; ok { panic(fmt.Sprintf("delivery vendor:%d, already exists", vendorID)) } c.DeliveryPlatformHandlers[vendorID] = &DeliveryPlatformHandlerInfo{ Handler: handler, Use4CreateWaybill: isUse4CreateWaybill, } } func (c *BaseScheduler) GetPurchasePlatformFromVendorID(vendorID int) partner.IPurchasePlatformHandler { return c.PurchasePlatformHandlers[vendorID] } func (c *BaseScheduler) GetDeliveryPlatformFromVendorID(vendorID int) *DeliveryPlatformHandlerInfo { return c.DeliveryPlatformHandlers[vendorID] } func (c *BaseScheduler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool) (err error) { globals.SugarLogger.Infof("AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) if order.LockStatus == model.OrderStatusUnknown && order.Status == model.OrderStatusNew { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogErrorWithInfo(func() error { return c.GetPurchasePlatformFromVendorID(order.VendorID).AcceptOrRefuseOrder(order, isAcceptIt) }, "AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) } } else { globals.SugarLogger.Infof("AcceptOrRefuseOrder orderID:%s, status:%d is not suitable, isAcceptIt:%t", order.VendorOrderID, order.Status, isAcceptIt) } return err } func (c *BaseScheduler) PickupGoods(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("PickupGoods orderID:%s", order.VendorOrderID) if order.LockStatus == model.OrderStatusUnknown && order.Status == model.OrderStatusAccepted { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogErrorWithInfo(func() error { return c.GetPurchasePlatformFromVendorID(order.VendorID).PickupGoods(order) }, "PickupGoods orderID:%s", order.VendorOrderID) } } else { globals.SugarLogger.Infof("PickupGoods orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } return err } func (c *BaseScheduler) Swtich2SelfDeliver(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s", order.VendorOrderID) if order.LockStatus == model.OrderStatusUnknown && order.Status == model.OrderStatusFinishedPickup { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogErrorWithInfo(func() error { return c.GetPurchasePlatformFromVendorID(order.VendorID).Swtich2SelfDeliver(order) }, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID) if err == nil { // 因为有些平台转自送后,不会再发送订单在配送中消息过来,所以成功后就强制设置状态为配送中 order.Status = model.OrderStatusDelivering } } } else { globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } return err } func (c *BaseScheduler) Swtich2SelfDelivered(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("Swtich2SelfDelivered orderID:%s", order.VendorOrderID) if order.LockStatus == model.OrderStatusUnknown && order.Status == model.OrderStatusDelivering { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogError(func() error { return c.GetPurchasePlatformFromVendorID(order.VendorID).Swtich2SelfDelivered(order) }, "Swtich2SelfDelivered orderID:%s", order.VendorOrderID) } } else { globals.SugarLogger.Infof("Swtich2SelfDelivered orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } return err } func (c *BaseScheduler) SelfDeliverDelievering(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("SelfDeliverDelievering orderID:%s", order.VendorOrderID) if order.LockStatus == model.OrderStatusUnknown && order.Status == model.OrderStatusFinishedPickup { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogError(func() error { return c.GetPurchasePlatformFromVendorID(order.VendorID).SelfDeliverDelievering(order) }, "SelfDeliverDelievering orderID:%s", order.VendorOrderID) if err == nil { // 因为有些平台设置配送中后,不会发送订单在配送中消息过来,所以成功后就强制设置状态为配送中 order.Status = model.OrderStatusDelivering } } } else if order.Status == model.OrderStatusDelivering { globals.SugarLogger.Debugf("SelfDeliverDelievering orderID:%s, status:%d already ok", order.VendorOrderID, order.Status) } else { globals.SugarLogger.Infof("SelfDeliverDelievering orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } return err } func (c *BaseScheduler) SelfDeliverDelievered(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("SelfDeliverDelievered orderID:%s", order.VendorOrderID) if order.LockStatus == model.OrderStatusUnknown && order.Status == model.OrderStatusDelivering { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogError(func() error { return c.GetPurchasePlatformFromVendorID(order.VendorID).SelfDeliverDelievered(order) }, "SelfDeliverDelievered orderID:%s", order.VendorOrderID) } } else { globals.SugarLogger.Infof("SelfDeliverDelievered orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } return err } func (c *BaseScheduler) CreateWaybill(platformVendorID int, order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("CreateWaybill orderID:%s, vendorID:%d", order.VendorOrderID, platformVendorID) if !model.IsOrderSolid(order) { // 如果订单是不完整的 globals.SugarLogger.Warnf("CreateWaybill orderID:%s, vendorID:%d is not solid!!!", order.VendorOrderID, platformVendorID) return ErrOrderIsNotSolid } if c.IsReallyCallPlatformAPI { handlerInfo := c.GetDeliveryPlatformFromVendorID(platformVendorID) if handlerInfo.Use4CreateWaybill { if err = handlerInfo.Handler.CreateWaybill(order); err != nil { globals.SugarLogger.Infof("CreateWaybill failed orderID:%s vendorID:%d with error:%v", order.VendorOrderID, platformVendorID, err) } } } return err } func (c *BaseScheduler) CancelWaybill(bill *model.Waybill) (err error) { globals.SugarLogger.Infof("CancelWaybill bill:%v", bill) if c.IsReallyCallPlatformAPI && bill.OrderVendorID != bill.WaybillVendorID { if handlerInfo := c.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID); handlerInfo != nil { err = utils.CallFuncLogError(func() error { return handlerInfo.Handler.CancelWaybill(bill) }, "CancelWaybill bill:%v", bill) globals.SugarLogger.Debugf("CancelWaybill bill:%v canceled by myself", bill) } } return err } type BasePurchasePlatform struct { } func (p *BasePurchasePlatform) GetStatusActionTimeout(statusType, status int) time.Duration { return 0 }