diff --git a/business/controller/mtps/waybill.go b/business/controller/mtps/waybill.go index be04510b2..a894c3cbe 100644 --- a/business/controller/mtps/waybill.go +++ b/business/controller/mtps/waybill.go @@ -214,7 +214,7 @@ func (c *WaybillController) getMTPSShopID(order *model.GoodsOrder, db orm.Ormer) retVal = "test_0001" } } else { - globals.SugarLogger.Errorf("getMTPSShopID can not find mtps store info for orderID:%s, store:%d, num:%d, error:%v", order.VendorOrderID, JxStoreID, num, err) + globals.SugarLogger.Infof("getMTPSShopID can not find mtps store info for orderID:%s, store:%d, num:%d, error:%v", order.VendorOrderID, JxStoreID, num, err) if err == nil { err = ErrCanNotFindMTPSStore } diff --git a/business/scheduler/defsch/defsch.go b/business/scheduler/defsch/defsch.go index c1df60a14..810595d3c 100644 --- a/business/scheduler/defsch/defsch.go +++ b/business/scheduler/defsch/defsch.go @@ -92,31 +92,28 @@ func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder) (err error) { func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err error) { if status.Status > model.OrderStatusUnknown { // 只处理状态转换,一般消息不处理 globals.SugarLogger.Debugf("OnOrderStatusChanged, status:%v", status) - if savedOrderInfo := s.loadSavedOrderFromMap(status); savedOrderInfo != nil { - s.updateOrderByStatus(savedOrderInfo.order, status) - if status.Status > model.OrderStatusUnknown && status.Status < model.OrderStatusEndBegin { - if !(status.Status == model.OrderStatusFinishedPickup && len(savedOrderInfo.waybills) > 0) { //饿了么还观察到运单消息早于拣货完成消息 - gap := 0 * time.Second - beginTime := status.StatusTime - if status.Status == model.OrderStatusNew { - beginTime = time.Now() - } else if status.Status == model.OrderStatusAccepted { - gap = time.Duration(rand.Int63n(int64(time2AutoPickupGap))) - beginTime = s.getBeginTime4LatestPickup(savedOrderInfo.order) - } else if status.Status == model.OrderStatusFinishedPickup { - // 召唤三方配送 - // 正常应该是只依赖于购物平台的第一个运单消息,但饿了么有观察到极少数情况下没有此事件,所以还是需要在这里加个保险的TIMER来驱动运单调度 - gap = time2Schedule3rdCarrierGap4OrderStatus - } - s.resetTimer(savedOrderInfo, status.Status, beginTime, gap) + savedOrderInfo := s.loadSavedOrderFromMap(status) + s.updateOrderByStatus(savedOrderInfo.order, status) + if status.Status > model.OrderStatusUnknown && status.Status < model.OrderStatusEndBegin { + if !(status.Status == model.OrderStatusFinishedPickup && len(savedOrderInfo.waybills) > 0) { //饿了么还观察到运单消息早于拣货完成消息 + gap := 0 * time.Second + beginTime := status.StatusTime + if status.Status == model.OrderStatusNew { + beginTime = time.Now() + } else if status.Status == model.OrderStatusAccepted { + gap = time.Duration(rand.Int63n(int64(time2AutoPickupGap))) + beginTime = s.getBeginTime4LatestPickup(savedOrderInfo.order) + } else if status.Status == model.OrderStatusFinishedPickup { + // 召唤三方配送 + // 正常应该是只依赖于购物平台的第一个运单消息,但饿了么有观察到极少数情况下没有此事件,所以还是需要在这里加个保险的TIMER来驱动运单调度 + gap = time2Schedule3rdCarrierGap4OrderStatus } - } else { - s.stopTimer(savedOrderInfo) - s.cancelOtherWaybills(savedOrderInfo, nil) - s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status)) + s.resetTimer(savedOrderInfo, status.Status, beginTime, gap) } } else { - err = scheduler.ErrCanNotFindOrder + s.stopTimer(savedOrderInfo) + s.cancelOtherWaybills(savedOrderInfo, nil) + s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status)) } } return err @@ -126,9 +123,10 @@ func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err erro func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) { if bill.Status > model.WaybillStatusUnknown { globals.SugarLogger.Debugf("OnWaybillStatusChanged, bill:%v", bill) - if savedOrderInfo := s.loadSavedOrderFromMap(model.Waybill2Status(bill)); savedOrderInfo != nil { - s.addWaybill2Map(savedOrderInfo, bill) // 这样写的原因是因为调试时,程度从中途运行,没有接受到WaybillStatusNew事件 + savedOrderInfo := s.loadSavedOrderFromMap(model.Waybill2Status(bill)) + if bill.Status >= model.WaybillStatusNew { if bill.Status == model.WaybillStatusNew { + s.addWaybill2Map(savedOrderInfo, bill) if bill.OrderVendorID == bill.WaybillVendorID { if savedOrderInfo.timerStatus == model.OrderStatusFinishedPickup { // 如果当前TIMER还是OrderStatusFinishedPickup(在OnOrderStatusChanged中设置的),则重置 s.resetTimer(savedOrderInfo, model.OrderStatusFinishedPickup, bill.StatusTime, 0) @@ -136,53 +134,59 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) { globals.SugarLogger.Infof("OnWaybillStatusChanged met other timer, status:%d", savedOrderInfo.timerStatus) } } - if savedOrderInfo.order.WaybillVendorID != model.VendorIDUnknown { + if savedOrderInfo.order.WaybillVendorID != model.VendorIDUnknown && savedOrderInfo.order.WaybillVendorID != bill.WaybillVendorID { globals.SugarLogger.Infof("OnWaybillStatusChanged multiple waybill created, bill:%v", bill) if bill.WaybillVendorID != bill.WaybillVendorID { s.CancelWaybill(bill) } } } else { + if savedOrderInfo.order.WaybillVendorID == model.VendorIDUnknown || savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { + s.stopTimer(savedOrderInfo) // todo 这样写可能不太合适!!! + } switch bill.Status { case model.WaybillStatusAccepted: - s.stopTimer(savedOrderInfo) // todo 这里应该另外启动一个TIMER s.cancelOtherWaybills(savedOrderInfo, bill) - s.CurOrderManager.UpdateWaybillVendorID(bill) - savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID - case model.WaybillStatusAcceptCanceled: - if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { - s.createWaybillOn3rdProviders(savedOrderInfo.order, bill) - - bill.WaybillVendorID = model.VendorIDUnknown + if savedOrderInfo.order.WaybillVendorID == model.WaybillStatusUnknown { s.CurOrderManager.UpdateWaybillVendorID(bill) savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID + } else { + globals.SugarLogger.Infof("orderID:%s got multiple bill:%v, order details:%v", savedOrderInfo.order.VendorOrderID, bill, savedOrderInfo.order) } + case model.WaybillStatusAcceptCanceled: + if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { + bill.WaybillVendorID = model.VendorIDUnknown + s.CurOrderManager.UpdateWaybillVendorID(bill) + savedOrderInfo.order.WaybillVendorID = model.VendorIDUnknown + + s.createWaybillOn3rdProviders(savedOrderInfo.order, bill) + } + case model.WaybillStatusCourierArrived: // do nothing case model.WaybillStatusFailed: // todo WaybillStatusFailed理解成订单整个失败了,不需要再尝试创建运单了,注意这里应该加个zabbix日志的报警 s.removeWaybillFromMap(savedOrderInfo, bill) globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill) case model.WaybillStatusCanceled: s.removeWaybillFromMap(savedOrderInfo, bill) if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { - s.createWaybillOn3rdProviders(savedOrderInfo.order, nil) - bill.WaybillVendorID = model.VendorIDUnknown s.CurOrderManager.UpdateWaybillVendorID(bill) - savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID + savedOrderInfo.order.WaybillVendorID = model.VendorIDUnknown + + savedOrderInfo.order.Status = model.OrderStatusFinishedPickup // 如果运单被取消,且是主运单,将订单状态强制回滚到model.OrderStatusFinishedPickup + s.createWaybillOn3rdProviders(savedOrderInfo.order, nil) } case model.WaybillStatusDelivering: - if savedOrderInfo.order.VendorID != bill.WaybillVendorID { + if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID && savedOrderInfo.order.VendorID != bill.WaybillVendorID { s.SelfDeliverDelievering(savedOrderInfo.order) } case model.WaybillStatusDelivered: s.removeWaybillFromMap(savedOrderInfo, bill) - if savedOrderInfo.order.VendorID != bill.WaybillVendorID { + if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID && savedOrderInfo.order.VendorID != bill.WaybillVendorID { s.SelfDeliverDelievered(savedOrderInfo.order) } } } - } else { - err = scheduler.ErrCanNotFindOrder } } return err @@ -209,23 +213,27 @@ func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, bill } func (s *DefScheduler) createWaybillOn3rdProviders(order *model.GoodsOrder, excludeBill *model.Waybill) (err error) { - globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, excludeBill:%v", order.VendorOrderID, excludeBill) - if s.isOrderSupport3rdDelivery(order) { - successCount := 0 - for vendorID := range s.DeliveryPlatformHandlers { - if excludeBill == nil || vendorID != excludeBill.WaybillVendorID { - if err = s.CreateWaybill(vendorID, order); err == nil { - successCount++ + globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, status:%d, excludeBill:%v", order.VendorOrderID, order.Status, excludeBill) + if order.Status == model.OrderStatusFinishedPickup { + if s.isOrderSupport3rdDelivery(order) { + successCount := 0 + for vendorID := range s.DeliveryPlatformHandlers { + if excludeBill == nil || vendorID != excludeBill.WaybillVendorID { + if err = s.CreateWaybill(vendorID, order); err == nil { + successCount++ + } } } + if successCount != 0 { + return nil + } + globals.SugarLogger.Warnf("createWaybillOn3rdProviders, orderID:%s all failed", order.VendorOrderID) + return scheduler.ErrCanNotCreateAtLeastOneWaybill } - if successCount != 0 { - return nil - } - globals.SugarLogger.Warnf("createWaybillOn3rdProviders, orderID:%s all failed", order.VendorOrderID) - return scheduler.ErrCanNotCreateAtLeastOneWaybill + globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, store:%d dont't support 3rd delivery platform", order.VendorOrderID, jxutils.GetJxStoreIDFromOrder(order)) + } else { + globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, status:%d doesn't match model.OrderStatusFinishedPickup, bypass", order.VendorOrderID, order.Status) } - globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, store:%d dont't support 3rd delivery platform", order.VendorOrderID, jxutils.GetJxStoreIDFromOrder(order)) return nil } @@ -302,12 +310,13 @@ func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) { if savedOrderInfo.timer != nil { globals.SugarLogger.Debugf("stopTimer orderid:%v", savedOrderInfo.order.VendorOrderID) savedOrderInfo.timer.Stop() + savedOrderInfo.timerStatus = 0 } } func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, status int, beginTime time.Time, gap time.Duration) { globals.SugarLogger.Debugf("resetTimer status:%v, orderID:%s", status, savedOrderInfo.order.VendorOrderID) - if status >= savedOrderInfo.timerStatus { // 新设置的TIMER不能覆盖状态在其后的TIMER + if status >= savedOrderInfo.timerStatus { // 新设置的TIMER不能覆盖状态在其后的TIMER,如果状态回绕,需要注意 s.stopTimer(savedOrderInfo) config := s.mergeOrderStatusConfig(status, s.GetPurchasePlatformFromVendorID(savedOrderInfo.order.VendorID).GetStatusActionConfig(status)) if config != nil && config.TimeoutAction != nil { diff --git a/business/scheduler/scheduler.go b/business/scheduler/scheduler.go index bcab6b90d..d5ceb78d8 100644 --- a/business/scheduler/scheduler.go +++ b/business/scheduler/scheduler.go @@ -110,49 +110,69 @@ func (c *BaseScheduler) GetDeliveryPlatformFromVendorID(vendorID int) DeliveryPl func (c *BaseScheduler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool) (err error) { globals.SugarLogger.Infof("AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) - if c.IsReallyCallPlatformAPI { - err = utils.CallFuncLogError(func() error { - return c.GetPurchasePlatformFromVendorID(order.VendorID).AcceptOrRefuseOrder(order, isAcceptIt) - }, "AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) + if order.Status == model.OrderStatusNew { + if c.IsReallyCallPlatformAPI { + err = utils.CallFuncLogError(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) PickedUpGoods(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("PickedUpGoods orderID:%s", order.VendorOrderID) - if c.IsReallyCallPlatformAPI { - err = utils.CallFuncLogError(func() error { - return c.GetPurchasePlatformFromVendorID(order.VendorID).PickedUpGoods(order) - }, "PickedUpGoods orderID:%s", order.VendorOrderID) + if order.Status == model.OrderStatusAccepted { + if c.IsReallyCallPlatformAPI { + err = utils.CallFuncLogError(func() error { + return c.GetPurchasePlatformFromVendorID(order.VendorID).PickedUpGoods(order) + }, "PickedUpGoods orderID:%s", order.VendorOrderID) + } + } else { + globals.SugarLogger.Infof("PickedUpGoods 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 c.IsReallyCallPlatformAPI { - err = utils.CallFuncLogError(func() error { - return c.GetPurchasePlatformFromVendorID(order.VendorID).Swtich2SelfDeliver(order) - }, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID) + if order.Status == model.OrderStatusFinishedPickup { + if c.IsReallyCallPlatformAPI { + err = utils.CallFuncLogError(func() error { + return c.GetPurchasePlatformFromVendorID(order.VendorID).Swtich2SelfDeliver(order) + }, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID) + } + } else { + globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s, status:% 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 c.IsReallyCallPlatformAPI { - err = utils.CallFuncLogError(func() error { - return c.GetPurchasePlatformFromVendorID(order.VendorID).SelfDeliverDelievering(order) - }, "SelfDeliverDelievering orderID:%s", order.VendorOrderID) + if order.Status == model.OrderStatusFinishedPickup { + if c.IsReallyCallPlatformAPI { + err = utils.CallFuncLogError(func() error { + return c.GetPurchasePlatformFromVendorID(order.VendorID).SelfDeliverDelievering(order) + }, "SelfDeliverDelievering orderID:%s", order.VendorOrderID) + } + } 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 c.IsReallyCallPlatformAPI { - err = utils.CallFuncLogError(func() error { - return c.GetPurchasePlatformFromVendorID(order.VendorID).SelfDeliverDelievered(order) - }, "SelfDeliverDelievered orderID:%s", order.VendorOrderID) + if 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 }