- order.DeliveryFlag added.

This commit is contained in:
gazebo
2018-08-24 10:03:34 +08:00
parent 46bbb7418c
commit bb049bb28b
12 changed files with 238 additions and 175 deletions

View File

@@ -342,12 +342,12 @@ func (c *OrderManager) LoadOrder(vendorOrderID string, vendorID int) (order *mod
return order, err return order, err
} }
func (c *OrderManager) UpdateOrderStatusDirectly(order *model.GoodsOrder) (err error) { func (c *OrderManager) UpdateOrderStatusAndFlag(order *model.GoodsOrder) (err error) {
db := orm.NewOrm() db := orm.NewOrm()
utils.CallFuncLogError(func() error { utils.CallFuncLogError(func() error {
_, err = db.Update(order, "Status") _, err = db.Update(order, "Status", "DeliveryFlag")
return err return err
}, "UpdateOrderStatusDirectly orderID:%s failed with error:%v", order.VendorOrderID, err) }, "UpdateOrderStatusAndFlag orderID:%s failed with error:%v", order.VendorOrderID, err)
return err return err
} }

View File

@@ -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) = ? WHERE IF(t1.jx_store_id != 0, t1.jx_store_id, t1.store_id) = ?
AND t1.order_created_at >= ? AND t1.order_created_at >= ?
AND t1.Status >= ? AND t1.Status <= ? AND t1.Status >= ? AND t1.Status <= ?
ORDER BY t1.order_created_at ORDER BY t1.status, t1.order_created_at
LIMIT ? OFFSET ? LIMIT ? OFFSET ?
`, storeID, time.Now().Add(-time.Duration(lastHours)*time.Hour), fromStatus, toStatus, pageSize, offset).QueryRows(&orders) `, storeID, time.Now().Add(-time.Duration(lastHours)*time.Hour), fromStatus, toStatus, pageSize, offset).QueryRows(&orders)
if err == nil { if err == nil {

View File

@@ -16,10 +16,6 @@ type BaseScheduler struct {
IsReallyCallPlatformAPI bool IsReallyCallPlatformAPI bool
} }
var (
FixedBaseScheduler *BaseScheduler
)
func (c *BaseScheduler) Init() { func (c *BaseScheduler) Init() {
c.PurchasePlatformHandlers = make(map[int]partner.IPurchasePlatformHandler) c.PurchasePlatformHandlers = make(map[int]partner.IPurchasePlatformHandler)
c.DeliveryPlatformHandlers = make(map[int]*scheduler.DeliveryPlatformHandlerInfo) 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) }, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
if err == nil { // 因为有些平台转自送后,不会再发送订单在配送中消息过来,所以成功后就强制设置状态为配送中 if err == nil { // 因为有些平台转自送后,不会再发送订单在配送中消息过来,所以成功后就强制设置状态为配送中
order.Status = model.OrderStatusDelivering order.Status = model.OrderStatusDelivering
order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled
} }
} }
} else { } else {

View File

@@ -30,29 +30,6 @@ func (c *BaseScheduler) CreateWaybillOnProviders(vendorOrderID string, vendorID
return nil, err 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) { func (c *BaseScheduler) SelfDeliveredAndUpdateStatus(vendorOrderID string, vendorID int, userName string) (err error) {
globals.SugarLogger.Infof("SelfDeliveredAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) globals.SugarLogger.Infof("SelfDeliveredAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName)
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID)
@@ -64,7 +41,7 @@ func (c *BaseScheduler) SelfDeliveredAndUpdateStatus(vendorOrderID string, vendo
} }
if err == nil { if err == nil {
order.Status = model.OrderStatusDelivered 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) globals.SugarLogger.Infof("SelfDeliveredAndUpdateStatus orderID:%s userName:%s successfully", vendorOrderID, userName)
return err return err
} }
@@ -81,7 +58,7 @@ func (c *BaseScheduler) PickupGoodsAndUpdateStatus(vendorOrderID string, vendorI
err = c.PickupGoods(order, userName) err = c.PickupGoods(order, userName)
if err == nil { if err == nil {
order.Status = model.OrderStatusFinishedPickup 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) globals.SugarLogger.Infof("PickupGoodsAndUpdateStatus orderID:%s userName:%s successfully", vendorOrderID, userName)
return err return err
} }

View File

