- 梳理TIMER,去除TimerTypeBaseExpectedDeliveredTime

This commit is contained in:
gazebo
2019-03-31 15:46:41 +08:00
parent d2fafe5ec0
commit ef05d85fc2
9 changed files with 132 additions and 119 deletions

View File

@@ -23,11 +23,13 @@ import (
)
const (
time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。
time2Schedule3rdCarrier = 20 // 收到平台方自有配送的新运单消息后等待创建三方配送运单的时间分钟如果是定时达会再根据ExpectedDeliveredTime与dingShiDaAheadTime做调整
// time2Schedule3rdCarrierGap4OrderStatus = 3 * time.Minute // 京东要求是运单状态为待抢单且超时5分钟但为了防止没有运单事件所以就拣货完成事件开始算添加3分钟
time2AutoPickupMin = 15 * time.Minute // 自动拣货等待时间这个只有在没有PickDeadline信息才有用否则会根据PickDeadline设置
time2AutoPickupGap = 1 * 60 //随机1分钟
time2Delivered = 1 * time.Hour // 正常从下单到送达的时间。
minute2Schedule3rdCarrier = 20 // 收到平台方自有配送的新运单消息后等待创建三方配送运单的时间分钟如果是定时达会再根据ExpectedDeliveredTime与dingShiDaAheadTime做调整
minMinute2Schedule3rdCarrier = 5 // 转三方配送最少等待时间(分钟
time2AutoPickupMin = 15 * time.Minute // 自动拣货等待时间这个只有在没有PickDeadline信息才有用否则会根据PickDeadline设置
second2AutoPickupGap = 60 //随机60秒
time2AutoPickupAhead = 20 * time.Second // 有最后拣货时间的提前值
// 把pending order timerout 在-pendingOrderTimerMinMinSecond至pendingOrderTimerMaxSecond映射到pendingOrderTimerMinSecond至pendingOrderTimerMaxSecond
pendingOrderTimerMinMinSecond = 5 * 60 // 5分钟
@@ -155,9 +157,9 @@ func init() {
},
model.OrderStatusAccepted: &StatusActionConfig{ // 自动拣货
StatusActionParams: partner.StatusActionParams{
TimerType: partner.TimerTypeBaseExpectedDeliveredTime,
Timeout: time2AutoPickupMin, // 此值会被门店设置覆盖
TimeoutGap: time2AutoPickupGap,
TimerType: partner.TimerTypeBaseStatusTime,
Timeout: time2AutoPickupMin,
TimeoutGap: second2AutoPickupGap,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo) (err error) {
if savedOrderInfo.autoPickupTimeoutMinute > 0 {
@@ -184,10 +186,10 @@ func init() {
model.WaybillStatusNew: &StatusActionConfig{
StatusActionParams: partner.StatusActionParams{
TimerType: partner.TimerTypeBaseStatusTime,
Timeout: time2Schedule3rdCarrier * time.Minute,
Timeout: minute2Schedule3rdCarrier * time.Minute,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo) (err error) {
if savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore { // 非自配商家使用
if savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore { // 非自配商家使用
return sch.createWaybillOn3rdProviders(savedOrderInfo, nil)
}
return nil
@@ -199,7 +201,7 @@ func init() {
func Init() {
configindb.WatchConfigChange(time2Schedule3rdCarrierKey, OnDefSchConfChanged)
if configTime, err := configindb.GetConfig(time2Schedule3rdCarrierKey, utils.Int2Str(time2Schedule3rdCarrier)); err == nil {
if configTime, err := configindb.GetConfig(time2Schedule3rdCarrierKey, utils.Int2Str(minute2Schedule3rdCarrier)); err == nil {
OnDefSchConfChanged(time2Schedule3rdCarrierKey, configTime)
} else {
globals.SugarLogger.Errorf("defsch Init, error:%v", err)
@@ -629,38 +631,12 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Wa
}
globals.SugarLogger.Debugf("resetTimer, orderID:%s statusType:%d status:%v", order.VendorOrderID, statusType, status)
if statusType != savedOrderInfo.timerStatusType || status >= savedOrderInfo.timerStatus { // 新设置的TIMER不能覆盖状态在其后的TIMER如果状态回绕需要注意
config := s.mergeOrderStatusConfig(savedOrderInfo.order, statusType, status, order.VendorID)
config := s.mergeOrderStatusConfig(savedOrderInfo, statusTime, statusType, status)
if config == nil || config.TimerType != partner.TimerTypeByPass {
s.stopTimer(savedOrderInfo)
}
if config != nil && config.TimeoutAction != nil && config.TimerType != partner.TimerTypeByPass {
nowTime := time.Now()
configTimerType := config.TimerType
if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted { // 自动拣货的TIMER特殊处理
if !utils.IsTimeZero(order.PickDeadline) { // 如果有PickDeadline值特殊处理
configTimerType = partner.TimerTypeBaseNow
config.Timeout = order.PickDeadline.Sub(nowTime) - 20*time.Second // 提前一点操作,防止超时
if config.TimeoutGap != 0 {
config.Timeout -= time.Duration(config.TimeoutGap) * time.Second
}
} else if savedOrderInfo.autoPickupTimeoutMinute > 1 { // 对于自动拣货,以订单中的设置为准
config.Timeout = time.Duration(savedOrderInfo.autoPickupTimeoutMinute) * time.Minute
}
}
var timeout time.Duration
switch configTimerType {
case partner.TimerTypeBaseNow:
timeout = config.Timeout
case partner.TimerTypeBaseStatusTime:
timeout = statusTime.Sub(nowTime) + config.Timeout
case partner.TimerTypeBaseExpectedDeliveredTime:
if order.BusinessType == model.BusinessTypeDingshida && !utils.IsTimeZero(order.ExpectedDeliveredTime) {
statusTime = order.ExpectedDeliveredTime.Add(-time2Delivered)
}
timeout = statusTime.Sub(nowTime) + config.Timeout
default:
panic("TimerType is wrong!!!")
}
timeout := config.GetRefTimeout(statusTime)
if config.TimeoutGap != 0 {
timeout += time.Duration(rand.Intn(int(config.TimeoutGap))) * time.Second
}
@@ -694,6 +670,87 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Wa
}
}
func (s *DefScheduler) mergeOrderStatusConfig(savedOrderInfo *WatchOrderInfo, statusTime time.Time, statusType, status int) (retVal *StatusActionConfig) {
s.locker.RLock()
defer func() {
s.locker.RUnlock()
}()
defConfig := s.defWorkflowConfig[statusType][status]
if defConfig == nil {
return nil
}
retVal = &StatusActionConfig{}
*retVal = *defConfig
order := savedOrderInfo.order
var vendorActionParams *partner.StatusActionParams
// 非立即达订单timer设置
if model.IsOrderSolid(order) {
if order.BusinessType != model.BusinessTypeImmediate { // 非立即达订单
if utils.IsTimeZero(order.ExpectedDeliveredTime) {
globals.SugarLogger.Warnf("mergeOrderStatusConfig orderID:%s 非立即达订单没有预计送达时间, orderDetail:%s", order.VendorOrderID, utils.Format4Output(order, false))
} else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup { // 这个只针对自配送门店才有效
vendorActionParams = &partner.StatusActionParams{
TimerType: partner.TimerTypeBaseNow,
Timeout: order.ExpectedDeliveredTime.Sub(time.Now()) - dingShiDaAheadTime,
TimeoutGap: -1,
}
timeout := statusTime.Sub(time.Now()) + minMinute2Schedule3rdCarrier*time.Minute
if vendorActionParams.GetRefTimeout(statusTime) < timeout { // 如果非立即达订单根据ExpectedDeliveredTime算出来的timeout太早
vendorActionParams.Timeout = timeout
vendorActionParams.TimeoutGap = 0
}
} else if statusType == scheduler.TimerStatusTypeWaybill && status == model.WaybillStatusNew { // 因为有些平台(比如美团外卖)的定时达单,很早就创建运单了
vendorActionParams = &partner.StatusActionParams{
TimerType: partner.TimerTypeBaseNow,
Timeout: order.ExpectedDeliveredTime.Sub(time.Now()) - dingShiDaAheadTime,
TimeoutGap: -1,
}
}
}
}
if vendorActionParams == nil {
vendorActionParams = partner.GetPurchasePlatformFromVendorID(order.VendorID).GetStatusActionTimeout(order, statusType, status)
}
// 自动拣货TIMER
if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted {
if savedOrderInfo.autoPickupTimeoutMinute > 0 {
if utils.IsTimeZero(order.PickDeadline) { // 没有最后拣货时间,正推,以订单中的配置为准
if utils.IsTimeZero(order.ExpectedDeliveredTime) || order.BusinessType == model.BusinessTypeImmediate { // 立即达或没有最后送达时间
// 以缺省配置或平台相关中的配置为准
} else { // 非立即达且有最后送达时间
timeout := time2AutoPickupMin
if savedOrderInfo.autoPickupTimeoutMinute > 1 {
timeout = time.Duration(savedOrderInfo.autoPickupTimeoutMinute) * time.Minute
}
vendorActionParams = &partner.StatusActionParams{
TimerType: partner.TimerTypeBaseNow,
Timeout: order.ExpectedDeliveredTime.Add(-time2Delivered).Sub(time.Now()) + timeout,
}
}
} else { // 有最后拣货时间,反推
vendorActionParams = &partner.StatusActionParams{
TimerType: partner.TimerTypeBaseNow,
Timeout: order.PickDeadline.Sub(time.Now()) - time2AutoPickupAhead - second2AutoPickupGap*time.Second,
TimeoutGap: second2AutoPickupGap,
}
}
}
}
if vendorActionParams != nil {
retVal.Timeout = vendorActionParams.Timeout
if vendorActionParams.TimeoutGap >= 0 {
retVal.TimeoutGap = vendorActionParams.TimeoutGap
}
if vendorActionParams.TimerType != partner.TimerTypeNoOverride {
retVal.TimerType = vendorActionParams.TimerType
}
}
return retVal
}
func (s *DefScheduler) handleAutoAcceptOrder(orderID string, vendorID int, userMobile string, jxStoreID int, db orm.Ormer, handler func(accepted bool) error) int {
handleType := 0
if userMobile != "" {
@@ -726,53 +783,6 @@ func (s *DefScheduler) handleAutoAcceptOrder(orderID string, vendorID int, userM
return handleType
}
func (s *DefScheduler) mergeOrderStatusConfig(order *model.GoodsOrder, statusType, status int, purchaseVendorID int) (retVal *StatusActionConfig) {
s.locker.RLock()
defer func() {
s.locker.RUnlock()
}()
defConfig := s.defWorkflowConfig[statusType][status]
if defConfig == nil {
return nil
}
retVal = &StatusActionConfig{}
*retVal = *defConfig
var vendorActionParams *partner.StatusActionParams
if model.IsOrderSolid(order) {
if order.BusinessType != model.BusinessTypeImmediate {
if jxutils.IsTimeEmpty(order.ExpectedDeliveredTime) {
globals.SugarLogger.Warnf("mergeOrderStatusConfig orderID:%s 非立即达订单没有预计送达时间, orderDetail:%s", order.VendorOrderID, utils.Format4Output(order, false))
} else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup { // 这个只针对自配送门店才有效
vendorActionParams = &partner.StatusActionParams{
TimerType: partner.TimerTypeBaseNow,
Timeout: order.ExpectedDeliveredTime.Sub(time.Now()) - dingShiDaAheadTime,
TimeoutGap: -1,
}
} else if statusType == scheduler.TimerStatusTypeWaybill && status == model.WaybillStatusNew { // 因为有些平台(比如美团外卖)的定时达单,很早就创建运单了
vendorActionParams = &partner.StatusActionParams{
TimerType: partner.TimerTypeBaseNow,
Timeout: order.ExpectedDeliveredTime.Sub(time.Now()) - dingShiDaAheadTime,
TimeoutGap: -1,
}
}
}
}
if vendorActionParams == nil {
vendorActionParams = partner.GetPurchasePlatformFromVendorID(purchaseVendorID).GetStatusActionTimeout(order, statusType, status)
}
if vendorActionParams != nil {
retVal.Timeout = vendorActionParams.Timeout
if vendorActionParams.TimeoutGap >= 0 {
retVal.TimeoutGap = vendorActionParams.TimeoutGap
}
if vendorActionParams.TimerType != partner.TimerTypeNoOverride {
retVal.TimerType = vendorActionParams.TimerType
}
}
return retVal
}
func (s *DefScheduler) updateOrderByStatus(order *model.GoodsOrder, status *model.OrderStatus) (retVal *model.GoodsOrder) {
order.Status = status.Status
order.VendorStatus = status.VendorStatus
@@ -833,7 +843,7 @@ func (s *DefScheduler) ProxyCancelWaybill(order *model.GoodsOrder, bill *model.W
func OnDefSchConfChanged(key, value string) {
if key == time2Schedule3rdCarrierKey {
waitMinutes := int(utils.Str2Int64WithDefault(value, time2Schedule3rdCarrier))
waitMinutes := int(utils.Str2Int64WithDefault(value, minute2Schedule3rdCarrier))
if waitMinutes >= 0 {
FixedScheduler.locker.Lock()
defer func() {

View File

@@ -25,7 +25,7 @@ var (
func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
buildTimeStr := ""
if !jxutils.IsTimeEmpty(buildTime) {
if !utils.IsTimeZero(buildTime) {
buildTimeStr = utils.Time2Str(buildTime)
}
serviceInfo = map[string]interface{}{

View File

@@ -391,7 +391,7 @@ func GetStoresSkusSaleInfo(ctx *jxcontext.Context, storeIDs []int, skuIDs []int,
WHERE t1.order_created_at >= ? AND t1.order_created_at <= ?
AND IF(t2.jx_store_id <> 0, jx_store_id, store_id) IN (` + dao.GenQuestionMarks(len(storeIDs)) + `)
`
if jxutils.IsTimeEmpty(toTime) {
if utils.IsTimeZero(toTime) {
toTime = time.Now()
}
sqlParams := []interface{}{

View File

@@ -858,10 +858,10 @@ func unmarshalCommentText(commentStr string) (retVal map[string]interface{}, isN
}
func RefreshEbaiBadComment(ctx *jxcontext.Context, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) {
if jxutils.IsTimeEmpty(fromTime) {
if utils.IsTimeZero(fromTime) {
fromTime = utils.Str2Time("2018-05-03 00:00:00")
}
if jxutils.IsTimeEmpty(toTime) {
if utils.IsTimeZero(toTime) {
toTime = time.Now().Add(-3 * time.Hour)
}
days := int(toTime.Sub(fromTime)/(24*time.Hour) + 1)

View File

@@ -369,10 +369,6 @@ func BatchStr2Time(strTime ...string) (timeList []time.Time, err error) {
return timeList, nil
}
func IsTimeEmpty(timeValue time.Time) bool {
return (timeValue == utils.DefaultTimeValue || timeValue == utils.ZeroTimeValue)
}
// strAndObjAddPairs必须按字符串1,转换地址1字符串2转换地址2这样的格式传递
func Strings2Objs(strAndObjAddPairs ...interface{}) (err error) {
str := ""

View File

@@ -102,7 +102,7 @@ func unregisterChan(storeID int, chan2Listen chan<- *ServerMsg) {
}
func getPendingOrderList(storeID int, lastOrderTime time.Time, lastOrderSeqID int64) (orderList []*model.GoodsOrderExt, err error) {
if jxutils.IsTimeEmpty(lastOrderTime) || time.Now().Sub(lastOrderTime) > maxGetOrderTimeDuration {
if utils.IsTimeZero(lastOrderTime) || time.Now().Sub(lastOrderTime) > maxGetOrderTimeDuration {
lastOrderTime = time.Now().Add(-maxGetOrderTimeDuration)
}
orderList, err = dao.GetStoreOrderAfterTime(dao.GetDB(), storeID, lastOrderTime, lastOrderSeqID)

View File

@@ -23,11 +23,10 @@ const (
)
const (
TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置
TimerTypeByPass = 1
TimerTypeBaseNow = 2
TimerTypeBaseStatusTime = 3
TimerTypeBaseExpectedDeliveredTime = 4 // 如果是定时达以expected delivery time倒推的时间当成statusTime之后与TimerTypeBaseStatusTime一样否则与TimerTypeBaseStatusTime相同
TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置
TimerTypeByPass = 1
TimerTypeBaseNow = 2
TimerTypeBaseStatusTime = 3
)
type StatusActionParams struct {
@@ -36,6 +35,18 @@ type StatusActionParams struct {
TimeoutGap int // 以秒为单位的随机时间0在GetStatusActionConfig返回时表示不修改缺省
}
func (s *StatusActionParams) GetRefTimeout(statusTime time.Time) (timeout time.Duration) {
switch s.TimerType {
case TimerTypeBaseNow:
timeout = s.Timeout
case TimerTypeBaseStatusTime:
timeout = statusTime.Sub(time.Now()) + s.Timeout
default:
timeout = 0
}
return timeout
}
var (
CancelWaybillReasonStrNotAcceptIntime = "没有及时抢单"
CancelWaybillReasonStrSwitch2SelfFailed = "转自送失败"

View File

@@ -19,8 +19,7 @@ import (
const (
// acceptOrderDelay = 180 * time.Second
pickupOrderDelay = 240 * time.Second
pickupOrderGap = 20
pickupOrderDelay = 260 * time.Second
callDeliveryDelay = 10 * time.Minute
callDeliveryDelayGap = 30
@@ -91,8 +90,8 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
ActualPayPrice: utils.MustInterface2Int64(orderMap["user_fee"]),
Skus: []*model.OrderSku{},
}
if jxutils.IsTimeEmpty(order.PickDeadline) && !jxutils.IsTimeEmpty(order.StatusTime) {
order.PickDeadline = order.StatusTime.Add(pickupOrderDelay /* + time.Duration(rand.Intn(pickupOrderGap))*time.Second*/)
if utils.IsTimeZero(order.PickDeadline) && !utils.IsTimeZero(order.StatusTime) {
order.PickDeadline = order.StatusTime.Add(pickupOrderDelay) // 饿百要求在5分钟内拣货不然订单会被取消
}
if order.ConsigneeMobile == "" {
if mobileInfo, err := api.EbaiAPI.OrderPrivateInfo(vendorOrderID); err == nil {
@@ -107,7 +106,7 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
order.BusinessType = model.BusinessTypeImmediate
} else {
order.BusinessType = model.BusinessTypeDingshida
if jxutils.IsTimeEmpty(order.ExpectedDeliveredTime) {
if utils.IsTimeZero(order.ExpectedDeliveredTime) {
order.ExpectedDeliveredTime = getTimeFromInterface(orderMap["latest_send_time"])
}
}
@@ -279,12 +278,11 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *ebaiapi.CallbackMsg) (orderSta
func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) {
if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted {
params = &partner.StatusActionParams{ // 饿百要求在5分钟内拣货不然订单会被取消
Timeout: pickupOrderDelay,
TimeoutGap: pickupOrderGap,
params = &partner.StatusActionParams{ // PickDeadline没有设置时才有效饿百要求在5分钟内拣货不然订单会被取消
Timeout: pickupOrderDelay,
}
} else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup {
params = &partner.StatusActionParams{ // 自配送延时召唤配送
params = &partner.StatusActionParams{ // 立即达订单有效,自配送延时召唤配送
Timeout: callDeliveryDelay,
TimeoutGap: callDeliveryDelayGap,
}

View File

@@ -23,8 +23,7 @@ const (
)
const (
pickupOrderDelay = 240 * time.Second
pickupOrderGap = 20
pickupOrderDelay = 260 * time.Second
callDeliveryDelay = 10 * time.Minute
callDeliveryDelayGap = 30
@@ -93,11 +92,11 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
ActualPayPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(result["total"])),
Skus: []*model.OrderSku{},
}
if jxutils.IsTimeEmpty(order.PickDeadline) && !jxutils.IsTimeEmpty(order.StatusTime) {
order.PickDeadline = order.StatusTime.Add(pickupOrderDelay /*+ time.Duration(rand.Intn(pickupOrderGap))*time.Second*/)
if utils.IsTimeZero(order.PickDeadline) && !utils.IsTimeZero(order.StatusTime) {
order.PickDeadline = order.StatusTime.Add(pickupOrderDelay) // 美团外卖要求在5分钟内拣货不然订单会被取消
}
order.Status = p.GetStatusFromVendorStatus(order.VendorStatus)
if jxutils.IsTimeEmpty(order.ExpectedDeliveredTime) {
if utils.IsTimeZero(order.ExpectedDeliveredTime) {
order.BusinessType = model.BusinessTypeImmediate
} else {
order.BusinessType = model.BusinessTypeDingshida
@@ -284,12 +283,11 @@ func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *mode
func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) {
if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted {
params = &partner.StatusActionParams{ // 美团外卖要求在5分钟内拣货不然订单会被取消
Timeout: pickupOrderDelay,
TimeoutGap: pickupOrderGap,
params = &partner.StatusActionParams{ // PickDeadline没有设置时才有效美团外卖要求在5分钟内拣货不然订单会被取消
Timeout: pickupOrderDelay,
}
} else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup {
params = &partner.StatusActionParams{ // 自配送延时召唤配送
params = &partner.StatusActionParams{ // 立即达订单有效,自配送延时召唤配送
Timeout: callDeliveryDelay,
TimeoutGap: callDeliveryDelayGap,
}