From 16c8aa018f96015b8ef2b374f04663ef6686f4bb Mon Sep 17 00:00:00 2001 From: gazebo Date: Tue, 14 May 2019 12:04:45 +0800 Subject: [PATCH] =?UTF-8?q?-=20defsch=E8=B0=83=E5=BA=A6=E5=99=A8=E7=9A=84t?= =?UTF-8?q?imer=E6=B7=BB=E5=8A=A0=E6=9D=A1=E4=BB=B6=E5=87=BD=E6=95=B0Shoul?= =?UTF-8?q?dSetTimer=20-=20=E9=A5=BF=E7=99=BE=E5=8F=91=E4=B8=89=E6=96=B9?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=9C=A8=E8=AE=A2=E5=8D=95=E5=88=9B=E5=BB=BA?= =?UTF-8?q?30=E5=88=86=E9=92=9F=E5=90=8E=E6=89=8D=E5=8F=AF=E4=BB=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jxcallback/scheduler/defsch/defsch.go | 128 ++++++++++++------ business/model/const.go | 1 - business/partner/partner.go | 16 ++- business/partner/purchase/ebai/waybill.go | 6 +- 4 files changed, 100 insertions(+), 51 deletions(-) diff --git a/business/jxcallback/scheduler/defsch/defsch.go b/business/jxcallback/scheduler/defsch/defsch.go index e94453f11..bc625b742 100644 --- a/business/jxcallback/scheduler/defsch/defsch.go +++ b/business/jxcallback/scheduler/defsch/defsch.go @@ -25,9 +25,10 @@ import ( ) const ( - time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。 - minute2Schedule3rdCarrier = 20 // 收到平台方自有配送的新运单消息后,等待创建三方配送运单的时间(分钟),如果是定时达,会再根据ExpectedDeliveredTime与dingShiDaAheadTime做调整 - minMinute2Schedule3rdCarrier = 5 // 转三方配送最少等待时间(分钟) + time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。 + minute2Schedule3rdCarrier = 20 // 收到平台方自有配送的新运单消息后,等待创建三方配送运单的时间(分钟),如果是定时达,会再根据ExpectedDeliveredTime与dingShiDaAheadTime做调整 + minute2Schedule3rdCarrier4Ebai = 30 // 饿百的最少转自配送需要的时间(分钟) + minMinute2Schedule3rdCarrier = 5 // 转三方配送最少等待时间(分钟) time2AutoPickupMin = 15 * time.Minute // 自动拣货等待时间,这个只有在没有PickDeadline信息才有用,否则会根据PickDeadline设置 second2AutoPickupGap = 60 //随机60秒 @@ -71,7 +72,15 @@ type WatchOrderInfo struct { type StatusActionConfig struct { partner.StatusActionParams - TimeoutAction func(savedOrderInfo *WatchOrderInfo) (err error) // 超时后需要执行的动作,为nil表示此状态不需要执行监控, nil在GetStatusActionConfig返回时表示不修改缺省 + TimeoutAction func(savedOrderInfo *WatchOrderInfo) (err error) // 超时后需要执行的动作,为nil表示此状态不需要执行监控, nil在GetStatusActionConfig返回时表示不修改缺省 + ShouldSetTimer func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool +} + +func (c *StatusActionConfig) CallShouldSetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + if c.ShouldSetTimer != nil { + return c.ShouldSetTimer(savedOrderInfo, bill) + } + return true } // 重要:此调度器要求同一定单的处理逻辑必须是序列化了的,不然会有并发问题 @@ -164,6 +173,9 @@ func init() { }) return nil }, + ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + return savedOrderInfo.order.Status == model.OrderStatusNew + }, }, model.OrderStatusAccepted: &StatusActionConfig{ // 自动拣货 StatusActionParams: partner.StatusActionParams{ @@ -177,6 +189,9 @@ func init() { } return nil }, + ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + return savedOrderInfo.autoPickupTimeoutMinute > 0 + }, }, model.OrderStatusFinishedPickup: &StatusActionConfig{ StatusActionParams: partner.StatusActionParams{ @@ -190,6 +205,9 @@ func init() { } return nil }, + ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + return savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore + }, }, }, map[int]*StatusActionConfig{ @@ -205,6 +223,27 @@ func init() { } return nil }, + ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + return savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && savedOrderInfo.order.VendorID != model.VendorIDEBAI + }, + }, + model.WaybillStatusCanceled: &StatusActionConfig{ + StatusActionParams: partner.StatusActionParams{ + TimerType: partner.TimerTypeBaseOrderCreatedAt, + Timeout: minute2Schedule3rdCarrier4Ebai * time.Minute, + }, + TimeoutAction: func(savedOrderInfo *WatchOrderInfo) (err error) { + // 饿百转自送的时机不太清楚,暂时禁用超时转自送,在饿百运单取消时还是会自动创建 + order := savedOrderInfo.order + if (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) && savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && order.VendorID == model.VendorIDEBAI { // 非自配送商家使用 + return sch.createWaybillOn3rdProviders(savedOrderInfo, nil) + } + return nil + }, + ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + order := savedOrderInfo.order + return (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) && savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && order.VendorID == model.VendorIDEBAI + }, }, }, } @@ -429,7 +468,7 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo // 之前的条件是order.Status < model.OrderStatusDelivering,但像订单902322817000122确实有在配送中取消状态,改成非订单结束状态都可以 // OrderStatusFinishedPickup状态的订单依赖于TIMER重新建运单 if bill.DeliveryFlag&model.WaybillDeliveryFlagMaskActiveCancel == 0 { - if order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin && (bill.WaybillVendorID != order.VendorID || order.VendorID == model.VendorIDEBAI) { + if (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) && bill.WaybillVendorID != order.VendorID { s.createWaybillOn3rdProviders(savedOrderInfo, nil) } } @@ -468,12 +507,12 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo weixinmsg.NotifyWaybillStatus(bill, order, false) }) } - case model.WaybillStatusNeverSend: // 平台不配送,直接创建三方运单 - s.resetTimer(savedOrderInfo, bill, isPending) - s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID) - if order.WaybillVendorID == model.VendorIDUnknown { - s.createWaybillOn3rdProviders(savedOrderInfo, nil) - } + // case model.WaybillStatusNeverSend: // 平台不配送,直接创建三方运单 + // s.resetTimer(savedOrderInfo, bill, isPending) + // s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID) + // if order.WaybillVendorID == model.VendorIDUnknown { + // s.createWaybillOn3rdProviders(savedOrderInfo, nil) + // } } s.updateBillsInfo(savedOrderInfo, bill) // 更新可能的运单状态变化 } @@ -660,38 +699,40 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Wa s.stopTimer(savedOrderInfo) } if config != nil && config.TimeoutAction != nil && config.TimerType != partner.TimerTypeByPass { - timeout := config.GetRefTimeout(statusTime) - if config.TimeoutGap != 0 { - timeout += time.Duration(rand.Intn(int(config.TimeoutGap))) * time.Second - } - if isPending && timeout < pendingOrderTimerMaxSecond*time.Second { // 如果是PENDING的订单,则将其分布到2--5秒内,让后续事件有机会执行 - timeout = time.Duration(jxutils.MapValue2Scope(int64(timeout), -pendingOrderTimerMinMinSecond*1000, pendingOrderTimerMaxSecond*1000, pendingOrderTimerMinSecond*1000, pendingOrderTimerMaxSecond*1000)) * time.Millisecond - } else if timeout < 0 { - timeout = 0 - } - if timeout == 0 { - config.TimeoutAction(savedOrderInfo) - } else { - timerName := "" - if statusType == scheduler.TimerStatusTypeOrder { - timerName = model.OrderStatusName[status] - } else if statusType == scheduler.TimerStatusTypeWaybill { - timerName = model.WaybillStatusName[status] + if config.CallShouldSetTimer(savedOrderInfo, bill) { + timeout := config.GetRefTimeout(statusTime, order.OrderCreatedAt) + if config.TimeoutGap != 0 { + timeout += time.Duration(rand.Intn(int(config.TimeoutGap))) * time.Second } - savedOrderInfo.timerStatusType = statusType - savedOrderInfo.timerStatus = status - savedOrderInfo.timerTime = time.Now().Add(timeout) - savedOrderInfo.timer = utils.AfterFuncWithRecover(timeout, func() { - jxutils.CallMsgHandlerAsync(func() { - globals.SugarLogger.Debugf("fire timer:%s, orderID:%s", timerName, order.VendorOrderID) - savedOrderInfo := s.loadSavedOrderFromMap(model.Order2Status(order), true) - config.TimeoutAction(savedOrderInfo) - savedOrderInfo.timerStatus = 0 - savedOrderInfo.timerStatusType = scheduler.TimerStatusTypeUnknown - }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID)) - }) + if isPending && timeout < pendingOrderTimerMaxSecond*time.Second { // 如果是PENDING的订单,则将其分布到2--5秒内,让后续事件有机会执行 + timeout = time.Duration(jxutils.MapValue2Scope(int64(timeout), -pendingOrderTimerMinMinSecond*1000, pendingOrderTimerMaxSecond*1000, pendingOrderTimerMinSecond*1000, pendingOrderTimerMaxSecond*1000)) * time.Millisecond + } else if timeout < 0 { + timeout = 0 + } + if timeout == 0 { + config.TimeoutAction(savedOrderInfo) + } else { + timerName := "" + if statusType == scheduler.TimerStatusTypeOrder { + timerName = model.OrderStatusName[status] + } else if statusType == scheduler.TimerStatusTypeWaybill { + timerName = model.WaybillStatusName[status] + } + savedOrderInfo.timerStatusType = statusType + savedOrderInfo.timerStatus = status + savedOrderInfo.timerTime = time.Now().Add(timeout) + savedOrderInfo.timer = utils.AfterFuncWithRecover(timeout, func() { + jxutils.CallMsgHandlerAsync(func() { + globals.SugarLogger.Debugf("fire timer:%s, orderID:%s", timerName, order.VendorOrderID) + savedOrderInfo := s.loadSavedOrderFromMap(model.Order2Status(order), true) + config.TimeoutAction(savedOrderInfo) + savedOrderInfo.timerStatus = 0 + savedOrderInfo.timerStatusType = scheduler.TimerStatusTypeUnknown + }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID)) + }) + } + globals.SugarLogger.Debugf("resetTimer, orderID:%s, status:%d, timeout:%v", order.VendorOrderID, status, timeout) } - globals.SugarLogger.Debugf("resetTimer, orderID:%s, status:%d, timeout:%v", order.VendorOrderID, status, timeout) } } } @@ -701,6 +742,9 @@ func isStatusNewer(curStatusType, curStatus, statusType, status int) bool { if curStatusType == scheduler.TimerStatusTypeWaybill && statusType == scheduler.TimerStatusTypeOrder && status <= model.OrderStatusFinishedPickup { return false } + if curStatusType == scheduler.TimerStatusTypeWaybill { + return curStatus != status + } return curStatusType != statusType || status >= curStatus } @@ -731,7 +775,7 @@ func (s *DefScheduler) mergeOrderStatusConfig(savedOrderInfo *WatchOrderInfo, st TimeoutGap: -1, } timeout := statusTime.Sub(time.Now()) + minMinute2Schedule3rdCarrier*time.Minute - if vendorActionParams.GetRefTimeout(statusTime) < timeout { // 如果非立即达订单,根据ExpectedDeliveredTime算出来的timeout太早 + if vendorActionParams.GetRefTimeout(statusTime, order.OrderCreatedAt) < timeout { // 如果非立即达订单,根据ExpectedDeliveredTime算出来的timeout太早 vendorActionParams.Timeout = timeout vendorActionParams.TimeoutGap = 0 } diff --git a/business/model/const.go b/business/model/const.go index 75d9f372f..4879ec977 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -278,7 +278,6 @@ const ( WaybillStatusDelivered = 105 // todo 这个应该改为110,与订单对应 WaybillStatusCanceled = 115 WaybillStatusFailed = 120 // 这个状态存在的意义是区分于WaybillStatusCanceled,比如达达平台在这种状态下再次创建运单的方式不一样 - WaybillStatusNeverSend = 125 // 这个状态指的是平台方不愿意配送,门店自己想办法。与WaybillStatusAcceptCanceled不一样,WaybillStatusAcceptCanceled可能之后还会尝试配送 ) const ( diff --git a/business/partner/partner.go b/business/partner/partner.go index d3db835ee..c0d398fa6 100644 --- a/business/partner/partner.go +++ b/business/partner/partner.go @@ -57,10 +57,11 @@ type PrinterStatus struct { } const ( - TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置 - TimerTypeByPass = 1 - TimerTypeBaseNow = 2 - TimerTypeBaseStatusTime = 3 + TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置 + TimerTypeByPass = 1 + TimerTypeBaseNow = 2 + TimerTypeBaseStatusTime = 3 + TimerTypeBaseOrderCreatedAt = 4 ) type StatusActionParams struct { @@ -86,15 +87,20 @@ type WaybillFeeInfo struct { Waybill *model.Waybill `json:"waybill"` } -func (s *StatusActionParams) GetRefTimeout(statusTime time.Time) (timeout time.Duration) { +func (s *StatusActionParams) GetRefTimeout(statusTime time.Time, orderCreatedAt time.Time) (timeout time.Duration) { switch s.TimerType { case TimerTypeBaseNow: timeout = s.Timeout case TimerTypeBaseStatusTime: timeout = statusTime.Sub(time.Now()) + s.Timeout + case TimerTypeBaseOrderCreatedAt: + timeout = orderCreatedAt.Sub(time.Now()) + s.Timeout default: timeout = 0 } + if timeout < 0 { + timeout = 0 + } return timeout } diff --git a/business/partner/purchase/ebai/waybill.go b/business/partner/purchase/ebai/waybill.go index 16ae27a2f..5b81bf2e1 100644 --- a/business/partner/purchase/ebai/waybill.go +++ b/business/partner/purchase/ebai/waybill.go @@ -18,10 +18,10 @@ var ( ebaiapi.WaybillStatusCourierPickedup: model.WaybillStatusDelivering, ebaiapi.WaybillStatusDeliveryCancled: model.WaybillStatusCanceled, ebaiapi.WaybillStatusFinished: model.WaybillStatusDelivered, - ebaiapi.WaybillStatusExceptional: model.WaybillStatusUnknown, + ebaiapi.WaybillStatusExceptional: model.WaybillStatusCanceled, ebaiapi.WaybillStatusSelfDelivery: model.WaybillStatusUnknown, - ebaiapi.WaybillStatusDontDeliver: model.WaybillStatusUnknown, - ebaiapi.WaybillStatusDeliveryRejected: model.WaybillStatusNeverSend, + ebaiapi.WaybillStatusDontDeliver: model.WaybillStatusCanceled, + ebaiapi.WaybillStatusDeliveryRejected: model.WaybillStatusCanceled, } )