From bb049bb28b5285734744c50c4f6fe1b45b656401 Mon Sep 17 00:00:00 2001 From: gazebo Date: Fri, 24 Aug 2018 10:03:34 +0800 Subject: [PATCH] - order.DeliveryFlag added. --- business/jxcallback/orderman/order.go | 6 +- business/jxcallback/orderman/orderman_ext.go | 2 +- .../jxcallback/scheduler/basesch/basesch.go | 5 +- .../scheduler/basesch/basesch_ext.go | 27 +- .../jxcallback/scheduler/defsch/defsch.go | 266 ++++++++++-------- .../jxcallback/scheduler/defsch/defsch_ext.go | 55 ++++ business/jxutils/weixinmsg/weixinmsg.go | 28 +- business/model/const.go | 5 + business/model/order.go | 5 +- business/partner/partner.go | 2 +- controllers/jx_order.go | 10 +- globals/globals.go | 2 + 12 files changed, 238 insertions(+), 175 deletions(-) create mode 100644 business/jxcallback/scheduler/defsch/defsch_ext.go diff --git a/business/jxcallback/orderman/order.go b/business/jxcallback/orderman/order.go index 0ff296309..489dcaee8 100644 --- a/business/jxcallback/orderman/order.go +++ b/business/jxcallback/orderman/order.go @@ -342,12 +342,12 @@ func (c *OrderManager) LoadOrder(vendorOrderID string, vendorID int) (order *mod return order, err } -func (c *OrderManager) UpdateOrderStatusDirectly(order *model.GoodsOrder) (err error) { +func (c *OrderManager) UpdateOrderStatusAndFlag(order *model.GoodsOrder) (err error) { db := orm.NewOrm() utils.CallFuncLogError(func() error { - _, err = db.Update(order, "Status") + _, err = db.Update(order, "Status", "DeliveryFlag") return err - }, "UpdateOrderStatusDirectly orderID:%s failed with error:%v", order.VendorOrderID, err) + }, "UpdateOrderStatusAndFlag orderID:%s failed with error:%v", order.VendorOrderID, err) return err } diff --git a/business/jxcallback/orderman/orderman_ext.go b/business/jxcallback/orderman/orderman_ext.go index 666bb7255..ce1cd0adb 100644 --- a/business/jxcallback/orderman/orderman_ext.go +++ b/business/jxcallback/orderman/orderman_ext.go @@ -40,7 +40,7 @@ func (c *OrderManager) GetStoreOrderInfo(storeID string, lastHours int, fromStat WHERE IF(t1.jx_store_id != 0, t1.jx_store_id, t1.store_id) = ? AND t1.order_created_at >= ? AND t1.Status >= ? AND t1.Status <= ? - ORDER BY t1.order_created_at + ORDER BY t1.status, t1.order_created_at LIMIT ? OFFSET ? `, storeID, time.Now().Add(-time.Duration(lastHours)*time.Hour), fromStatus, toStatus, pageSize, offset).QueryRows(&orders) if err == nil { diff --git a/business/jxcallback/scheduler/basesch/basesch.go b/business/jxcallback/scheduler/basesch/basesch.go index 5f8154bf5..87fb4263d 100644 --- a/business/jxcallback/scheduler/basesch/basesch.go +++ b/business/jxcallback/scheduler/basesch/basesch.go @@ -16,10 +16,6 @@ type BaseScheduler struct { IsReallyCallPlatformAPI bool } -var ( - FixedBaseScheduler *BaseScheduler -) - func (c *BaseScheduler) Init() { c.PurchasePlatformHandlers = make(map[int]partner.IPurchasePlatformHandler) c.DeliveryPlatformHandlers = make(map[int]*scheduler.DeliveryPlatformHandlerInfo) @@ -100,6 +96,7 @@ func (c *BaseScheduler) Swtich2SelfDeliver(order *model.GoodsOrder, userName str }, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID) if err == nil { // 因为有些平台转自送后,不会再发送订单在配送中消息过来,所以成功后就强制设置状态为配送中 order.Status = model.OrderStatusDelivering + order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled } } } else { diff --git a/business/jxcallback/scheduler/basesch/basesch_ext.go b/business/jxcallback/scheduler/basesch/basesch_ext.go index 35f611725..47743ec73 100644 --- a/business/jxcallback/scheduler/basesch/basesch_ext.go +++ b/business/jxcallback/scheduler/basesch/basesch_ext.go @@ -30,29 +30,6 @@ func (c *BaseScheduler) CreateWaybillOnProviders(vendorOrderID string, vendorID return nil, err } -// todo 这里应该要考虑纯自送与转自送 -func (c *BaseScheduler) SelfDeliveringAndUpdateStatus(vendorOrderID string, vendorID int, userName string) (err error) { - globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) - order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) - if err == nil { - if getStoreDeliveryType(order) == scheduler.StoreDeliveryTypeByStore { - err = c.SelfDeliverDelievering(order, userName) - } else { - err = c.Swtich2SelfDeliver(order, userName) - } - if err == nil { - order.Status = model.OrderStatusDelivering - if err = partner.CurOrderManager.UpdateOrderStatusDirectly(order); err == nil { - globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus orderID:%s userName:%s successfully", vendorOrderID, userName) - return err - } - } - } - globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus orderID:%s userName:%s error:%v", vendorOrderID, userName, err) - return err -} - -// todo 这里应该要考虑纯自送与转自送 func (c *BaseScheduler) SelfDeliveredAndUpdateStatus(vendorOrderID string, vendorID int, userName string) (err error) { globals.SugarLogger.Infof("SelfDeliveredAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) @@ -64,7 +41,7 @@ func (c *BaseScheduler) SelfDeliveredAndUpdateStatus(vendorOrderID string, vendo } if err == nil { order.Status = model.OrderStatusDelivered - if err = partner.CurOrderManager.UpdateOrderStatusDirectly(order); err == nil { + if err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order); err == nil { globals.SugarLogger.Infof("SelfDeliveredAndUpdateStatus orderID:%s userName:%s successfully", vendorOrderID, userName) return err } @@ -81,7 +58,7 @@ func (c *BaseScheduler) PickupGoodsAndUpdateStatus(vendorOrderID string, vendorI err = c.PickupGoods(order, userName) if err == nil { order.Status = model.OrderStatusFinishedPickup - if err = partner.CurOrderManager.UpdateOrderStatusDirectly(order); err == nil { + if err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order); err == nil { globals.SugarLogger.Infof("PickupGoodsAndUpdateStatus orderID:%s userName:%s successfully", vendorOrderID, userName) return err } diff --git a/business/jxcallback/scheduler/defsch/defsch.go b/business/jxcallback/scheduler/defsch/defsch.go index cc3816f28..7aa7306f7 100644 --- a/business/jxcallback/scheduler/defsch/defsch.go +++ b/business/jxcallback/scheduler/defsch/defsch.go @@ -43,12 +43,14 @@ var ( ErrAddFeeExceeded = errors.New("配送超过基准价太多") ) +var ( + FixedScheduler *DefScheduler +) + type WatchOrderInfo struct { autoPickupTimeoutMinute int // 0表示禁用,1表示用缺省值time2AutoPickupMin,其它表示分钟数 storeDeliveryType int - isNeed3rdDelivery bool supported3rdCarriers []int - isSwitched2SelfDelivery bool order *model.GoodsOrder // order里的信息是保持更新的 waybills map[int]*model.Waybill // 这个waybills里的状态信息是不真实的,只使用id相关的信息 @@ -76,7 +78,6 @@ type DefScheduler struct { func NewWatchOrderInfo(order *model.GoodsOrder) (retVal *WatchOrderInfo) { retVal = &WatchOrderInfo{ autoPickupTimeoutMinute: 1, - isNeed3rdDelivery: false, storeDeliveryType: scheduler.StoreDeliveryTypeCrowdSourcing, waybills: map[int]*model.Waybill{}, supported3rdCarriers: []int{}, @@ -111,12 +112,16 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e } else if order.VendorID == model.VendorIDJD { s.storeDeliveryType = int(storefeature.JdDeliveryType) } + if s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { + order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled + } + isNeedSchedule := false if (s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore) || (order.VendorID == model.VendorIDJD && storefeature.JdCompetition != 0) || (order.VendorID == model.VendorIDELM && storefeature.ElmCompetition != 0) { - s.isNeed3rdDelivery = true + isNeedSchedule = true } - if s.isNeed3rdDelivery { + if isNeedSchedule { if storefeature.SupportMtps != 0 { s.supported3rdCarriers = append(s.supported3rdCarriers, model.VendorIDMTPS) } @@ -127,10 +132,13 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e s.supported3rdCarriers = append(s.supported3rdCarriers, model.VendorIDFengNiao) } if len(s.supported3rdCarriers) == 0 { - s.isNeed3rdDelivery = false + isNeedSchedule = false globals.SugarLogger.Infof("updateOrderStoreFeature orderID:%s no at least one carrier supported", order.VendorOrderID) } } + if !isNeedSchedule { + order.DeliveryFlag |= model.OrderDeliveryFlagMaskScheduleDisabled + } } return err }, "updateOrderStoreFeature") @@ -140,9 +148,9 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e func init() { sch := &DefScheduler{} + FixedScheduler = sch sch.IsReallyCallPlatformAPI = globals.ReallyCallPlatformAPI sch.Init() - basesch.FixedBaseScheduler = &sch.BaseScheduler scheduler.CurrentScheduler = sch sch.defWorkflowConfig = []map[int]*StatusActionConfig{ map[int]*StatusActionConfig{ @@ -238,7 +246,9 @@ func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus, isPending globals.SugarLogger.Infof("OnOrderStatusChanged [运营2]订单orderID:%s可能被手动点击送达,会对程序状态产生不利影响,请通知门店不要这样操作!", status.VendorOrderID) } } - s.cancelOtherWaybills(savedOrderInfo, curWaybill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrOrderAlreadyFinished) + if (savedOrderInfo.order.DeliveryFlag & model.OrderDeliveryFlagMaskScheduleDisabled) == 0 { + s.cancelOtherWaybills(savedOrderInfo, curWaybill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrOrderAlreadyFinished) + } s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status)) } } else if status.LockStatus != model.OrderStatusUnknown { @@ -262,129 +272,131 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo // s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(model.Order2Status(order))) // return nil // } - if bill.Status == model.WaybillStatusNew { - s.addWaybill2Map(savedOrderInfo, bill) - if !isPending { - if order.Status > model.OrderStatusEndBegin { - s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - } else if order.WaybillVendorID != model.VendorIDUnknown { - globals.SugarLogger.Debugf("OnWaybillStatusChanged multiple waybill created, bill:%v", bill) - if !s.isBillCandidate(order, bill) && bill.WaybillVendorID != order.VendorID { - s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - } else if bill.WaybillVendorID == order.VendorID && order.WaybillVendorID != order.VendorID { - globals.SugarLogger.Warnf("OnWaybillStatusChanged bill:%v purchase platform bill came later than others, strange!!!", bill) - } - } - } - // 只有购物平台的新运单消息才会启动抢单TIMER - if bill.OrderVendorID == bill.WaybillVendorID { - s.resetTimer(savedOrderInfo, bill, isPending) - } - } else { - switch bill.Status { - case model.WaybillStatusAccepted: - s.resetTimer(savedOrderInfo, bill, isPending) + if (order.DeliveryFlag & model.OrderDeliveryFlagMaskScheduleDisabled) == 0 { // 如果被停止调度,整个不动作 + if bill.Status == model.WaybillStatusNew { + s.addWaybill2Map(savedOrderInfo, bill) if !isPending { - // todo 购买平台的运单,优先级最高,但这样写也可能带来问题,即在这个时间,因为之前3方已经接单,已经发出了转自送请求(而且可能成功了),所以加个isSwitched2SelfDelivery状态判断 - if order.WaybillVendorID == model.VendorIDUnknown || - (order.VendorID == bill.WaybillVendorID && order.VendorID != order.WaybillVendorID && !savedOrderInfo.isSwitched2SelfDelivery) { - if order.WaybillVendorID != model.VendorIDUnknown { - // 进到这里的原因是,在这个时间点,购物平台物流已经抢单(但抢单消息还没有被收到)(比如:818810379000941) - globals.SugarLogger.Infof("OnWaybillStatusChanged orderID:%s purchase platform waybill arrvied later, may case problem", order.VendorOrderID) - } - s.updateOrderByBill(order, bill, false) - s.cancelOtherWaybills(savedOrderInfo, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - if bill.WaybillVendorID != bill.OrderVendorID { - if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { - s.SelfDeliverDelievering(savedOrderInfo.order, "") - } else { - s.swtich2SelfDeliverWithRetry(savedOrderInfo, bill, 2, 10*time.Second) - } - } - if !isPending { - weixinmsg.NotifyWaybillStatus(bill, order) - } - } else if !s.isBillCandidate(order, bill) && bill.WaybillVendorID != order.VendorID { - // 发生这种情况的原因就是两个接单事件几乎同时到达(来不及取消),也算正常 + if order.Status > model.OrderStatusEndBegin { s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - globals.SugarLogger.Infof("OnWaybillStatusChanged Accepted orderID:%s got multiple bill:%v", order.VendorOrderID, bill) + } else if order.WaybillVendorID != model.VendorIDUnknown { + globals.SugarLogger.Debugf("OnWaybillStatusChanged multiple waybill created, bill:%v", bill) + if !s.isBillCandidate(order, bill) && bill.WaybillVendorID != order.VendorID { + s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + } else if bill.WaybillVendorID == order.VendorID && order.WaybillVendorID != order.VendorID { + globals.SugarLogger.Warnf("OnWaybillStatusChanged bill:%v purchase platform bill came later than others, strange!!!", bill) + } } } - case model.WaybillStatusAcceptCanceled: - if s.isBillCandidate(order, bill) { + // 只有购物平台的新运单消息才会启动抢单TIMER + if bill.OrderVendorID == bill.WaybillVendorID { + s.resetTimer(savedOrderInfo, bill, isPending) + } + } else { + switch bill.Status { + case model.WaybillStatusAccepted: s.resetTimer(savedOrderInfo, bill, isPending) if !isPending { - bill.WaybillVendorID = model.VendorIDUnknown - s.updateOrderByBill(order, bill, false) + // todo 购买平台的运单,优先级最高,但这样写也可能带来问题,即在这个时间,因为之前3方已经接单,已经发出了转自送请求(而且可能成功了),所以加个状态判断 + if order.WaybillVendorID == model.VendorIDUnknown || + (order.VendorID == bill.WaybillVendorID && order.VendorID != order.WaybillVendorID && (order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled) == 0) { + if order.WaybillVendorID != model.VendorIDUnknown { + // 进到这里的原因是,在这个时间点,购物平台物流已经抢单(但抢单消息还没有被收到)(比如:818810379000941) + globals.SugarLogger.Infof("OnWaybillStatusChanged orderID:%s purchase platform waybill arrvied later, may case problem", order.VendorOrderID) + } + s.updateOrderByBill(order, bill, false) + s.cancelOtherWaybills(savedOrderInfo, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + if bill.WaybillVendorID != bill.OrderVendorID { + if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { + s.SelfDeliverDelievering(savedOrderInfo.order, "") + } else { + s.swtich2SelfDeliverWithRetry(savedOrderInfo, bill, 2, 10*time.Second) + } + } + if !isPending { + weixinmsg.NotifyWaybillStatus(bill, order) + } + } else if !s.isBillCandidate(order, bill) && bill.WaybillVendorID != order.VendorID { + // 发生这种情况的原因就是两个接单事件几乎同时到达(来不及取消),也算正常 + s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + globals.SugarLogger.Infof("OnWaybillStatusChanged Accepted orderID:%s got multiple bill:%v", order.VendorOrderID, bill) + } + } + case model.WaybillStatusAcceptCanceled: + if s.isBillCandidate(order, bill) { + s.resetTimer(savedOrderInfo, bill, isPending) + if !isPending { + bill.WaybillVendorID = model.VendorIDUnknown + s.updateOrderByBill(order, bill, false) - s.createWaybillOn3rdProviders(savedOrderInfo, bill) + s.createWaybillOn3rdProviders(savedOrderInfo, bill) + } + } else if order.WaybillVendorID != model.VendorIDUnknown { + s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + globals.SugarLogger.Warnf("OnWaybillStatusChanged AcceptCanceled orderID:%s got multiple bill:%v, order details:%v", order.VendorOrderID, bill, order) } - } else if order.WaybillVendorID != model.VendorIDUnknown { - s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - globals.SugarLogger.Warnf("OnWaybillStatusChanged AcceptCanceled orderID:%s got multiple bill:%v, order details:%v", order.VendorOrderID, bill, order) - } - case model.WaybillStatusCourierArrived: // do nothing - s.resetTimer(savedOrderInfo, bill, isPending) - if s.isBillCandidate(order, bill) { - } else { - // s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - globals.SugarLogger.Infof("OnWaybillStatusChanged CourierArrived order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) - } - case model.WaybillStatusFailed: // todo WaybillStatusFailed理解成订单整个失败了,不需要再尝试创建运单了,注意这里应该加个zabbix日志的报警 - s.removeWaybillFromMap(savedOrderInfo, bill) - if s.isBillCandidate(order, bill) { + case model.WaybillStatusCourierArrived: // do nothing s.resetTimer(savedOrderInfo, bill, isPending) - if !isPending { - globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill) - bill.WaybillVendorID = model.VendorIDUnknown - s.updateOrderByBill(order, bill, false) + if s.isBillCandidate(order, bill) { + } else { + // s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + globals.SugarLogger.Infof("OnWaybillStatusChanged CourierArrived order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) } - } else { - // 创建运单失败时,可能到这里来(比如:818874313000121) - globals.SugarLogger.Infof("OnWaybillStatusChanged Failed bill:%v shouldn't got here, order details:%v", bill, order) - } - case model.WaybillStatusCanceled: - s.removeWaybillFromMap(savedOrderInfo, bill) - if s.isBillCandidate(order, bill) || order.WaybillVendorID == model.VendorIDUnknown { - s.resetTimer(savedOrderInfo, bill, isPending) - if !isPending { - if order.WaybillVendorID != model.VendorIDUnknown { + case model.WaybillStatusFailed: // todo WaybillStatusFailed理解成订单整个失败了,不需要再尝试创建运单了,注意这里应该加个zabbix日志的报警 + s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID) + if s.isBillCandidate(order, bill) { + s.resetTimer(savedOrderInfo, bill, isPending) + if !isPending { + globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill) bill.WaybillVendorID = model.VendorIDUnknown s.updateOrderByBill(order, bill, false) } - if bill.WaybillVendorID != order.VendorID { // 3方的运单取消才会重新发起创建3方订单,购物平台的运单取消后,它本身还会再创建新运单(NewWabill事件有相应TIMER)),至少京东是这样的,暂时按京东的行为来 - s.createWaybillOn3rdProviders(savedOrderInfo, nil) + } else { + // 创建运单失败时,可能到这里来(比如:818874313000121) + globals.SugarLogger.Infof("OnWaybillStatusChanged Failed bill:%v shouldn't got here, order details:%v", bill, order) + } + case model.WaybillStatusCanceled: + s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID) + if s.isBillCandidate(order, bill) || order.WaybillVendorID == model.VendorIDUnknown { + s.resetTimer(savedOrderInfo, bill, isPending) + if !isPending { + if order.WaybillVendorID != model.VendorIDUnknown { + bill.WaybillVendorID = model.VendorIDUnknown + s.updateOrderByBill(order, bill, false) + } + if bill.WaybillVendorID != order.VendorID { // 3方的运单取消才会重新发起创建3方订单,购物平台的运单取消后,它本身还会再创建新运单(NewWabill事件有相应TIMER)),至少京东是这样的,暂时按京东的行为来 + s.createWaybillOn3rdProviders(savedOrderInfo, nil) + } } } - } - case model.WaybillStatusDelivering: - s.resetTimer(savedOrderInfo, bill, isPending) - if s.isBillCandidate(order, bill) { - // do nothing - } else { - // s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - globals.SugarLogger.Infof("OnWaybillStatusChanged Delivering order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) - } - case model.WaybillStatusDelivered: - s.resetTimer(savedOrderInfo, bill, isPending) - s.removeWaybillFromMap(savedOrderInfo, bill) - if order.VendorID != bill.WaybillVendorID && !isPending { - if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { - s.SelfDeliverDelievered(order, "") + case model.WaybillStatusDelivering: + s.resetTimer(savedOrderInfo, bill, isPending) + if s.isBillCandidate(order, bill) { + // do nothing } else { - s.Swtich2SelfDelivered(order, "") + // s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + globals.SugarLogger.Infof("OnWaybillStatusChanged Delivering order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) } - } - if !s.isBillCandidate(order, bill) { - // 一般只会消息乱序才会到这里,即新订单消息在运单接单消息后到达 - // 典型的一个:1223633660228537567 - globals.SugarLogger.Infof("OnWaybillStatusChanged Delivered order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) - if order.WaybillVendorID == model.VendorIDUnknown { - s.updateOrderByBill(order, bill, false) + case model.WaybillStatusDelivered: + s.resetTimer(savedOrderInfo, bill, isPending) + s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID) + if order.VendorID != bill.WaybillVendorID && !isPending { + if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { + s.SelfDeliverDelievered(order, "") + } else { + s.Swtich2SelfDelivered(order, "") + } + } + if !s.isBillCandidate(order, bill) { + // 一般只会消息乱序才会到这里,即新订单消息在运单接单消息后到达 + // 典型的一个:1223633660228537567 + globals.SugarLogger.Infof("OnWaybillStatusChanged Delivered order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill) + if order.WaybillVendorID == model.VendorIDUnknown { + s.updateOrderByBill(order, bill, false) + } + } + if !isPending { + weixinmsg.NotifyWaybillStatus(bill, order) } - } - if !isPending { - weixinmsg.NotifyWaybillStatus(bill, order) } } } @@ -401,9 +413,9 @@ func (s *DefScheduler) addWaybill2Map(savedOrderInfo *WatchOrderInfo, bill *mode savedOrderInfo.waybills[bill.WaybillVendorID] = bill } -func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { - if _, ok := savedOrderInfo.waybills[bill.WaybillVendorID]; ok { - delete(savedOrderInfo.waybills, bill.WaybillVendorID) +func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, waybillVendorID int) { + if _, ok := savedOrderInfo.waybills[waybillVendorID]; ok { + delete(savedOrderInfo.waybills, waybillVendorID) } } @@ -411,7 +423,7 @@ func (s *DefScheduler) createWaybillOn3rdProviders(savedOrderInfo *WatchOrderInf order := savedOrderInfo.order globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, status:%d, excludeBill:%v", order.VendorOrderID, order.Status, excludeBill) if order.LockStatus == model.OrderStatusUnknown && order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin { // 订单在配送中被取消时就是配送中状态 - if savedOrderInfo.isNeed3rdDelivery { + if (order.DeliveryFlag & model.OrderDeliveryFlagMaskScheduleDisabled) == 0 { if savedOrderInfo.retryCount <= maxWaybillRetryCount { successCount := 0 for _, vendorID := range savedOrderInfo.supported3rdCarriers { @@ -466,18 +478,29 @@ func (s *DefScheduler) createWaybillOn3rdProviders(savedOrderInfo *WatchOrderInf func (s *DefScheduler) cancelOtherWaybills(savedOrderInfo *WatchOrderInfo, bill2Keep *model.Waybill, cancelReasonID int, cancelReason string) (err error) { globals.SugarLogger.Debugf("cancelOtherWaybills, orderID:%s, bill:%v", savedOrderInfo.order.VendorOrderID, bill2Keep) + toBeDeleted := []*model.Waybill{} for _, v := range savedOrderInfo.waybills { if (v.OrderVendorID != v.WaybillVendorID) && (bill2Keep == nil || !(v.WaybillVendorID == bill2Keep.WaybillVendorID && v.VendorWaybillID == bill2Keep.VendorWaybillID)) { - s.CancelWaybill(v, cancelReasonID, cancelReason) + err2 := s.CancelWaybill(v, cancelReasonID, cancelReason) + if err2 == nil { + toBeDeleted = append(toBeDeleted, v) + } + // 至少返回一个错误 + if err == nil && err2 != nil { + err = err2 + } } } - return nil + for _, v := range toBeDeleted { + s.removeWaybillFromMap(savedOrderInfo, v.WaybillVendorID) + } + return err } func (s *DefScheduler) swtich2SelfDeliverWithRetry(savedOrderInfo *WatchOrderInfo, bill *model.Waybill, retryCount int, duration time.Duration) { order := savedOrderInfo.order globals.SugarLogger.Debugf("swtich2SelfDeliverWithRetry orderID:%s", order.VendorOrderID) - if !savedOrderInfo.isSwitched2SelfDelivery { + if (order.DeliveryFlag & model.OrderDeliveryFlagMaskPurcahseDisabled) == 0 { if order.WaybillVendorID != order.VendorID { if err := s.Swtich2SelfDeliver(order, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation { globals.SugarLogger.Infof("swtich2SelfDeliverWithRetry failed, bill:%v, err:%v", bill, err) @@ -507,7 +530,8 @@ func (s *DefScheduler) swtich2SelfDeliverWithRetry(savedOrderInfo *WatchOrderInf } } } else { - savedOrderInfo.isSwitched2SelfDelivery = true + s.removeWaybillFromMap(savedOrderInfo, order.VendorID) + partner.CurOrderManager.UpdateOrderStatusAndFlag(order) } } else { // 进到这里的原因是,在这个时间点,购物平台物流已经抢单(但抢单消息还没有被收到),所以转自送会失败 (比如:818810379000941),更好的做法应该是判断Swtich2SelfDeliver的返回值,这种情况下就不得试了 diff --git a/business/jxcallback/scheduler/defsch/defsch_ext.go b/business/jxcallback/scheduler/defsch/defsch_ext.go new file mode 100644 index 000000000..fb766c585 --- /dev/null +++ b/business/jxcallback/scheduler/defsch/defsch_ext.go @@ -0,0 +1,55 @@ +package defsch + +import ( + "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" +) + +func (s *DefScheduler) SelfDeliveringAndUpdateStatus(vendorOrderID string, vendorID int, userName string) (err error) { + globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) + status := &model.OrderStatus{ + VendorOrderID: vendorOrderID, + VendorID: vendorID, + } + savedOrderInfo := s.loadSavedOrderFromMap(status, false) + if savedOrderInfo != nil { + order := savedOrderInfo.order + err = s.cancelOtherWaybills(savedOrderInfo, nil, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive) + if err == nil { + if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { + if order.Status <= model.OrderStatusFinishedPickup { + err = s.SelfDeliverDelievering(order, "") + } + } else { + if order.Status <= model.OrderStatusFinishedPickup { + err = s.Swtich2SelfDeliver(order, userName) + } else if order.VendorID == order.WaybillVendorID { // 状态为配送中,且是购物平台运单,不能转自送了 + err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation + } + } + } + if err == nil { + order.Status = model.OrderStatusDelivering + order.DeliveryFlag |= model.OrderDeliveryFlagMaskScheduleDisabled | model.OrderDeliveryFlagMaskPurcahseDisabled + if err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order); err == nil { + s.stopTimer(savedOrderInfo) + globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus orderID:%s userName:%s successfully", vendorOrderID, userName) + return err + } + } + } else { + err = scheduler.ErrCanNotFindOrder + } + globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus orderID:%s userName:%s error:%v", vendorOrderID, userName, err) + return err +} + +func (s *DefScheduler) SelfDeliveringAndUpdateStatusExt(vendorOrderID string, vendorID int, userName string) (err error) { + jxutils.CallMsgHandler(func() { + err = s.SelfDeliveringAndUpdateStatus(vendorOrderID, vendorID, userName) + }, jxutils.ComposeUniversalOrderID(vendorOrderID, vendorID)) + return err +} diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 7c1dd1a7d..b25277b10 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -79,20 +79,22 @@ func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) { } func SendMsgToStore(storeID int, templateID, downloadURL string, data interface{}) (err error) { - openIDs := GetWeixinOpenIDsFromStoreID(storeID) - successCount := 0 - for _, openID := range openIDs { - if err2 := api.WeixinAPI.MessageTemplateSend(openID, templateID, downloadURL, nil, data); err2 == nil { - successCount++ - } else { - err = err2 + if globals.ReallySendWeixinMsg { + openIDs := GetWeixinOpenIDsFromStoreID(storeID) + successCount := 0 + for _, openID := range openIDs { + if err2 := api.WeixinAPI.MessageTemplateSend(openID, templateID, downloadURL, nil, data); err2 == nil { + successCount++ + } else { + err = err2 + } + } + if successCount > 0 { + err = nil // 只要成功一个都当成成功 + } + if err != nil { + globals.SugarLogger.Debugf("SendMsgToStore all failed storeID:%d, templateID:%s, error:%v", storeID, templateID, err) } - } - if successCount > 0 { - err = nil // 只要成功一个都当成成功 - } - if err != nil { - globals.SugarLogger.Debugf("SendMsgToStore all failed storeID:%d, templateID:%s, error:%v", storeID, templateID, err) } return err } diff --git a/business/model/const.go b/business/model/const.go index cdd7b9599..6b06c8122 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -135,3 +135,8 @@ const ( JdPlatformFeeRate = 10 MtPlatformFeeRate = 10 ) + +const ( + OrderDeliveryFlagMaskScheduleDisabled = 1 // 禁止三方配送调度 + OrderDeliveryFlagMaskPurcahseDisabled = 2 // 购物平台已不配送(一般为门店配送类型本身为自配送,或已经转自配送) +) diff --git a/business/model/order.go b/business/model/order.go index 1ed109328..f371963af 100644 --- a/business/model/order.go +++ b/business/model/order.go @@ -37,8 +37,9 @@ type GoodsOrder struct { CancelApplyReason string `orm:"size(255)" json:"-"` // ""表示没有申请,不为null表示用户正在取消申请 VendorWaybillID string `orm:"column(vendor_waybill_id);size(48)" json:"vendorWaybillID"` WaybillVendorID int `orm:"column(waybill_vendor_id)" json:"waybillVendorID"` // 表示当前承运商,-1表示还没有安排 - DuplicatedCount int // 重复新订单消息数,这个一般不是由于消息重发造成的(消息重发由OrderStatus过滤),一般是业务逻辑造成的 - OrderCreatedAt time.Time `orm:"type(datetime);index" json:"orderCreatedAt"` // 这里记录的是订单生效时间,即用户支付完成(货到付款即为下单时间) + DeliveryFlag int8 `json:"deliveryFlag"` // 第1位为1表示禁止调度器调度三方配送 + DuplicatedCount int `json:"-"` // 重复新订单消息数,这个一般不是由于消息重发造成的(消息重发由OrderStatus过滤),一般是业务逻辑造成的 + OrderCreatedAt time.Time `orm:"type(datetime);index" json:"orderCreatedAt"` // 这里记录的是订单生效时间,即用户支付完成(货到付款即为下单时间) OrderFinishedAt time.Time `orm:"type(datetime)" json:"orderFinishedAt"` StatusTime time.Time `orm:"type(datetime)" json:"-"` // last status time ModelTimeInfo `json:"-"` diff --git a/business/partner/partner.go b/business/partner/partner.go index 29226f021..91f8050cc 100644 --- a/business/partner/partner.go +++ b/business/partner/partner.go @@ -32,7 +32,7 @@ type IOrderManager interface { LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) UpdateWaybillVendorID(bill *model.Waybill, revertStatus bool) (err error) - UpdateOrderStatusDirectly(order *model.GoodsOrder) (err error) + UpdateOrderStatusAndFlag(order *model.GoodsOrder) (err error) } type IPurchasePlatformHandler interface { diff --git a/controllers/jx_order.go b/controllers/jx_order.go index e830fbddb..b2f9c8515 100644 --- a/controllers/jx_order.go +++ b/controllers/jx_order.go @@ -3,7 +3,7 @@ package controllers import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" - "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/basesch" + "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/model" "github.com/astaxie/beego" @@ -78,7 +78,7 @@ func (c *OrderController) orderOperate(handler func(vendorOrderID string, vendor // @router /FinishedPickup [post] func (c *OrderController) FinishedPickup() { c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { - return nil, basesch.FixedBaseScheduler.PickupGoodsAndUpdateStatus(vendorOrderID, vendorID, userName) + return nil, defsch.FixedScheduler.PickupGoodsAndUpdateStatus(vendorOrderID, vendorID, userName) }) } @@ -92,7 +92,7 @@ func (c *OrderController) FinishedPickup() { // @router /SelfDelivering [post] func (c *OrderController) SelfDelivering() { c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { - return nil, basesch.FixedBaseScheduler.SelfDeliveringAndUpdateStatus(vendorOrderID, vendorID, userName) + return nil, defsch.FixedScheduler.SelfDeliveringAndUpdateStatusExt(vendorOrderID, vendorID, userName) }) } @@ -106,7 +106,7 @@ func (c *OrderController) SelfDelivering() { // @router /SelfDelivered [post] func (c *OrderController) SelfDelivered() { c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { - return nil, basesch.FixedBaseScheduler.SelfDeliveredAndUpdateStatus(vendorOrderID, vendorID, userName) + return nil, defsch.FixedScheduler.SelfDeliveredAndUpdateStatus(vendorOrderID, vendorID, userName) }) } @@ -120,7 +120,7 @@ func (c *OrderController) SelfDelivered() { // @router /CreateWaybillOnProviders [post] func (c *OrderController) CreateWaybillOnProviders() { c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { - return basesch.FixedBaseScheduler.CreateWaybillOnProviders(vendorOrderID, vendorID, userName) + return defsch.FixedScheduler.CreateWaybillOnProviders(vendorOrderID, vendorID, userName) }) } diff --git a/globals/globals.go b/globals/globals.go index 570cd3c33..689b3a414 100644 --- a/globals/globals.go +++ b/globals/globals.go @@ -15,6 +15,7 @@ const ( var ( GenerateLegacyJxOrder bool ReallyCallPlatformAPI bool + ReallySendWeixinMsg bool SugarLogger *zap.SugaredLogger @@ -38,6 +39,7 @@ func init() { } func Init() { + ReallySendWeixinMsg = beego.BConfig.RunMode == "prod" ReallyCallPlatformAPI = true GenerateLegacyJxOrder = beego.AppConfig.DefaultBool("generateLegacyJxOrder", false)