- fix weixin push msg bug.
- handle jd out-of-order msg.
This commit is contained in:
@@ -24,7 +24,7 @@ func NewOrderManager() *OrderController {
|
||||
func (c *OrderController) OnOrderNew(order *model.GoodsOrder) (err error) {
|
||||
db := orm.NewOrm()
|
||||
order.StatusTime = order.OrderCreatedAt
|
||||
isDuplicated, err := addOrderOrWaybillStatus(c.order2Status(order), db)
|
||||
isDuplicated, err := addOrderOrWaybillStatus(model.Order2Status(order), db)
|
||||
if err == nil && !isDuplicated {
|
||||
if err = c.saveOrder(order, false, db); err == nil {
|
||||
err = scheduler.CurrentScheduler.OnOrderNew(order)
|
||||
@@ -37,7 +37,7 @@ func (c *OrderController) OnOrderNew(order *model.GoodsOrder) (err error) {
|
||||
func (c *OrderController) OnOrderAdjust(order *model.GoodsOrder) (err error) {
|
||||
db := orm.NewOrm()
|
||||
order.StatusTime = order.OrderCreatedAt
|
||||
status := c.order2Status(order)
|
||||
status := model.Order2Status(order)
|
||||
isDuplicated, err := addOrderOrWaybillStatus(status, db)
|
||||
if err == nil && !isDuplicated {
|
||||
err = utils.CallFuncLogError(func() error {
|
||||
@@ -207,20 +207,6 @@ func (c *OrderController) addOrderStatus(orderStatus *model.OrderStatus, db orm.
|
||||
return isDuplicated, err
|
||||
}
|
||||
|
||||
func (c *OrderController) order2Status(order *model.GoodsOrder) (retVal *model.OrderStatus) {
|
||||
retVal = &model.OrderStatus{
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: order.VendorID,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: order.VendorOrderID,
|
||||
RefVendorID: order.VendorID,
|
||||
Status: order.Status,
|
||||
VendorStatus: order.VendorStatus,
|
||||
StatusTime: order.StatusTime,
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *OrderController) LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) {
|
||||
db := orm.NewOrm()
|
||||
order = &model.GoodsOrder{
|
||||
|
||||
@@ -19,7 +19,7 @@ func NewWaybillManager() *WaybillController {
|
||||
|
||||
func (w *WaybillController) onWaybillNew(bill *model.Waybill) (err error) {
|
||||
db := orm.NewOrm()
|
||||
isDuplicated, err := addOrderOrWaybillStatus(w.waybill2Status(bill), db)
|
||||
isDuplicated, err := addOrderOrWaybillStatus(model.Waybill2Status(bill), db)
|
||||
if !isDuplicated {
|
||||
bill.WaybillFinishedAt = utils.DefaultTimeValue
|
||||
bill.ID = 0
|
||||
@@ -89,7 +89,7 @@ func (w *WaybillController) addWaybillStatus(bill *model.Waybill, db orm.Ormer)
|
||||
if db == nil {
|
||||
db = orm.NewOrm()
|
||||
}
|
||||
waybillStatus := w.waybill2Status(bill)
|
||||
waybillStatus := model.Waybill2Status(bill)
|
||||
isDuplicated, err = addOrderOrWaybillStatus(waybillStatus, db)
|
||||
if !isDuplicated && waybillStatus.Status > model.WaybillStatusNew {
|
||||
params := orm.Params{
|
||||
@@ -106,17 +106,3 @@ func (w *WaybillController) addWaybillStatus(bill *model.Waybill, db orm.Ormer)
|
||||
}
|
||||
return isDuplicated, err
|
||||
}
|
||||
|
||||
func (w *WaybillController) waybill2Status(bill *model.Waybill) (retVal *model.OrderStatus) {
|
||||
retVal = &model.OrderStatus{
|
||||
VendorOrderID: bill.VendorWaybillID,
|
||||
VendorID: bill.WaybillVendorID,
|
||||
OrderType: model.OrderTypeWaybill,
|
||||
RefVendorOrderID: bill.VendorOrderID,
|
||||
RefVendorID: bill.OrderVendorID,
|
||||
Status: bill.Status,
|
||||
VendorStatus: bill.VendorStatus,
|
||||
StatusTime: bill.WaybillCreatedAt,
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ const (
|
||||
WX_DADA_DELIVERY_DONE_TEMPLATE_ID = "YXdCrQAHZlcZX1htYUiarrLmtkmKAjp7rynjwObgODo" //微信达达众包配送员配送完成推送
|
||||
)
|
||||
|
||||
var (
|
||||
venderColors = map[int]string{
|
||||
model.VendorIDJD: WX_TEMPLATE_VENDERCOLOR_JDDJ,
|
||||
model.VendorIDMTWM: WX_TEMPLATE_VENDERCOLOR_MT,
|
||||
model.VendorIDELM: WX_TEMPLATE_VENDERCOLOR_ELM,
|
||||
}
|
||||
)
|
||||
|
||||
func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) {
|
||||
db := orm.NewOrm()
|
||||
var lists []orm.ParamsList
|
||||
@@ -60,7 +68,7 @@ func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) {
|
||||
}
|
||||
// todo,调试,只发给我
|
||||
globals.SugarLogger.Debugf("GetWeixinOpenIDsFromStoreID store:%d, openids:%v", storeID, retVal)
|
||||
if storeID%3 == 0 { //} storeID == 100146 {
|
||||
if storeID == 100146 {
|
||||
retVal = []string{"oYN_ust9hXKEvEv0X6Mq6nlAWs_E"}
|
||||
} else {
|
||||
retVal = []string{}
|
||||
@@ -86,7 +94,7 @@ func SendMsgToStore(storeID int, templateID, downloadURL string, data interface{
|
||||
|
||||
func NotifyNewOrder(order *model.GoodsOrder) (err error) {
|
||||
sb := new(strings.Builder)
|
||||
sb.WriteString("老板")
|
||||
sb.WriteString("老板,")
|
||||
sb.WriteString(order.ConsigneeName)
|
||||
sb.WriteString("购买了商品")
|
||||
sb.WriteString(order.Skus[0].SkuName)
|
||||
@@ -102,7 +110,7 @@ func NotifyNewOrder(order *model.GoodsOrder) (err error) {
|
||||
"value": sb.String(),
|
||||
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
|
||||
},
|
||||
"day": map[string]interface{}{
|
||||
"Day": map[string]interface{}{
|
||||
"value": FormatDeliveryTime(order),
|
||||
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
|
||||
},
|
||||
@@ -111,8 +119,8 @@ func NotifyNewOrder(order *model.GoodsOrder) (err error) {
|
||||
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
|
||||
},
|
||||
"orderType": map[string]interface{}{
|
||||
"value": fmt.Sprintf("%s第%d号订单", model.VendorChineseNames[order.VendorID], order.OrderSeq),
|
||||
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
|
||||
"value": fmt.Sprintf("%s 第%d号订单", model.VendorChineseNames[order.VendorID], order.OrderSeq),
|
||||
"color": venderColors[order.VendorID],
|
||||
},
|
||||
"customerName": map[string]interface{}{
|
||||
"value": order.ConsigneeName,
|
||||
@@ -186,5 +194,5 @@ func FormatDeliveryTime(order *model.GoodsOrder) string {
|
||||
left := tmpTime.Sub(time.Now()) / time.Minute
|
||||
leftHours := left / 60
|
||||
leftMinutes := left % 60
|
||||
return fmt.Sprintf("请于%s前送达(剩余时间%d小时%d分钟", utils.Time2Str(tmpTime), leftHours, leftMinutes)
|
||||
return fmt.Sprintf("请于%s前送达(剩余时间%d小时%d分钟)", utils.Time2Str(tmpTime), leftHours, leftMinutes)
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ var (
|
||||
VendorIDMTPS: "MTPS",
|
||||
}
|
||||
VendorChineseNames = map[int]string{
|
||||
VendorIDJD: "京东",
|
||||
VendorIDMTWM: "美团",
|
||||
VendorIDJD: "京东到家",
|
||||
VendorIDMTWM: "美团外卖",
|
||||
VendorIDELM: "饿了么",
|
||||
VendorIDDada: "达达众包",
|
||||
VendorIDMTPS: "美团配送",
|
||||
|
||||
29
business/model/model.go
Normal file
29
business/model/model.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package model
|
||||
|
||||
func Order2Status(order *GoodsOrder) (retVal *OrderStatus) {
|
||||
retVal = &OrderStatus{
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: order.VendorID,
|
||||
OrderType: OrderTypeOrder,
|
||||
RefVendorOrderID: order.VendorOrderID,
|
||||
RefVendorID: order.VendorID,
|
||||
Status: order.Status,
|
||||
VendorStatus: order.VendorStatus,
|
||||
StatusTime: order.StatusTime,
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func Waybill2Status(bill *Waybill) (retVal *OrderStatus) {
|
||||
retVal = &OrderStatus{
|
||||
VendorOrderID: bill.VendorWaybillID,
|
||||
VendorID: bill.WaybillVendorID,
|
||||
OrderType: OrderTypeWaybill,
|
||||
RefVendorOrderID: bill.VendorOrderID,
|
||||
RefVendorID: bill.OrderVendorID,
|
||||
Status: bill.Status,
|
||||
VendorStatus: bill.VendorStatus,
|
||||
StatusTime: bill.WaybillCreatedAt,
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
@@ -24,6 +24,7 @@ const (
|
||||
|
||||
type WatchOrderInfo struct {
|
||||
order *model.GoodsOrder // order里的信息是保持更新的
|
||||
dirty int // 因为京东事件序列New与Accepted有极少数情况下会错序,处理延迟加载
|
||||
waybills []*model.Waybill // 这个waybills里的状态信息是不真实的,只使用id相关的信息
|
||||
timerStatus int
|
||||
timer *time.Timer
|
||||
@@ -79,7 +80,7 @@ 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.loadWatchOrderFromMap(status.VendorOrderID, status.VendorID); savedOrderInfo != nil {
|
||||
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) { //饿了么还观察到运单消息早于拣货完成消息
|
||||
@@ -99,6 +100,7 @@ func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err erro
|
||||
}
|
||||
} else {
|
||||
s.stopTimer(savedOrderInfo)
|
||||
s.cancelOtherWaybills(savedOrderInfo, nil)
|
||||
s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status))
|
||||
}
|
||||
} else {
|
||||
@@ -112,7 +114,7 @@ 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.loadWatchOrderFromMap(bill.VendorOrderID, bill.OrderVendorID); savedOrderInfo != nil {
|
||||
if savedOrderInfo := s.loadSavedOrderFromMap(model.Waybill2Status(bill)); savedOrderInfo != nil {
|
||||
s.addWaybill2Map(savedOrderInfo, bill) // 这样写的原因是因为调试时,程度从中途运行,没有接受到WaybillStatusNew事件
|
||||
if bill.Status == model.WaybillStatusNew {
|
||||
if bill.OrderVendorID == bill.WaybillVendorID {
|
||||
@@ -144,7 +146,10 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
|
||||
s.CurOrderManager.UpdateWaybillVendorID(bill)
|
||||
savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID
|
||||
}
|
||||
case model.WaybillStatusCanceled, model.WaybillStatusFailed:
|
||||
case model.WaybillStatusFailed: // WaybillStatusFailed理解成订单整个失败了,不需要再尝试创建运单了
|
||||
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)
|
||||
@@ -158,10 +163,10 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
|
||||
s.GetPurchasePlatformFromVendorID(bill.OrderVendorID).SelfDeliverDelievering(savedOrderInfo.order)
|
||||
}
|
||||
case model.WaybillStatusDelivered:
|
||||
s.removeWaybillFromMap(savedOrderInfo, bill)
|
||||
if savedOrderInfo.order.VendorID != bill.WaybillVendorID {
|
||||
s.GetPurchasePlatformFromVendorID(bill.OrderVendorID).SelfDeliverDelievered(savedOrderInfo.order)
|
||||
}
|
||||
s.removeWaybillFromMap(savedOrderInfo, bill)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -210,11 +215,11 @@ func (s *DefScheduler) createWaybillOn3rdProviders(order *model.GoodsOrder, excl
|
||||
func (s *DefScheduler) cancelOtherWaybills(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
|
||||
globals.SugarLogger.Debugf("cancelOtherWaybills, order:%v, bill:%v", savedOrderInfo.order, bill)
|
||||
for _, v := range savedOrderInfo.waybills {
|
||||
if v.WaybillVendorID != bill.OrderVendorID && !(v.WaybillVendorID == bill.WaybillVendorID && v.VendorWaybillID == bill.VendorWaybillID) {
|
||||
if bill == nil || v.WaybillVendorID != bill.OrderVendorID && !(v.WaybillVendorID == bill.WaybillVendorID && v.VendorWaybillID == bill.VendorWaybillID) {
|
||||
_ = s.GetDeliveryPlatformFromVendorID(v.WaybillVendorID).CancelWaybill(v)
|
||||
}
|
||||
}
|
||||
if bill.WaybillVendorID != bill.OrderVendorID {
|
||||
if bill != nil && bill.WaybillVendorID != bill.OrderVendorID {
|
||||
s.swtich2SelfDeliverWithRetry(bill, 2, 10*time.Second)
|
||||
}
|
||||
return nil
|
||||
@@ -231,20 +236,34 @@ func (s *DefScheduler) swtich2SelfDeliverWithRetry(bill *model.Waybill, retryCou
|
||||
}, duration, retryCount)
|
||||
}
|
||||
|
||||
func (s *DefScheduler) loadWatchOrderFromMap(vendorOrderID string, vendorID int) *WatchOrderInfo {
|
||||
universalOrderID := jxutils.ComposeUniversalOrderID(vendorOrderID, vendorID)
|
||||
// 这个函数这样写的原因是适应一些消息错序
|
||||
func (s *DefScheduler) loadSavedOrderFromMap(status *model.OrderStatus) *WatchOrderInfo {
|
||||
universalOrderID := jxutils.ComposeUniversalOrderID(status.VendorOrderID, status.VendorID)
|
||||
var realSavedInfo *WatchOrderInfo
|
||||
if savedInfo, ok := s.orderMap.Load(universalOrderID); ok {
|
||||
realSavedInfo = savedInfo.(*WatchOrderInfo)
|
||||
} else {
|
||||
globals.SugarLogger.Infof("can not get saved order, vendorOrderID:%s, vendorID:%d, load it", vendorOrderID, vendorID)
|
||||
if order, err := s.CurOrderManager.LoadOrder(vendorOrderID, vendorID); err == nil {
|
||||
realSavedInfo = &WatchOrderInfo{
|
||||
order: order,
|
||||
}
|
||||
}
|
||||
if realSavedInfo == nil || realSavedInfo.dirty == 1 {
|
||||
if realSavedInfo == nil {
|
||||
realSavedInfo = new(WatchOrderInfo)
|
||||
s.orderMap.Store(universalOrderID, realSavedInfo)
|
||||
} else {
|
||||
globals.SugarLogger.Errorf("can not load order vendorOrderID:%s, vendorID:%d", vendorOrderID, vendorID)
|
||||
realSavedInfo.dirty = 0
|
||||
globals.SugarLogger.Infof("order is dirty, vendorOrderID:%s, vendorID:%d, load it", status.VendorOrderID, status.VendorID)
|
||||
}
|
||||
if order, err := s.CurOrderManager.LoadOrder(status.VendorOrderID, status.VendorID); err == nil {
|
||||
realSavedInfo.order = order
|
||||
} else {
|
||||
realSavedInfo.order = &model.GoodsOrder{
|
||||
VendorOrderID: status.VendorOrderID,
|
||||
VendorID: status.VendorID,
|
||||
Status: status.Status,
|
||||
StatusTime: status.StatusTime,
|
||||
OrderCreatedAt: status.StatusTime,
|
||||
WaybillVendorID: model.VendorIDUnknown,
|
||||
}
|
||||
realSavedInfo.dirty = 1
|
||||
globals.SugarLogger.Infof("can not load order vendorOrderID:%s, vendorID:%d", status.VendorOrderID, status.VendorID)
|
||||
}
|
||||
}
|
||||
return realSavedInfo
|
||||
@@ -266,16 +285,20 @@ func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) {
|
||||
|
||||
func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, status int, beginTime time.Time, gap time.Duration) {
|
||||
globals.SugarLogger.Debugf("resetTimer status:%v, orderid:%v", status, savedOrderInfo.order.VendorOrderID)
|
||||
s.stopTimer(savedOrderInfo)
|
||||
config := s.mergeOrderStatusConfig(status, s.GetPurchasePlatformFromVendorID(savedOrderInfo.order.VendorID).GetStatusActionConfig(status))
|
||||
if config != nil && config.TimeoutAction != nil {
|
||||
timeout := jxutils.GetRealTimeout(beginTime, config.Timeout) + gap
|
||||
globals.SugarLogger.Debugf("resetTimer timeout:%v, orderid:%v", timeout, savedOrderInfo.order.VendorOrderID)
|
||||
savedOrderInfo.timerStatus = status
|
||||
savedOrderInfo.timer = time.AfterFunc(timeout, func() {
|
||||
config.TimeoutAction(savedOrderInfo.order)
|
||||
savedOrderInfo.timerStatus = 0
|
||||
})
|
||||
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 {
|
||||
timeout := jxutils.GetRealTimeout(beginTime, config.Timeout) + gap
|
||||
globals.SugarLogger.Debugf("resetTimer timeout:%v, orderid:%v", timeout, savedOrderInfo.order.VendorOrderID)
|
||||
savedOrderInfo.timerStatus = status
|
||||
savedOrderInfo.timer = time.AfterFunc(timeout, func() {
|
||||
config.TimeoutAction(savedOrderInfo.order)
|
||||
savedOrderInfo.timerStatus = 0 // todo 可能有线程安全问题,考虑加入订单队列
|
||||
})
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Infof("resetTimer status revert, orderid:%s, current timer status:%d, status:%d", savedOrderInfo.order.VendorOrderID, savedOrderInfo.timerStatus, status)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user