From da46c3396ee84e7c537c762c8c6f5a42ddaa1274 Mon Sep 17 00:00:00 2001 From: gazebo Date: Fri, 20 Jul 2018 18:10:14 +0800 Subject: [PATCH] - weixin msg added. - elm sometimes have no delivery msg - elm sometimes delivery msg arrvied before finished pickup - the gap between finished pickup and first delivery msg is big --- business/controller/order.go | 2 + business/controller/waybill.go | 6 + business/jxutils/jxutils.go | 7 +- business/jxutils/weixinmsg/weixinmsg.go | 183 +++++++++++++++++++++++ business/model/const.go | 11 +- business/scheduler/defsch/defsch.go | 184 ++++++++++++------------ business/scheduler/scheduler.go | 2 + globals/api/api.go | 1 - 8 files changed, 302 insertions(+), 94 deletions(-) create mode 100644 business/jxutils/weixinmsg/weixinmsg.go diff --git a/business/controller/order.go b/business/controller/order.go index e977c3a9c..a0fca1d47 100644 --- a/business/controller/order.go +++ b/business/controller/order.go @@ -7,6 +7,7 @@ import ( "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/globals" "github.com/astaxie/beego/orm" @@ -27,6 +28,7 @@ func (c *OrderController) OnOrderNew(order *model.GoodsOrder) (err error) { if err == nil && !isDuplicated { if err = c.saveOrder(order, false, db); err == nil { err = scheduler.CurrentScheduler.OnOrderNew(order) + weixinmsg.NotifyNewOrder(order) } } return err diff --git a/business/controller/waybill.go b/business/controller/waybill.go index c62d719ee..86833be14 100644 --- a/business/controller/waybill.go +++ b/business/controller/waybill.go @@ -2,6 +2,7 @@ package controller import ( "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/scheduler" "git.rosy.net.cn/jx-callback/globals" @@ -55,6 +56,11 @@ func (w *WaybillController) OnWaybillStatusChanged(bill *model.Waybill) (err err } } } + if bill.Status == model.WaybillStatusAccepted || bill.Status == model.WaybillStatusDelivered { + if order, err2 := OrderManager.LoadOrder(bill.VendorOrderID, bill.OrderVendorID); err2 == nil { + weixinmsg.NotifyWaybillStatus(bill, order) + } + } return err } diff --git a/business/jxutils/jxutils.go b/business/jxutils/jxutils.go index 1698cdb57..930e108ac 100644 --- a/business/jxutils/jxutils.go +++ b/business/jxutils/jxutils.go @@ -11,7 +11,6 @@ import ( "git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" - "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) @@ -127,7 +126,7 @@ func IntCoordinate2MarsStandard(gpsLng, gpsLat int, coordinateType int) (marsLng case model.CoordinateTypeMapbar: coordSys = autonavi.CoordSysMapbar default: - globals.SugarLogger.Errorf("known coordinate type:%d", coordinateType) + panic(fmt.Sprintf("known coordinate type:%d", coordinateType)) } return api.AutonaviAPI.CoordinateConvert(marsLng, marsLat, coordSys) } @@ -139,3 +138,7 @@ func IntPrice2Standard(value int64) float64 { func StandardPrice2Int(value float64) int64 { return int64(math.Round(value * 100)) } + +func IntPrice2StandardString(value int64) string { + return fmt.Sprintf("%.2f", IntPrice2Standard(value)) +} diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go new file mode 100644 index 000000000..c6fab7413 --- /dev/null +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -0,0 +1,183 @@ +package weixinmsg + +import ( + "fmt" + "strings" + "time" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/globals" + "github.com/astaxie/beego/orm" +) + +const ( + WX_TO_ORDER_PAGE_URL = "http://www.jxc4.com/jx/h5/#/?jxStoreId=" + WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://www.jxc4.com/jx/h5/#/assess-list?jxStoreId=" //展示差评详情的页面 + //新订单模板消息文字颜色 + WX_NEW_ORDER_TEMPLATE_COLOR = "#173177" + WX_HIGHLEVEL_TEMPLATE_COLOR = "#FF0000" //红色 + WX_TEMPLATE_VENDERCOLOR_JDDJ = "#47B34F" + WX_TEMPLATE_VENDERCOLOR_MT = "#F4A800" + WX_TEMPLATE_VENDERCOLOR_ELM = "#0191EA" //蓝色 + WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS = "#4F4DA0" + + WX_NEWORDER_TEMPLATE_ID = "_DtNGwmOeR6TkkTVUblxLIlkV2MAPOX57TkvfdqG6nY" //微信新订单推送 + WX_MTPS_DELIVERY_GRABDONE_TEMPLATE_ID = "h4dkON6AgnHz1XmaksEUB_8Bcir4V8MSexUhC149pPE" //微信美团配送员接单推送 + WX_MTPS_DELIVERY_DONE_TEMPLATE_ID = "YXdCrQAHZlcZX1htYUiarrLmtkmKAjp7rynjwObgODo" //微信美团配送员配送完成推送 + WX_MTPS_UNABLE_DELIVER_TEMPLATE_ID = "ZFph5Hp7oLlrzVRXbsKIC_StmaBeB9Dlp4tlHeAmUQ8" //微信美团配送配送能力不足推送 + WX_MTPS_DELIVERY_EXCEPTION_TEMPLATE_ID = "RkfOFHgR1N75L4-a6Gv0DljpCsVfOHhLm_vyXh8MR-w" //微信美团配送异常推送 + WX_BAD_COMMENT_PUSH_TEMPLATE_ID = "zMZH5Ek0k1OHlWnsDb98UaHEOlkJZYok2QOJUfwfJWs" //微信差评消息推送 + + WX_DADA_DELIVERY_GRABDONE_TEMPLATE_ID = "h4dkON6AgnHz1XmaksEUB_8Bcir4V8MSexUhC149pPE" //微信达达众包配送员接单推送 + WX_DADA_DELIVERY_DONE_TEMPLATE_ID = "YXdCrQAHZlcZX1htYUiarrLmtkmKAjp7rynjwObgODo" //微信达达众包配送员配送完成推送 +) + +func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) { + db := orm.NewOrm() + var lists []orm.ParamsList + num, err := db.Raw(` + SELECT openid + FROM weixins t1 + JOIN + (SELECT id + FROM weixins + WHERE jxstoreid = ? AND parentid = -1) t2 ON t2.id = t1.parentid + UNION + SELECT openid + FROM weixins + WHERE jxstoreid = ? AND parentid = -1 + `, storeID, storeID).ValuesList(&lists) + if err != nil || num == 0 { + globals.SugarLogger.Infof("can not find openid for store:%s, error:%v", storeID, err) + return retVal + } + for _, v := range lists { + retVal = append(retVal, v[0].(string)) + } + return retVal +} + +func SendMsgToStore(storeID int, templateID, downloadURL string, data interface{}) (err error) { + openIDs := GetWeixinOpenIDsFromStoreID(storeID) + errCount := 0 + for _, openID := range openIDs { + globals.SugarLogger.Debugf("send to:%s, templateID:%s, msg:%s", openID, templateID, string(utils.MustMarshal(data))) + // todo + // err2 := api.WeixinAPI.MessageTemplateSend(openID, templateID, downloadURL, nil, data) + // if err2 != nil { + // err = err2 + // errCount++ + // } + } + if errCount < len(openIDs) { + err = nil // 只要成功一个都当成成功 + } + return err +} + +func NotifyNewOrder(order *model.GoodsOrder) (err error) { + sb := new(strings.Builder) + sb.WriteString("老板") + sb.WriteString(order.ConsigneeName) + sb.WriteString("购买了商品") + sb.WriteString(order.Skus[0].SkuName) + sb.WriteString("共") + sb.WriteString(utils.Int2Str(order.Skus[0].Count)) + sb.WriteString("份(") + sb.WriteString(jxutils.IntPrice2StandardString(order.Skus[0].SalePrice)) + sb.WriteString("元/份)等,共支付了") + sb.WriteString(jxutils.IntPrice2StandardString(order.SalePrice)) + sb.WriteString("元") + data := map[string]interface{}{ + "first": map[string]interface{}{ + "value": sb.String(), + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "day": map[string]interface{}{ + "value": FormatDeliveryTime(order), + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "orderId": map[string]interface{}{ + "value": order.VendorOrderID, + "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, + }, + "customerName": map[string]interface{}{ + "value": order.ConsigneeName, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "customerPhone": map[string]interface{}{ + "value": order.ConsigneeMobile, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + } + storeID := jxutils.GetJxStoreIDFromOrder(order) + return SendMsgToStore(storeID, fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_NEWORDER_TEMPLATE_ID, data) +} + +func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder) error { + var title string + var templateID string + switch bill.Status { + case model.WaybillStatusAccepted: + if bill.WaybillVendorID == model.VendorIDMTPS { + templateID = WX_MTPS_DELIVERY_GRABDONE_TEMPLATE_ID + } else if bill.WaybillVendorID == model.VendorIDDada { + templateID = WX_DADA_DELIVERY_GRABDONE_TEMPLATE_ID + } + title = fmt.Sprintf("%s %s#订单长时间无人配送,我们已安排%s配送员%s电话号码%s负责配送。^_^", model.VendorChineseNames[bill.OrderVendorID], bill.VendorOrderID, model.VendorChineseNames[bill.WaybillVendorID], bill.CourierName, bill.CourierMobile) + case model.WaybillStatusDelivered: + if bill.WaybillVendorID == model.VendorIDMTPS { + templateID = WX_MTPS_DELIVERY_DONE_TEMPLATE_ID + } else if bill.WaybillVendorID == model.VendorIDDada { + templateID = WX_DADA_DELIVERY_DONE_TEMPLATE_ID + } + title = fmt.Sprintf("%s 第%d号订单的配送完成", model.VendorChineseNames[bill.OrderVendorID], order.OrderSeq) + } + if title != "" { + data := map[string]interface{}{ + "first": map[string]interface{}{ + "value": title, + "color": WX_HIGHLEVEL_TEMPLATE_COLOR, + }, + "keyword1": map[string]interface{}{ + "value": bill.VendorOrderID, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword2": map[string]interface{}{ + "value": bill.CourierName, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword3": map[string]interface{}{ + "value": bill.CourierMobile, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "remark": map[string]interface{}{ + "value": FormatDeliveryTime(order), + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + } + return SendMsgToStore(jxutils.GetJxStoreIDFromOrder(order), templateID, "", data) + } else { + globals.SugarLogger.Infof("NotifyWaybillStatus wrong, bill:%v", bill) + } + return nil +} + +func FormatDeliveryTime(order *model.GoodsOrder) string { + var tmpTime time.Time + if order.ExpectedDeliveredTime == utils.DefaultTimeValue { + tmpTime = order.OrderCreatedAt.Add(1 * time.Hour) + } else { + tmpTime = order.ExpectedDeliveredTime + } + left := tmpTime.Sub(time.Now()) / time.Minute + leftHours := left / 60 + leftMinutes := left % 60 + return fmt.Sprintf("请于%s前送达(剩余时间%d小时%d分钟", utils.Time2Str(tmpTime), leftHours, leftMinutes) +} diff --git a/business/model/const.go b/business/model/const.go index 7b70b9bb8..4c20b65d5 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -18,8 +18,17 @@ const ( var ( VendorNames = map[int]string{ VendorIDJD: "JD", - VendorIDELM: "ELEME", VendorIDMTWM: "MT", + VendorIDELM: "ELEME", + VendorIDDada: "Dada", + VendorIDMTPS: "MTPS", + } + VendorChineseNames = map[int]string{ + VendorIDJD: "京东", + VendorIDMTWM: "美团", + VendorIDELM: "饿了么", + VendorIDDada: "达达众包", + VendorIDMTPS: "美团配送", } ) diff --git a/business/scheduler/defsch/defsch.go b/business/scheduler/defsch/defsch.go index 52f1dd253..7454b0a39 100644 --- a/business/scheduler/defsch/defsch.go +++ b/business/scheduler/defsch/defsch.go @@ -18,8 +18,8 @@ const ( defTime2Delivered = 1 * time.Hour // 正常订单都是1小时达 defTime2Schedule3rdCarrier = 330 * time.Second // 京东要求5分钟后才能转自送,保险起见,设置为5分半钟 time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟,但为了防止没有运单事件,所以就拣货完成事件开始算,添加3分钟 - defTime2AutoPickupMin = 25 * time.Minute - time2AutoPickupGap = 5 * time.Minute + defTime2AutoPickupMin = 10 * time.Minute + time2AutoPickupGap = 2 * time.Minute ) type WatchOrderInfo struct { @@ -72,25 +72,37 @@ func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder) (err error) { order: order, } s.orderMap.Store(jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), watchInfo) - s.resetTimer(model.OrderStatusNew, watchInfo, 0) + s.resetTimer(watchInfo, model.OrderStatusNew, order.OrderCreatedAt, 0) return err } func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err error) { - globals.SugarLogger.Debugf("OnOrderStatusChanged, status:%v", status) - if savedOrderInfo := s.loadWatchOrderFromMap(status.VendorOrderID, status.VendorID); savedOrderInfo != nil { - if status.Status > model.OrderStatusUnknown && status.Status < model.OrderStatusEndBegin { + if status.Status > model.OrderStatusUnknown { + globals.SugarLogger.Debugf("OnOrderStatusChanged, status:%v", status) + if savedOrderInfo := s.loadWatchOrderFromMap(status.VendorOrderID, status.VendorID); savedOrderInfo != nil { s.updateOrderByStatus(savedOrderInfo.order, status) - gap := 0 * time.Second - if status.Status == model.OrderStatusAccepted { - gap = time.Duration(rand.Int63n(int64(time2AutoPickupGap))) - } else if status.Status == model.OrderStatusFinishedPickup { - gap = time2Schedule3rdCarrierGap4OrderStatus + if status.Status > model.OrderStatusUnknown && status.Status < model.OrderStatusEndBegin { + if !(status.Status == model.OrderStatusFinishedPickup && len(savedOrderInfo.waybills) > 0) { //饿了么还观察到运单消息早于拣货完成消息 + gap := 0 * time.Second + beginTime := status.StatusTime + if status.Status == model.OrderStatusNew { + beginTime = time.Now() + } else if status.Status == model.OrderStatusAccepted { + gap = time.Duration(rand.Int63n(int64(time2AutoPickupGap))) + beginTime = s.getBeginTime4LatestPickup(savedOrderInfo.order) + } else if status.Status == model.OrderStatusFinishedPickup { + // 召唤三方配送 + // 正常应该是只依赖于购物平台的第一个运单消息,但饿了么有观察到极少数情况下没有此事件,所以还是需要在这里加个保险的TIMER来驱动运单调度 + gap = time2Schedule3rdCarrierGap4OrderStatus + } + s.resetTimer(savedOrderInfo, status.Status, beginTime, gap) + } + } else { + s.stopTimer(savedOrderInfo) + s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status)) } - s.resetTimer(status.Status, savedOrderInfo, gap) } else { - s.stopTimer(savedOrderInfo) - s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status)) + err = scheduler.ErrCanNotFindOrder } } return err @@ -98,60 +110,65 @@ func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err erro // 以下是运单 func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) { - globals.SugarLogger.Debugf("OnWaybillStatusChanged, bill:%v", bill) - if savedOrderInfo := s.loadWatchOrderFromMap(bill.VendorOrderID, bill.OrderVendorID); savedOrderInfo != nil { - s.addWaybill2Map(savedOrderInfo, bill) // 这样写的原因是因为调试时,程度从中途运行,没有接受到WaybillStatusNew事件 - if bill.Status == model.WaybillStatusNew { - if bill.OrderVendorID == bill.WaybillVendorID { - if savedOrderInfo.timerStatus == model.OrderStatusFinishedPickup { - s.resetTimer(model.OrderStatusFinishedPickup, savedOrderInfo, 0) - } else { - globals.SugarLogger.Infof("OnWaybillStatusChanged met other timer, status:%d", savedOrderInfo.timerStatus) + if bill.Status > model.WaybillStatusUnknown { + globals.SugarLogger.Debugf("OnWaybillStatusChanged, bill:%v", bill) + if savedOrderInfo := s.loadWatchOrderFromMap(bill.VendorOrderID, bill.OrderVendorID); savedOrderInfo != nil { + s.addWaybill2Map(savedOrderInfo, bill) // 这样写的原因是因为调试时,程度从中途运行,没有接受到WaybillStatusNew事件 + if bill.Status == model.WaybillStatusNew { + if bill.OrderVendorID == bill.WaybillVendorID { + if savedOrderInfo.timerStatus == model.OrderStatusFinishedPickup { // 如果当前TIMER还是OrderStatusFinishedPickup(在OnOrderStatusChanged中设置的),则重置 + s.resetTimer(savedOrderInfo, model.OrderStatusFinishedPickup, bill.WaybillCreatedAt, 0) + } else { + globals.SugarLogger.Infof("OnWaybillStatusChanged met other timer, status:%d", savedOrderInfo.timerStatus) + } } - } - if savedOrderInfo.order.WaybillVendorID != model.VendorIDUnknown { - globals.SugarLogger.Infof("OnWaybillStatusChanged multiple waybill created, bill:%v", bill) - if bill.WaybillVendorID != bill.WaybillVendorID { - s.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID).CancelWaybill(bill) + if savedOrderInfo.order.WaybillVendorID != model.VendorIDUnknown { + globals.SugarLogger.Infof("OnWaybillStatusChanged multiple waybill created, bill:%v", bill) + if bill.WaybillVendorID != bill.WaybillVendorID { + s.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID).CancelWaybill(bill) + } + } + } else { + switch bill.Status { + case model.WaybillStatusAccepted: + s.stopTimer(savedOrderInfo) // todo 这里应该另外启动一个TIMER + s.cancelOtherWaybills(savedOrderInfo, bill) + + s.CurOrderManager.UpdateWaybillVendorID(bill) + savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID + case model.WaybillStatusAcceptCanceled: + if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { + s.createWaybillOn3rdProviders(savedOrderInfo.order, bill) + + bill.WaybillVendorID = model.VendorIDUnknown + s.CurOrderManager.UpdateWaybillVendorID(bill) + savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID + } + case model.WaybillStatusCanceled, model.WaybillStatusFailed: + s.removeWaybillFromMap(savedOrderInfo, bill) + if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { + s.createWaybillOn3rdProviders(savedOrderInfo.order, nil) + + bill.WaybillVendorID = model.VendorIDUnknown + s.CurOrderManager.UpdateWaybillVendorID(bill) + savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID + } + case model.WaybillStatusDelivering: + if savedOrderInfo.order.VendorID != bill.WaybillVendorID { + s.GetPurchasePlatformFromVendorID(bill.OrderVendorID).SelfDeliverDelievering(savedOrderInfo.order) + } + case model.WaybillStatusDelivered: + if savedOrderInfo.order.VendorID != bill.WaybillVendorID { + s.GetPurchasePlatformFromVendorID(bill.OrderVendorID).SelfDeliverDelievered(savedOrderInfo.order) + } + s.removeWaybillFromMap(savedOrderInfo, bill) } } } else { - switch bill.Status { - case model.WaybillStatusAccepted: - s.stopTimer(savedOrderInfo) // todo 这里应该另外启动一个TIMER - s.cancelOtherWaybills(savedOrderInfo, bill) - - s.CurOrderManager.UpdateWaybillVendorID(bill) - savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID - case model.WaybillStatusAcceptCanceled: - s.createWaybillOn3rdProviders(savedOrderInfo.order, bill) - if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { - bill.WaybillVendorID = model.VendorIDUnknown - s.CurOrderManager.UpdateWaybillVendorID(bill) - savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID - } - case model.WaybillStatusCanceled, model.WaybillStatusFailed: - s.removeWaybillFromMap(savedOrderInfo, bill) - if savedOrderInfo.order.WaybillVendorID == bill.WaybillVendorID { - s.createWaybillOn3rdProviders(savedOrderInfo.order, nil) - - bill.WaybillVendorID = model.VendorIDUnknown - s.CurOrderManager.UpdateWaybillVendorID(bill) - savedOrderInfo.order.WaybillVendorID = bill.WaybillVendorID - } - case model.WaybillStatusDelivering: - if savedOrderInfo.order.VendorID != bill.WaybillVendorID { - s.GetPurchasePlatformFromVendorID(bill.OrderVendorID).SelfDeliverDelievering(savedOrderInfo.order) - } - case model.WaybillStatusDelivered: - if savedOrderInfo.order.VendorID != bill.WaybillVendorID { - s.GetPurchasePlatformFromVendorID(bill.OrderVendorID).SelfDeliverDelievered(savedOrderInfo.order) - } - s.removeWaybillFromMap(savedOrderInfo, bill) - } + err = scheduler.ErrCanNotFindOrder } } - return nil + return err } func (s *DefScheduler) addWaybill2Map(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { @@ -165,6 +182,15 @@ func (s *DefScheduler) addWaybill2Map(savedOrderInfo *WatchOrderInfo, bill *mode savedOrderInfo.waybills = append(savedOrderInfo.waybills, bill) } +func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { + for k, v := range savedOrderInfo.waybills { + if v.VendorWaybillID == bill.VendorWaybillID && v.WaybillVendorID == bill.WaybillVendorID { + savedOrderInfo.waybills = append(savedOrderInfo.waybills[0:k], savedOrderInfo.waybills[k+1:]...) + break + } + } +} + func (s *DefScheduler) createWaybillOn3rdProviders(order *model.GoodsOrder, excludeBill *model.Waybill) (err error) { globals.SugarLogger.Debugf("createWaybillOn3rdProviders, order:%v", order) successCount := 0 @@ -224,26 +250,11 @@ func (s *DefScheduler) loadWatchOrderFromMap(vendorOrderID string, vendorID int) return realSavedInfo } -func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { - if savedOrderInfo == nil { - savedOrderInfo = s.loadWatchOrderFromMap(bill.VendorOrderID, bill.OrderVendorID) - } - if savedOrderInfo != nil { - for k, v := range savedOrderInfo.waybills { - if v.VendorWaybillID == bill.VendorWaybillID && v.WaybillVendorID == bill.WaybillVendorID { - savedOrderInfo.waybills = append(savedOrderInfo.waybills[0:k], savedOrderInfo.waybills[k+1:]...) - break - } - } - } -} - -func (s *DefScheduler) getLatestPickupTimeout(order *model.GoodsOrder, configTimeout time.Duration) (retVal time.Duration) { - beginTime := order.StatusTime +func (s *DefScheduler) getBeginTime4LatestPickup(order *model.GoodsOrder) (retVal time.Time) { if order.ExpectedDeliveredTime != utils.DefaultTimeValue { - beginTime = order.ExpectedDeliveredTime.Add(-defTime2Delivered) + return order.ExpectedDeliveredTime.Add(-defTime2Delivered) } - return jxutils.GetRealTimeout(beginTime, configTimeout) + return order.StatusTime } func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) { @@ -253,24 +264,17 @@ func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) { } } -func (s *DefScheduler) resetTimer(status int, savedOrderInfo *WatchOrderInfo, gap time.Duration) { +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 { - var timeout time.Duration - if status == model.OrderStatusNew { - timeout = config.Timeout // 绝对值 - } else if status == model.OrderStatusAccepted { - timeout = s.getLatestPickupTimeout(savedOrderInfo.order, config.Timeout) - } else { - timeout = jxutils.GetRealTimeout(savedOrderInfo.order.StatusTime, config.Timeout) - } - timeout += gap + 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 }) } } diff --git a/business/scheduler/scheduler.go b/business/scheduler/scheduler.go index 5f4cd31b0..449a90029 100644 --- a/business/scheduler/scheduler.go +++ b/business/scheduler/scheduler.go @@ -15,6 +15,8 @@ var ( var ( ErrStatusIsNotOKForOperation = errors.New("当前状态操作无效") ErrCanNotCreateAtLeastOneWaybill = errors.New("一个运单都不能创建") + ErrCanNotFindOrder = errors.New("不能找到订单(一般是由于事件错序)") + ErrCanNotFindWaybill = errors.New("不能找到运单(一般是由于事件错序)") ) type StatusActionConfig struct { diff --git a/globals/api/api.go b/globals/api/api.go index 41f6aa5dd..7d68eabb2 100644 --- a/globals/api/api.go +++ b/globals/api/api.go @@ -11,7 +11,6 @@ import ( "github.com/astaxie/beego" "github.com/astaxie/beego/orm" - _ "github.com/go-sql-driver/mysql" // import your used driver ) var (