@@ -43,12 +43,14 @@ var (
ErrAddFeeExceeded = errors.New("配送超过基准价太多") ErrAddFeeExceeded = errors.New("配送超过基准价太多")
) )
var (
FixedScheduler *DefScheduler
)
type WatchOrderInfo struct { type WatchOrderInfo struct {
autoPickupTimeoutMinute int // 0表示禁用1表示用缺省值time2AutoPickupMin其它表示分钟数 autoPickupTimeoutMinute int // 0表示禁用1表示用缺省值time2AutoPickupMin其它表示分钟数
storeDeliveryType int storeDeliveryType int
isNeed3rdDelivery bool
supported3rdCarriers []int supported3rdCarriers []int
isSwitched2SelfDelivery bool
order *model.GoodsOrder // order里的信息是保持更新的 order *model.GoodsOrder // order里的信息是保持更新的
waybills map[int]*model.Waybill // 这个waybills里的状态信息是不真实的只使用id相关的信息 waybills map[int]*model.Waybill // 这个waybills里的状态信息是不真实的只使用id相关的信息
@@ -76,7 +78,6 @@ type DefScheduler struct {
func NewWatchOrderInfo(order *model.GoodsOrder) (retVal *WatchOrderInfo) { func NewWatchOrderInfo(order *model.GoodsOrder) (retVal *WatchOrderInfo) {
retVal = &WatchOrderInfo{ retVal = &WatchOrderInfo{
autoPickupTimeoutMinute: 1, autoPickupTimeoutMinute: 1,
isNeed3rdDelivery: false,
storeDeliveryType: scheduler.StoreDeliveryTypeCrowdSourcing, storeDeliveryType: scheduler.StoreDeliveryTypeCrowdSourcing,
waybills: map[int]*model.Waybill{}, waybills: map[int]*model.Waybill{},
supported3rdCarriers: []int{}, supported3rdCarriers: []int{},
@@ -111,12 +112,16 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e
} else if order.VendorID == model.VendorIDJD { } else if order.VendorID == model.VendorIDJD {
s.storeDeliveryType = int(storefeature.JdDeliveryType) s.storeDeliveryType = int(storefeature.JdDeliveryType)
} }
if s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore {
order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled
}
isNeedSchedule := false
if (s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore) || if (s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore) ||
(order.VendorID == model.VendorIDJD && storefeature.JdCompetition != 0) || (order.VendorID == model.VendorIDJD && storefeature.JdCompetition != 0) ||
(order.VendorID == model.VendorIDELM && storefeature.ElmCompetition != 0) { (order.VendorID == model.VendorIDELM && storefeature.ElmCompetition != 0) {
s.isNeed3rdDelivery = true isNeedSchedule = true
} }
if s.isNeed3rdDelivery { if isNeedSchedule {
if storefeature.SupportMtps != 0 { if storefeature.SupportMtps != 0 {
s.supported3rdCarriers = append(s.supported3rdCarriers, model.VendorIDMTPS) 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) s.supported3rdCarriers = append(s.supported3rdCarriers, model.VendorIDFengNiao)
} }
if len(s.supported3rdCarriers) == 0 { if len(s.supported3rdCarriers) == 0 {
s.isNeed3rdDelivery = false isNeedSchedule = false
globals.SugarLogger.Infof("updateOrderStoreFeature orderID:%s no at least one carrier supported", order.VendorOrderID) globals.SugarLogger.Infof("updateOrderStoreFeature orderID:%s no at least one carrier supported", order.VendorOrderID)
} }
} }
if !isNeedSchedule {
order.DeliveryFlag |= model.OrderDeliveryFlagMaskScheduleDisabled
}
} }
return err return err
}, "updateOrderStoreFeature") }, "updateOrderStoreFeature")
@@ -140,9 +148,9 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e
func init() { func init() {
sch := &DefScheduler{} sch := &DefScheduler{}
FixedScheduler = sch
sch.IsReallyCallPlatformAPI = globals.ReallyCallPlatformAPI sch.IsReallyCallPlatformAPI = globals.ReallyCallPlatformAPI
sch.Init() sch.Init()
basesch.FixedBaseScheduler = &sch.BaseScheduler
scheduler.CurrentScheduler = sch scheduler.CurrentScheduler = sch
sch.defWorkflowConfig = []map[int]*StatusActionConfig{ sch.defWorkflowConfig = []map[int]*StatusActionConfig{
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) 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)) s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status))
} }
} else if status.LockStatus != model.OrderStatusUnknown { } 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))) // s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(model.Order2Status(order)))
// return nil // return nil
// } // }
if bill.Status == model.WaybillStatusNew { if (order.DeliveryFlag & model.OrderDeliveryFlagMaskScheduleDisabled) == 0 { // 如果被停止调度,整个不动作
s.addWaybill2Map(savedOrderInfo, bill) if bill.Status == model.WaybillStatusNew {
if !isPending { s.addWaybill2Map(savedOrderInfo, bill)
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 !isPending { if !isPending {
// todo 购买平台的运单优先级最高但这样写也可能带来问题即在这个时间因为之前3方已经接单已经发出了转自送请求而且可能成功了所以加个isSwitched2SelfDelivery状态判断 if order.Status > model.OrderStatusEndBegin {
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 {
// 发生这种情况的原因就是两个接单事件几乎同时到达(来不及取消),也算正常
s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) 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: // 只有购物平台的新运单消息才会启动抢单TIMER
if s.isBillCandidate(order, bill) { if bill.OrderVendorID == bill.WaybillVendorID {
s.resetTimer(savedOrderInfo, bill, isPending)
}
} else {
switch bill.Status {
case model.WaybillStatusAccepted:
s.resetTimer(savedOrderInfo, bill, isPending) s.resetTimer(savedOrderInfo, bill, isPending)
if !isPending { if !isPending {
bill.WaybillVendorID = model.VendorIDUnknown // todo 购买平台的运单优先级最高但这样写也可能带来问题即在这个时间因为之前3方已经接单已经发出了转自送请求而且可能成功了所以加个状态判断
s.updateOrderByBill(order, bill, false) 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 { case model.WaybillStatusCourierArrived: // do nothing
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) {
s.resetTimer(savedOrderInfo, bill, isPending) s.resetTimer(savedOrderInfo, bill, isPending)
if !isPending { if s.isBillCandidate(order, bill) {
globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill) } else {
bill.WaybillVendorID = model.VendorIDUnknown // s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
s.updateOrderByBill(order, bill, false) 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 { case model.WaybillStatusFailed: // todo WaybillStatusFailed理解成订单整个失败了不需要再尝试创建运单了注意这里应该加个zabbix日志的报警
// 创建运单失败时可能到这里来比如818874313000121 s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID)
globals.SugarLogger.Infof("OnWaybillStatusChanged Failed bill:%v shouldn't got here, order details:%v", bill, order) if s.isBillCandidate(order, bill) {
} s.resetTimer(savedOrderInfo, bill, isPending)
case model.WaybillStatusCanceled: if !isPending {
s.removeWaybillFromMap(savedOrderInfo, bill) globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill)
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 bill.WaybillVendorID = model.VendorIDUnknown
s.updateOrderByBill(order, bill, false) s.updateOrderByBill(order, bill, false)
} }
if bill.WaybillVendorID != order.VendorID { // 3方的运单取消才会重新发起创建3方订单购物平台的运单取消后它本身还会再创建新运单(NewWabill事件有相应TIMER)),至少京东是这样的,暂时按京东的行为来 } else {
s.createWaybillOn3rdProviders(savedOrderInfo, nil) // 创建运单失败时可能到这里来比如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:
case model.WaybillStatusDelivering: s.resetTimer(savedOrderInfo, bill, isPending)
s.resetTimer(savedOrderInfo, bill, isPending) if s.isBillCandidate(order, bill) {
if s.isBillCandidate(order, bill) { // do nothing
// 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, "")
} else { } 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)
} }
} case model.WaybillStatusDelivered:
if !s.isBillCandidate(order, bill) { s.resetTimer(savedOrderInfo, bill, isPending)
// 一般只会消息乱序才会到这里,即新订单消息在运单接单消息后到达 s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID)
// 典型的一个1223633660228537567 if order.VendorID != bill.WaybillVendorID && !isPending {
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 savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore {
if order.WaybillVendorID == model.VendorIDUnknown { s.SelfDeliverDelievered(order, "")
s.updateOrderByBill(order, bill, false) } 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 savedOrderInfo.waybills[bill.WaybillVendorID] = bill
} }
func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, waybillVendorID int) {
if _, ok := savedOrderInfo.waybills[bill.WaybillVendorID]; ok { if _, ok := savedOrderInfo.waybills[waybillVendorID]; ok {
delete(savedOrderInfo.waybills, bill.WaybillVendorID) delete(savedOrderInfo.waybills, waybillVendorID)
} }
} }
@@ -411,7 +423,7 @@ func (s *DefScheduler) createWaybillOn3rdProviders(savedOrderInfo *WatchOrderInf
order := savedOrderInfo.order order := savedOrderInfo.order
globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, status:%d, excludeBill:%v", order.VendorOrderID, order.Status, excludeBill) 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 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 { if savedOrderInfo.retryCount <= maxWaybillRetryCount {
successCount := 0 successCount := 0
for _, vendorID := range savedOrderInfo.supported3rdCarriers { 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) { 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) globals.SugarLogger.Debugf("cancelOtherWaybills, orderID:%s, bill:%v", savedOrderInfo.order.VendorOrderID, bill2Keep)
toBeDeleted := []*model.Waybill{}
for _, v := range savedOrderInfo.waybills { for _, v := range savedOrderInfo.waybills {
if (v.OrderVendorID != v.WaybillVendorID) && (bill2Keep == nil || !(v.WaybillVendorID == bill2Keep.WaybillVendorID && v.VendorWaybillID == bill2Keep.VendorWaybillID)) { 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) { func (s *DefScheduler) swtich2SelfDeliverWithRetry(savedOrderInfo *WatchOrderInfo, bill *model.Waybill, retryCount int, duration time.Duration) {
order := savedOrderInfo.order order := savedOrderInfo.order
globals.SugarLogger.Debugf("swtich2SelfDeliverWithRetry orderID:%s", order.VendorOrderID) globals.SugarLogger.Debugf("swtich2SelfDeliverWithRetry orderID:%s", order.VendorOrderID)
if !savedOrderInfo.isSwitched2SelfDelivery { if (order.DeliveryFlag & model.OrderDeliveryFlagMaskPurcahseDisabled) == 0 {
if order.WaybillVendorID != order.VendorID { if order.WaybillVendorID != order.VendorID {
if err := s.Swtich2SelfDeliver(order, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation { if err := s.Swtich2SelfDeliver(order, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation {
globals.SugarLogger.Infof("swtich2SelfDeliverWithRetry failed, bill:%v, err:%v", bill, err) globals.SugarLogger.Infof("swtich2SelfDeliverWithRetry failed, bill:%v, err:%v", bill, err)
@@ -507,7 +530,8 @@ func (s *DefScheduler) swtich2SelfDeliverWithRetry(savedOrderInfo *WatchOrderInf
} }
} }
} else { } else {
savedOrderInfo.isSwitched2SelfDelivery = true s.removeWaybillFromMap(savedOrderInfo, order.VendorID)
partner.CurOrderManager.UpdateOrderStatusAndFlag(order)
} }
} else { } else {
// 进到这里的原因是,在这个时间点,购物平台物流已经抢单(但抢单消息还没有被收到),所以转自送会失败 比如818810379000941更好的做法应该是判断Swtich2SelfDeliver的返回值这种情况下就不得试了 // 进到这里的原因是,在这个时间点,购物平台物流已经抢单(但抢单消息还没有被收到),所以转自送会失败 比如818810379000941更好的做法应该是判断Swtich2SelfDeliver的返回值这种情况下就不得试了

View File

@@ -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
}

View File

@@ -79,20 +79,22 @@ func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) {
} }
func SendMsgToStore(storeID int, templateID, downloadURL string, data interface{}) (err error) { func SendMsgToStore(storeID int, templateID, downloadURL string, data interface{}) (err error) {
openIDs := GetWeixinOpenIDsFromStoreID(storeID) if globals.ReallySendWeixinMsg {
successCount := 0 openIDs := GetWeixinOpenIDsFromStoreID(storeID)
for _, openID := range openIDs { successCount := 0
if err2 := api.WeixinAPI.MessageTemplateSend(openID, templateID, downloadURL, nil, data); err2 == nil { for _, openID := range openIDs {
successCount++ if err2 := api.WeixinAPI.MessageTemplateSend(openID, templateID, downloadURL, nil, data); err2 == nil {
} else { successCount++
err = err2 } 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 return err
} }

View File

@@ -135,3 +135,8 @@ const (
JdPlatformFeeRate = 10 JdPlatformFeeRate = 10
MtPlatformFeeRate = 10 MtPlatformFeeRate = 10
) )
const (
OrderDeliveryFlagMaskScheduleDisabled = 1 // 禁止三方配送调度
OrderDeliveryFlagMaskPurcahseDisabled = 2 // 购物平台已不配送(一般为门店配送类型本身为自配送,或已经转自配送)
)

View File

@@ -37,8 +37,9 @@ type GoodsOrder struct {
CancelApplyReason string `orm:"size(255)" json:"-"` // ""表示没有申请不为null表示用户正在取消申请 CancelApplyReason string `orm:"size(255)" json:"-"` // ""表示没有申请不为null表示用户正在取消申请
VendorWaybillID string `orm:"column(vendor_waybill_id);size(48)" json:"vendorWaybillID"` VendorWaybillID string `orm:"column(vendor_waybill_id);size(48)" json:"vendorWaybillID"`
WaybillVendorID int `orm:"column(waybill_vendor_id)" json:"waybillVendorID"` // 表示当前承运商,-1表示还没有安排 WaybillVendorID int `orm:"column(waybill_vendor_id)" json:"waybillVendorID"` // 表示当前承运商,-1表示还没有安排
DuplicatedCount int // 重复新订单消息数这个一般不是由于消息重发造成的消息重发由OrderStatus过滤一般是业务逻辑造成的 DeliveryFlag int8 `json:"deliveryFlag"` // 第1位为1表示禁止调度器调度三方配送
OrderCreatedAt time.Time `orm:"type(datetime);index" json:"orderCreatedAt"` // 这里记录的是订单生效时间,即用户支付完成(货到付款即为下单时间) DuplicatedCount int `json:"-"` // 重复新订单消息数这个一般不是由于消息重发造成的消息重发由OrderStatus过滤一般是业务逻辑造成的
OrderCreatedAt time.Time `orm:"type(datetime);index" json:"orderCreatedAt"` // 这里记录的是订单生效时间,即用户支付完成(货到付款即为下单时间)
OrderFinishedAt time.Time `orm:"type(datetime)" json:"orderFinishedAt"` OrderFinishedAt time.Time `orm:"type(datetime)" json:"orderFinishedAt"`
StatusTime time.Time `orm:"type(datetime)" json:"-"` // last status time StatusTime time.Time `orm:"type(datetime)" json:"-"` // last status time
ModelTimeInfo `json:"-"` ModelTimeInfo `json:"-"`

View File

@@ -32,7 +32,7 @@ type IOrderManager interface {
LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error)
UpdateWaybillVendorID(bill *model.Waybill, revertStatus bool) (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 { type IPurchasePlatformHandler interface {

View File

@@ -3,7 +3,7 @@ package controllers
import ( import (
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman" "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/jxutils"
"git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model"
"github.com/astaxie/beego" "github.com/astaxie/beego"
@@ -78,7 +78,7 @@ func (c *OrderController) orderOperate(handler func(vendorOrderID string, vendor
// @router /FinishedPickup [post] // @router /FinishedPickup [post]
func (c *OrderController) FinishedPickup() { func (c *OrderController) FinishedPickup() {
c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { 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] // @router /SelfDelivering [post]
func (c *OrderController) SelfDelivering() { func (c *OrderController) SelfDelivering() {
c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { 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] // @router /SelfDelivered [post]
func (c *OrderController) SelfDelivered() { func (c *OrderController) SelfDelivered() {
c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { 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] // @router /CreateWaybillOnProviders [post]
func (c *OrderController) CreateWaybillOnProviders() { func (c *OrderController) CreateWaybillOnProviders() {
c.orderOperate(func(vendorOrderID string, vendorID int, userName string) (interface{}, error) { 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)
}) })
} }

View File

@@ -15,6 +15,7 @@ const (
var ( var (
GenerateLegacyJxOrder bool GenerateLegacyJxOrder bool
ReallyCallPlatformAPI bool ReallyCallPlatformAPI bool
ReallySendWeixinMsg bool
SugarLogger *zap.SugaredLogger SugarLogger *zap.SugaredLogger
@@ -38,6 +39,7 @@ func init() {
} }
func Init() { func Init() {
ReallySendWeixinMsg = beego.BConfig.RunMode == "prod"
ReallyCallPlatformAPI = true ReallyCallPlatformAPI = true
GenerateLegacyJxOrder = beego.AppConfig.DefaultBool("generateLegacyJxOrder", false) GenerateLegacyJxOrder = beego.AppConfig.DefaultBool("generateLegacyJxOrder", false)