- 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
This commit is contained in:
gazebo
2018-07-20 18:10:14 +08:00
parent 6fc02ac6cd
commit da46c3396e
8 changed files with 302 additions and 94 deletions

View File

@@ -7,6 +7,7 @@ import (
"git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/utils" "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/model"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
@@ -27,6 +28,7 @@ func (c *OrderController) OnOrderNew(order *model.GoodsOrder) (err error) {
if err == nil && !isDuplicated { if err == nil && !isDuplicated {
if err = c.saveOrder(order, false, db); err == nil { if err = c.saveOrder(order, false, db); err == nil {
err = scheduler.CurrentScheduler.OnOrderNew(order) err = scheduler.CurrentScheduler.OnOrderNew(order)
weixinmsg.NotifyNewOrder(order)
} }
} }
return err return err

View File

@@ -2,6 +2,7 @@ package controller
import ( import (
"git.rosy.net.cn/baseapi/utils" "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/model"
"git.rosy.net.cn/jx-callback/business/scheduler" "git.rosy.net.cn/jx-callback/business/scheduler"
"git.rosy.net.cn/jx-callback/globals" "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 return err
} }

View File

@@ -11,7 +11,6 @@ import (
"git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/platformapi/autonavi"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api"
) )
@@ -127,7 +126,7 @@ func IntCoordinate2MarsStandard(gpsLng, gpsLat int, coordinateType int) (marsLng
case model.CoordinateTypeMapbar: case model.CoordinateTypeMapbar:
coordSys = autonavi.CoordSysMapbar coordSys = autonavi.CoordSysMapbar
default: default:
globals.SugarLogger.Errorf("known coordinate type:%d", coordinateType) panic(fmt.Sprintf("known coordinate type:%d", coordinateType))
} }
return api.AutonaviAPI.CoordinateConvert(marsLng, marsLat, coordSys) return api.AutonaviAPI.CoordinateConvert(marsLng, marsLat, coordSys)
} }
@@ -139,3 +138,7 @@ func IntPrice2Standard(value int64) float64 {
func StandardPrice2Int(value float64) int64 { func StandardPrice2Int(value float64) int64 {
return int64(math.Round(value * 100)) return int64(math.Round(value * 100))
} }
func IntPrice2StandardString(value int64) string {
return fmt.Sprintf("%.2f", IntPrice2Standard(value))
}

View File

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

View File

@@ -18,8 +18,17 @@ const (
var ( var (
VendorNames = map[int]string{ VendorNames = map[int]string{
VendorIDJD: "JD", VendorIDJD: "JD",
VendorIDELM: "ELEME",
VendorIDMTWM: "MT", VendorIDMTWM: "MT",
VendorIDELM: "ELEME",
VendorIDDada: "Dada",
VendorIDMTPS: "MTPS",
}
VendorChineseNames = map[int]string{
VendorIDJD: "京东",
VendorIDMTWM: "美团",
VendorIDELM: "饿了么",
VendorIDDada: "达达众包",
VendorIDMTPS: "美团配送",
} }
) )

View File

@@ -18,8 +18,8 @@ const (
defTime2Delivered = 1 * time.Hour // 正常订单都是1小时达 defTime2Delivered = 1 * time.Hour // 正常订单都是1小时达
defTime2Schedule3rdCarrier = 330 * time.Second // 京东要求5分钟后才能转自送保险起见设置为5分半钟 defTime2Schedule3rdCarrier = 330 * time.Second // 京东要求5分钟后才能转自送保险起见设置为5分半钟
time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟但为了防止没有运单事件所以就拣货完成事件开始算添加3分钟 time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟但为了防止没有运单事件所以就拣货完成事件开始算添加3分钟
defTime2AutoPickupMin = 25 * time.Minute defTime2AutoPickupMin = 10 * time.Minute
time2AutoPickupGap = 5 * time.Minute time2AutoPickupGap = 2 * time.Minute
) )
type WatchOrderInfo struct { type WatchOrderInfo struct {
@@ -72,25 +72,37 @@ func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder) (err error) {
order: order, order: order,
} }
s.orderMap.Store(jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), watchInfo) 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 return err
} }
func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err error) { func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err error) {
globals.SugarLogger.Debugf("OnOrderStatusChanged, status:%v", status) if status.Status > model.OrderStatusUnknown {
if savedOrderInfo := s.loadWatchOrderFromMap(status.VendorOrderID, status.VendorID); savedOrderInfo != nil { globals.SugarLogger.Debugf("OnOrderStatusChanged, status:%v", status)
if status.Status > model.OrderStatusUnknown && status.Status < model.OrderStatusEndBegin { if savedOrderInfo := s.loadWatchOrderFromMap(status.VendorOrderID, status.VendorID); savedOrderInfo != nil {
s.updateOrderByStatus(savedOrderInfo.order, status) s.updateOrderByStatus(savedOrderInfo.order, status)
gap := 0 * time.Second if status.Status > model.OrderStatusUnknown && status.Status < model.OrderStatusEndBegin {
if status.Status == model.OrderStatusAccepted { if !(status.Status == model.OrderStatusFinishedPickup && len(savedOrderInfo.waybills) > 0) { //饿了么还观察到运单消息早于拣货完成消息
gap = time.Duration(rand.Int63n(int64(time2AutoPickupGap))) gap := 0 * time.Second
} else if status.Status == model.OrderStatusFinishedPickup { beginTime := status.StatusTime
gap = time2Schedule3rdCarrierGap4OrderStatus 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 { } else {
s.stopTimer(savedOrderInfo) err = scheduler.ErrCanNotFindOrder
s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status))
} }
} }
return err return err
@@ -98,60 +110,65 @@ func (s *DefScheduler) OnOrderStatusChanged(status *model.OrderStatus) (err erro
// 以下是运单 // 以下是运单
func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) { func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
globals.SugarLogger.Debugf("OnWaybillStatusChanged, bill:%v", bill) if bill.Status > model.WaybillStatusUnknown {
if savedOrderInfo := s.loadWatchOrderFromMap(bill.VendorOrderID, bill.OrderVendorID); savedOrderInfo != nil { globals.SugarLogger.Debugf("OnWaybillStatusChanged, bill:%v", bill)
s.addWaybill2Map(savedOrderInfo, bill) // 这样写的原因是因为调试时程度从中途运行没有接受到WaybillStatusNew事件 if savedOrderInfo := s.loadWatchOrderFromMap(bill.VendorOrderID, bill.OrderVendorID); savedOrderInfo != nil {
if bill.Status == model.WaybillStatusNew { s.addWaybill2Map(savedOrderInfo, bill) // 这样写的原因是因为调试时,程度从中途运行,没有接受到WaybillStatusNew事件
if bill.OrderVendorID == bill.WaybillVendorID { if bill.Status == model.WaybillStatusNew {
if savedOrderInfo.timerStatus == model.OrderStatusFinishedPickup { if bill.OrderVendorID == bill.WaybillVendorID {
s.resetTimer(model.OrderStatusFinishedPickup, savedOrderInfo, 0) if savedOrderInfo.timerStatus == model.OrderStatusFinishedPickup { // 如果当前TIMER还是OrderStatusFinishedPickup在OnOrderStatusChanged中设置的则重置
} else { s.resetTimer(savedOrderInfo, model.OrderStatusFinishedPickup, bill.WaybillCreatedAt, 0)
globals.SugarLogger.Infof("OnWaybillStatusChanged met other timer, status:%d", savedOrderInfo.timerStatus) } else {
globals.SugarLogger.Infof("OnWaybillStatusChanged met other timer, status:%d", savedOrderInfo.timerStatus)
}
} }
} if savedOrderInfo.order.WaybillVendorID != model.VendorIDUnknown {
if savedOrderInfo.order.WaybillVendorID != model.VendorIDUnknown { globals.SugarLogger.Infof("OnWaybillStatusChanged multiple waybill created, bill:%v", bill)
globals.SugarLogger.Infof("OnWaybillStatusChanged multiple waybill created, bill:%v", bill) if bill.WaybillVendorID != bill.WaybillVendorID {
if bill.WaybillVendorID != bill.WaybillVendorID { s.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID).CancelWaybill(bill)
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 { } else {
switch bill.Status { err = scheduler.ErrCanNotFindOrder
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)
}
} }
} }
return nil return err
} }
func (s *DefScheduler) addWaybill2Map(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { 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) 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) { func (s *DefScheduler) createWaybillOn3rdProviders(order *model.GoodsOrder, excludeBill *model.Waybill) (err error) {
globals.SugarLogger.Debugf("createWaybillOn3rdProviders, order:%v", order) globals.SugarLogger.Debugf("createWaybillOn3rdProviders, order:%v", order)
successCount := 0 successCount := 0
@@ -224,26 +250,11 @@ func (s *DefScheduler) loadWatchOrderFromMap(vendorOrderID string, vendorID int)
return realSavedInfo return realSavedInfo
} }
func (s *DefScheduler) removeWaybillFromMap(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) { func (s *DefScheduler) getBeginTime4LatestPickup(order *model.GoodsOrder) (retVal time.Time) {
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
if order.ExpectedDeliveredTime != utils.DefaultTimeValue { 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) { 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) globals.SugarLogger.Debugf("resetTimer status:%v, orderid:%v", status, savedOrderInfo.order.VendorOrderID)
s.stopTimer(savedOrderInfo) s.stopTimer(savedOrderInfo)
config := s.mergeOrderStatusConfig(status, s.GetPurchasePlatformFromVendorID(savedOrderInfo.order.VendorID).GetStatusActionConfig(status)) config := s.mergeOrderStatusConfig(status, s.GetPurchasePlatformFromVendorID(savedOrderInfo.order.VendorID).GetStatusActionConfig(status))
if config != nil && config.TimeoutAction != nil { if config != nil && config.TimeoutAction != nil {
var timeout time.Duration timeout := jxutils.GetRealTimeout(beginTime, config.Timeout) + gap
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
globals.SugarLogger.Debugf("resetTimer timeout:%v, orderid:%v", timeout, savedOrderInfo.order.VendorOrderID) globals.SugarLogger.Debugf("resetTimer timeout:%v, orderid:%v", timeout, savedOrderInfo.order.VendorOrderID)
savedOrderInfo.timerStatus = status savedOrderInfo.timerStatus = status
savedOrderInfo.timer = time.AfterFunc(timeout, func() { savedOrderInfo.timer = time.AfterFunc(timeout, func() {
config.TimeoutAction(savedOrderInfo.order) config.TimeoutAction(savedOrderInfo.order)
savedOrderInfo.timerStatus = 0
}) })
} }
} }

View File

@@ -15,6 +15,8 @@ var (
var ( var (
ErrStatusIsNotOKForOperation = errors.New("当前状态操作无效") ErrStatusIsNotOKForOperation = errors.New("当前状态操作无效")
ErrCanNotCreateAtLeastOneWaybill = errors.New("一个运单都不能创建") ErrCanNotCreateAtLeastOneWaybill = errors.New("一个运单都不能创建")
ErrCanNotFindOrder = errors.New("不能找到订单(一般是由于事件错序)")
ErrCanNotFindWaybill = errors.New("不能找到运单(一般是由于事件错序)")
) )
type StatusActionConfig struct { type StatusActionConfig struct {

View File

@@ -11,7 +11,6 @@ import (
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql" // import your used driver
) )
var ( var (