mergemark

This commit is contained in:
苏尹岚
2019-11-26 10:26:14 +08:00
25 changed files with 1208 additions and 289 deletions

View File

@@ -72,6 +72,7 @@ func (a *MiniAuther) DecryptData(authInfo *auth2.AuthInfo, jsCode, encryptedData
if err != nil {
return "", err
}
authInfo.AuthBindInfo.UserData = sessionKey
return string(decryptedData), nil
}

View File

@@ -303,7 +303,7 @@ func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao
return isDuplicated, err
}
func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao.DaoDB, storePayPercentage int) (err error) {
func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao.DaoDB, storePayPercentage, changePriceType int) (err error) {
globals.SugarLogger.Debugf("updateOrderSkuOtherInfo orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID)
jxStoreID := jxutils.GetShowStoreIDFromOrder(order)
var opNumStr string
@@ -372,9 +372,17 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao.
}
}
}
v.EarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, storePayPercentage)
// 直营店始终按比例结算,不考虑活动与结算表
salePrice := v.SalePrice
if changePriceType == model.StoreChangePriceTypeManagedStore && v.ShopPrice != 0 {
salePrice = 0
}
v.EarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, salePrice, storePayPercentage)
}
// 直营店始终按比例结算,不考虑活动与结算表
if changePriceType != model.StoreChangePriceTypeManagedStore {
updateSingleOrderEarningPrice(order, db)
}
updateSingleOrderEarningPrice(order, db)
}
return nil
}
@@ -409,6 +417,7 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao
globals.SugarLogger.Debugf("updateOrderOtherInfo orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID)
payPercentage := 0
changePriceType := model.StoreChangePriceTypeDirect
storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID)
if err != nil {
if !dao.IsNoRowsError(err) {
@@ -422,8 +431,9 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao
} else {
order.JxStoreID = storeDetail.Store.ID
payPercentage = storeDetail.PayPercentage
changePriceType = int(storeDetail.ChangePriceType)
}
if err = c.updateOrderSkuOtherInfo(order, db, payPercentage); err == nil {
if err = c.updateOrderSkuOtherInfo(order, db, payPercentage, changePriceType); err == nil {
jxutils.RefreshOrderSkuRelated(order)
// caculateOrderEarningPrice(order, payPercentage)
}
@@ -454,6 +464,11 @@ func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.Da
VendorID: orderStatus.VendorID,
}
if err = db.Db.ReadForUpdate(order, "VendorOrderID", "VendorID"); err == nil {
// todo 美团在订单完成后还可能收到订单取消应该当成售后单处理才合适强制忽略这种情况比如订单80662201436073600
// 后来又发现有订单81710104014426376在完成后直接再被取消的情况不能生成售后单还是再允许完成后取消。。。
// if orderStatus.VendorID == model.VendorIDMTWM && model.IsOrderFinalStatus(order.Status) {
// return false, order, nil
// }
if (model.IsOrderLockStatus(orderStatus.Status) || model.IsOrderUnlockStatus(orderStatus.Status)) ||
(model.IsOrderMainStatus(orderStatus.Status) && orderStatus.Status >= order.Status) { // todo 要求status不能回绕
order.VendorStatus = orderStatus.VendorStatus

View File

@@ -63,6 +63,15 @@ var (
FixedScheduler *DefScheduler
)
type tTimerInfo struct {
statusType int
vendorID int
status int
timer *time.Timer
timerTime time.Time
}
type WatchOrderInfo struct {
order *model.GoodsOrder // order里的信息是保持更新的
@@ -74,10 +83,12 @@ type WatchOrderInfo struct {
waybills map[int]*model.Waybill // 这个waybills里的状态信息是不真实的只使用id相关的信息
timerStatusType int // 0表示订单1表示运单
timerStatus int
timer *time.Timer
timerTime time.Time
// timerStatusType int // 0表示订单1表示运单
// timerStatus int
// timer *time.Timer
// timerTime time.Time
timerList []*tTimerInfo
retryCount int // 失败后尝试的次数,调试阶段可能出现死循化,阻止这种情况发生
}
@@ -88,6 +99,14 @@ type StatusActionConfig struct {
ShouldSetTimer func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool
}
func (c *StatusActionConfig) CallTimeoutAction(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
if c.TimeoutAction != nil &&
c.CallShouldSetTimer(savedOrderInfo, bill) {
err = c.TimeoutAction(savedOrderInfo, bill)
}
return err
}
func (c *StatusActionConfig) CallShouldSetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool {
if c.ShouldSetTimer != nil {
return c.ShouldSetTimer(savedOrderInfo, bill)
@@ -145,6 +164,40 @@ func (s *WatchOrderInfo) GetWaybillVendorIDs() (vendorIDs []int) {
return vendorIDs
}
// orderType-1全部
// vendorID-1全部
// status-1全部
func (w *WatchOrderInfo) StopTimer(statusType, vendorID, status int) {
var newTimerList []*tTimerInfo
for _, timerInfo := range w.timerList {
if (statusType == -1 || statusType == timerInfo.statusType) &&
(vendorID == -1 || vendorID == timerInfo.vendorID) &&
(status == -1 || status <= timerInfo.status) {
if timerInfo.timer != nil {
timerInfo.timer.Stop()
timerInfo.timer = nil
}
} else {
newTimerList = append(newTimerList, timerInfo)
}
}
w.timerList = newTimerList
}
func (w *WatchOrderInfo) GetCreateWaybillTimeout() (timeoutSecond int) {
// if w.timerStatusType == scheduler.TimerStatusTypeWaybill && w.timerStatus == model.WaybillStatusNew {
// timeoutSecond = int(w.timerTime.Sub(time.Now()) / time.Second)
// }
for _, timerInfo := range w.timerList {
if timerInfo.statusType == scheduler.TimerStatusTypeWaybill &&
timerInfo.status == model.WaybillStatusNew {
timeoutSecond = int(timerInfo.timerTime.Sub(time.Now()) / time.Second)
break
}
}
return timeoutSecond
}
func init() {
sch := &DefScheduler{}
basesch.FixedBaseScheduler = &sch.BaseScheduler
@@ -159,41 +212,39 @@ func init() {
Timeout: 10 * time.Millisecond,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
if savedOrderInfo.order.LockStatus == model.LockStatusUnlocked && savedOrderInfo.order.Status == model.OrderStatusNew {
order := savedOrderInfo.order
mobile := order.ConsigneeMobile
if order.ConsigneeMobile2 != "" {
mobile = order.ConsigneeMobile2
}
_ = sch.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, mobile, jxutils.GetSaleStoreIDFromOrder(order), nil, func(isAcceptIt bool) error {
if err = sch.AcceptOrRefuseOrder(order, isAcceptIt, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation {
partner.CurOrderManager.OnOrderMsg(order, "自动接单失败", err.Error())
// 为了解决京东新消息与接单消息乱序的问题
if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 && errWithCode.IntCode() == -1 {
if order2, err2 := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrder(order.VendorOrderID); err2 == nil {
if order2.Status > order.Status {
order.Status = order2.Status
jxutils.CallMsgHandlerAsync(func() {
sch.OnOrderStatusChanged(order, model.Order2Status(order2), false)
}, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID))
err = nil
}
} else {
err = err2
}
}
}
if isAcceptIt {
if err == nil {
sch.notifyNewOrder(order)
msghub.OnNewOrder(order)
}
} else {
partner.CurOrderManager.OnOrderMsg(order, "黑名单拒单", "")
}
return err
})
order := savedOrderInfo.order
mobile := order.ConsigneeMobile
if order.ConsigneeMobile2 != "" {
mobile = order.ConsigneeMobile2
}
_ = sch.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, mobile, jxutils.GetSaleStoreIDFromOrder(order), nil, func(isAcceptIt bool) error {
if err = sch.AcceptOrRefuseOrder(order, isAcceptIt, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation {
partner.CurOrderManager.OnOrderMsg(order, "自动接单失败", err.Error())
// 为了解决京东新消息与接单消息乱序的问题
if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 && errWithCode.IntCode() == -1 {
if order2, err2 := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrder(order.VendorOrderID); err2 == nil {
if order2.Status > order.Status {
order.Status = order2.Status
jxutils.CallMsgHandlerAsync(func() {
sch.OnOrderStatusChanged(order, model.Order2Status(order2), false)
}, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID))
err = nil
}
} else {
err = err2
}
}
}
if isAcceptIt {
if err == nil {
sch.notifyNewOrder(order)
msghub.OnNewOrder(order)
}
} else {
partner.CurOrderManager.OnOrderMsg(order, "黑名单拒单", "")
}
return err
})
return nil
},
ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool {
@@ -207,10 +258,8 @@ func init() {
TimeoutGap: second2AutoPickupGap,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
if savedOrderInfo.autoPickupTimeoutMinute > 0 {
if err = sch.autoPickupGood(savedOrderInfo); err != nil {
partner.CurOrderManager.OnOrderMsg(savedOrderInfo.order, "自动拣货失败", err.Error())
}
if err = sch.autoPickupGood(savedOrderInfo); err != nil {
partner.CurOrderManager.OnOrderMsg(savedOrderInfo.order, "自动拣货失败", err.Error())
}
return nil
},
@@ -225,15 +274,12 @@ func init() {
TimeoutGap: 0,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
if model.IsOrderDeliveryByStore(savedOrderInfo.order) { // 自配送商家使用
// 启动抢单TIMER
sch.saveDeliveryFeeFromAndStartWatch(savedOrderInfo, savedOrderInfo.order.StatusTime)
return sch.createWaybillOn3rdProviders(savedOrderInfo, 0, nil)
}
return nil
// 启动抢单TIMER
sch.saveDeliveryFeeFromAndStartWatch(savedOrderInfo, savedOrderInfo.order.StatusTime)
return sch.createWaybillOn3rdProviders(savedOrderInfo, 0, nil)
},
ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool {
return model.IsOrderDeliveryByStore(savedOrderInfo.order)
return model.IsOrderDeliveryByStore(savedOrderInfo.order) // 自配送商家使用
},
},
},
@@ -245,17 +291,11 @@ func init() {
Timeout: minute2Schedule3rdCarrier * time.Minute,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
// 饿百转自送的时机不太清楚,暂时禁用超时转自送,在饿百运单取消时还是会自动创建
if savedOrderInfo.isDeliveryCompetition &&
model.IsOrderDeliveryByPlatform(savedOrderInfo.order) &&
savedOrderInfo.order.VendorID == bill.WaybillVendorID &&
savedOrderInfo.order.VendorID != model.VendorIDEBAI &&
savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake { // 非自配送商家使用
return sch.createWaybillOn3rdProviders(savedOrderInfo, 0, nil)
}
return nil
return sch.createWaybillOn3rdProviders(savedOrderInfo, 0, nil)
},
ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool {
// 饿百转自送的时机不太清楚,暂时禁用超时转自送,在饿百运单取消时还是会自动创建
// 非自配送商家使用
return savedOrderInfo.isDeliveryCompetition &&
model.IsOrderDeliveryByPlatform(savedOrderInfo.order) &&
savedOrderInfo.order.VendorID == bill.WaybillVendorID &&
@@ -270,19 +310,11 @@ func init() {
Timeout: 5 * time.Second,
},
TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) {
order := savedOrderInfo.order
if (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) &&
savedOrderInfo.isDeliveryCompetition &&
savedOrderInfo.order.VendorID == bill.WaybillVendorID &&
model.IsOrderDeliveryByPlatform(savedOrderInfo.order) &&
order.VendorID == model.VendorIDEBAI &&
savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake { // 非自配送商家使用
return sch.createWaybillOn3rdProviders(savedOrderInfo, ebaiCancelWaybillMaxFee, nil)
}
return nil
return sch.createWaybillOn3rdProviders(savedOrderInfo, ebaiCancelWaybillMaxFee, nil)
},
ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool {
order := savedOrderInfo.order
// 非自配送商家使用
return (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) &&
savedOrderInfo.isDeliveryCompetition &&
savedOrderInfo.order.VendorID == bill.WaybillVendorID &&
@@ -739,91 +771,169 @@ func (s *DefScheduler) loadSavedOrderFromMap(status *model.OrderStatus, isForceL
return realSavedInfo
}
func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) {
if savedOrderInfo.timer != nil {
globals.SugarLogger.Debugf("stopTimer orderID:%s", savedOrderInfo.order.VendorOrderID)
savedOrderInfo.timer.Stop()
savedOrderInfo.timerStatus = model.OrderStatusUnknown
savedOrderInfo.timerStatusType = scheduler.TimerStatusTypeUnknown
savedOrderInfo.timer = nil
}
}
func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Waybill, isPending bool) {
order := savedOrderInfo.order
status := order.Status
statusType := scheduler.TimerStatusTypeOrder
vendorID := order.VendorID
statusTime := order.StatusTime
if bill != nil {
status = bill.Status
statusType = scheduler.TimerStatusTypeWaybill
vendorID = bill.WaybillVendorID
statusTime = bill.StatusTime
}
globals.SugarLogger.Debugf("resetTimer, orderID:%s statusType:%d status:%d", order.VendorOrderID, statusType, status)
if isStatusNewer(order.VendorID, savedOrderInfo.timerStatusType, savedOrderInfo.timerStatus, statusType, status) { // 新设置的TIMER不能覆盖状态在其后的TIMER如果状态回绕需要注意
config := s.mergeOrderStatusConfig(savedOrderInfo, statusTime, statusType, status)
if config == nil || config.TimerType != partner.TimerTypeByPass {
s.stopTimer(savedOrderInfo)
config := s.mergeOrderStatusConfig(savedOrderInfo, statusTime, statusType, status)
stopStatusType := statusType
stopStatus := status
if statusType == scheduler.TimerStatusTypeOrder {
if status >= model.OrderStatusDelivering {
stopStatusType = -1
stopStatus = -1
}
if config != nil && config.TimeoutAction != nil && config.TimerType != partner.TimerTypeByPass {
if config.CallShouldSetTimer(savedOrderInfo, bill) {
timeout := config.GetRefTimeout(statusTime, order.OrderCreatedAt)
if config.TimeoutGap != 0 {
timeout += time.Duration(rand.Intn(int(config.TimeoutGap))) * time.Second
}
if isPending && timeout < pendingOrderTimerMaxSecond*time.Second { // 如果是PENDING的订单则将其分布到2--5秒内让后续事件有机会执行
timeout = time.Duration(jxutils.MapValue2Scope(int64(timeout), -pendingOrderTimerMinMinSecond*1000, pendingOrderTimerMaxSecond*1000, pendingOrderTimerMinSecond*1000, pendingOrderTimerMaxSecond*1000)) * time.Millisecond
} else if timeout < 0 {
timeout = 0
}
if timeout == 0 {
config.TimeoutAction(savedOrderInfo, bill)
} else {
timerName := ""
if statusType == scheduler.TimerStatusTypeOrder {
timerName = model.OrderStatusName[status]
} else if statusType == scheduler.TimerStatusTypeWaybill {
timerName = model.WaybillStatusName[status]
}
savedOrderInfo.timerStatusType = statusType
savedOrderInfo.timerStatus = status
savedOrderInfo.timerTime = time.Now().Add(timeout)
savedOrderInfo.timer = utils.AfterFuncWithRecover(timeout, func() {
jxutils.CallMsgHandlerAsync(func() {
globals.SugarLogger.Debugf("fire timer:%s, orderID:%s", timerName, order.VendorOrderID)
savedOrderInfo := s.loadSavedOrderFromMap(model.Order2Status(order), true)
config.TimeoutAction(savedOrderInfo, bill)
savedOrderInfo.timerStatus = 0
savedOrderInfo.timerStatusType = scheduler.TimerStatusTypeUnknown
}, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID))
})
}
globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, timeout:%v", order.VendorOrderID, statusType, status, timeout)
} else {
globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, should not set timer", order.VendorOrderID, statusType, status)
}
if config == nil || config.TimerType != partner.TimerTypeByPass {
savedOrderInfo.StopTimer(stopStatusType, -1, stopStatus)
}
if config != nil && config.TimeoutAction != nil && config.TimerType != partner.TimerTypeByPass {
if config.CallShouldSetTimer(savedOrderInfo, bill) {
timeout := config.GetRefTimeout(statusTime, order.OrderCreatedAt)
if config.TimeoutGap != 0 {
timeout += time.Duration(rand.Intn(int(config.TimeoutGap))) * time.Second
}
if isPending && timeout < pendingOrderTimerMaxSecond*time.Second { // 如果是PENDING的订单则将其分布到2--5秒内让后续事件有机会执行
timeout = time.Duration(jxutils.MapValue2Scope(int64(timeout), -pendingOrderTimerMinMinSecond*1000, pendingOrderTimerMaxSecond*1000, pendingOrderTimerMinSecond*1000, pendingOrderTimerMaxSecond*1000)) * time.Millisecond
} else if timeout < 0 {
timeout = 0
}
if timeout == 0 {
config.CallTimeoutAction(savedOrderInfo, bill)
} else {
timerName := ""
if statusType == model.OrderTypeOrder {
timerName = model.OrderStatusName[status]
} else if statusType == model.OrderTypeWaybill {
timerName = model.WaybillStatusName[status]
}
timerInfo := &tTimerInfo{
statusType: statusType,
vendorID: vendorID,
status: status,
timerTime: time.Now().Add(timeout),
}
timerInfo.timer = utils.AfterFuncWithRecover(timeout, func() {
jxutils.CallMsgHandlerAsync(func() {
globals.SugarLogger.Debugf("fire timer:%s, orderID:%s", timerName, order.VendorOrderID)
ts := s.loadSavedOrderFromMap(model.Order2Status(order), true)
config.CallTimeoutAction(ts, bill)
timerInfo.timer = nil
ts.StopTimer(statusType, vendorID, status)
}, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID))
})
}
globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, timeout:%v", order.VendorOrderID, statusType, status, timeout)
} else {
globals.SugarLogger.Debugf("resetTimer bypass2, orderID:%s statusType:%d status:%v, config:%s", order.VendorOrderID, statusType, status, utils.Format4Output(config, true))
globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, should not set timer", order.VendorOrderID, statusType, status)
}
} else {
globals.SugarLogger.Debugf("resetTimer bypass1, orderID:%s statusType:%d status:%v", order.VendorOrderID, statusType, status)
globals.SugarLogger.Debugf("resetTimer bypass2, orderID:%s statusType:%d status:%v, config:%s", order.VendorOrderID, statusType, status, utils.Format4Output(config, true))
}
}
func isStatusNewer(vendorID int, curStatusType, curStatus, statusType, status int) bool {
// 拣货完成及之前的订单事件TIMER不能覆盖运单TIMER一般是消息错序引起的
// 美团订单在接单后就会收到新运单事件因当前只支持一个TIMER暂时舍弃三方配送调度而要自动拣货调度
if vendorID != model.VendorIDMTWM {
if curStatusType == scheduler.TimerStatusTypeWaybill && statusType == scheduler.TimerStatusTypeOrder && status <= model.OrderStatusFinishedPickup {
return false
}
}
if curStatusType == scheduler.TimerStatusTypeWaybill {
return curStatus != status
}
return curStatusType != statusType || status >= curStatus
func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) {
savedOrderInfo.StopTimer(-1, -1, -1)
}
// func (s *DefScheduler) stopTimer(savedOrderInfo *WatchOrderInfo) {
// if savedOrderInfo.timer != nil {
// globals.SugarLogger.Debugf("stopTimer orderID:%s", savedOrderInfo.order.VendorOrderID)
// savedOrderInfo.timer.Stop()
// savedOrderInfo.timerStatus = model.OrderStatusUnknown
// savedOrderInfo.timerStatusType = scheduler.TimerStatusTypeUnknown
// savedOrderInfo.timer = nil
// }
// }
// func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Waybill, isPending bool) {
// order := savedOrderInfo.order
// status := order.Status
// statusType := scheduler.TimerStatusTypeOrder
// statusTime := order.StatusTime
// if bill != nil {
// status = bill.Status
// statusType = scheduler.TimerStatusTypeWaybill
// statusTime = bill.StatusTime
// }
// globals.SugarLogger.Debugf("resetTimer, orderID:%s statusType:%d status:%d", order.VendorOrderID, statusType, status)
// if isStatusNewer(order.VendorID, savedOrderInfo.timerStatusType, savedOrderInfo.timerStatus, statusType, status) { // 新设置的TIMER不能覆盖状态在其后的TIMER如果状态回绕需要注意
// 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 {
// if config.CallShouldSetTimer(savedOrderInfo, bill) {
// timeout := config.GetRefTimeout(statusTime, order.OrderCreatedAt)
// if config.TimeoutGap != 0 {
// timeout += time.Duration(rand.Intn(int(config.TimeoutGap))) * time.Second
// }
// if isPending && timeout < pendingOrderTimerMaxSecond*time.Second { // 如果是PENDING的订单则将其分布到2--5秒内让后续事件有机会执行
// timeout = time.Duration(jxutils.MapValue2Scope(int64(timeout), -pendingOrderTimerMinMinSecond*1000, pendingOrderTimerMaxSecond*1000, pendingOrderTimerMinSecond*1000, pendingOrderTimerMaxSecond*1000)) * time.Millisecond
// } else if timeout < 0 {
// timeout = 0
// }
// if timeout == 0 {
// config.CallTimeoutAction(savedOrderInfo, bill)
// } else {
// timerName := ""
// if statusType == scheduler.TimerStatusTypeOrder {
// timerName = model.OrderStatusName[status]
// } else if statusType == scheduler.TimerStatusTypeWaybill {
// timerName = model.WaybillStatusName[status]
// }
// savedOrderInfo.timerStatusType = statusType
// savedOrderInfo.timerStatus = status
// savedOrderInfo.timerTime = time.Now().Add(timeout)
// savedOrderInfo.timer = utils.AfterFuncWithRecover(timeout, func() {
// jxutils.CallMsgHandlerAsync(func() {
// globals.SugarLogger.Debugf("fire timer:%s, orderID:%s", timerName, order.VendorOrderID)
// savedOrderInfo := s.loadSavedOrderFromMap(model.Order2Status(order), true)
// config.CallTimeoutAction(savedOrderInfo, bill)
// savedOrderInfo.timerStatus = 0
// savedOrderInfo.timerStatusType = scheduler.TimerStatusTypeUnknown
// }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID))
// })
// }
// globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, timeout:%v", order.VendorOrderID, statusType, status, timeout)
// } else {
// globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, should not set timer", order.VendorOrderID, statusType, status)
// }
// } else {
// globals.SugarLogger.Debugf("resetTimer bypass2, orderID:%s statusType:%d status:%v, config:%s", order.VendorOrderID, statusType, status, utils.Format4Output(config, true))
// }
// } else {
// globals.SugarLogger.Debugf("resetTimer bypass1, orderID:%s statusType:%d status:%v", order.VendorOrderID, statusType, status)
// }
// }
// func isStatusNewer(vendorID int, curStatusType, curStatus, statusType, status int) bool {
// // 拣货完成及之前的订单事件TIMER不能覆盖运单TIMER一般是消息错序引起的
// // 美团订单在接单后就会收到新运单事件因当前只支持一个TIMER暂时舍弃三方配送调度而要自动拣货调度
// if vendorID != model.VendorIDMTWM {
// if curStatusType == scheduler.TimerStatusTypeWaybill && statusType == scheduler.TimerStatusTypeOrder && status <= model.OrderStatusFinishedPickup {
// return false
// }
// } else {
// return statusType == scheduler.TimerStatusTypeOrder && status >= curStatus
// }
// if curStatusType == scheduler.TimerStatusTypeWaybill {
// return curStatus != status
// }
// return curStatusType != statusType || status >= curStatus
// }
func (s *DefScheduler) mergeOrderStatusConfig(savedOrderInfo *WatchOrderInfo, statusTime time.Time, statusType, status int) (retVal *StatusActionConfig) {
s.locker.RLock()
defer func() {
@@ -1015,6 +1125,10 @@ func getMaxDeliveryFee(order *model.GoodsOrder) (maxDeliveryFee int64) {
} else {
maxDeliveryFee = baseWaybillFee + order.DistanceFreightMoney + getWaybillTip(order)
}
if maxDeliveryFee < ebaiCancelWaybillMaxFee &&
order.DeliveryType == model.OrderDeliveryTypeStoreSelf {
maxDeliveryFee = ebaiCancelWaybillMaxFee
}
return maxDeliveryFee
}

View File

@@ -226,9 +226,7 @@ func (s *DefScheduler) QueryOrderWaybillFeeInfoEx(ctx *jxcontext.Context, vendor
var timeoutSecond int
if savedOrderInfo := s.loadSavedOrderByID(vendorOrderID, vendorID, false); savedOrderInfo != nil {
if savedOrderInfo.timerStatusType == scheduler.TimerStatusTypeWaybill && savedOrderInfo.timerStatus == model.WaybillStatusNew {
timeoutSecond = int(savedOrderInfo.timerTime.Sub(time.Now()) / time.Second)
}
timeoutSecond = savedOrderInfo.GetCreateWaybillTimeout()
}
for _, storeCourier := range storeCourierList {
var feeInfo *partner.WaybillFeeInfo

View File

@@ -150,7 +150,6 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac
jxPrice := storeSkuInfo.Price
actSkuMap.VendorPrice = int64(getVendorPriceFromStoreSkuBind(storeSkuInfo, vendorID))
v.OriginalPrice = int64(jxPrice)
v.OriginalPrice = actSkuMap.VendorPrice // 暂时返回平台价
}
var err2 error
if act.Type != model.ActSkuFake { // 非结算,要计算实际活动价格
@@ -629,10 +628,6 @@ func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, act
if len(actMap) == 0 {
return 0, fmt.Errorf("找不到活动:%d或已被取消", actID)
}
if actMap[0].Status != model.ActStatusCreated {
// 如果不是正常状态直接跳过
return 0, nil
}
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, nil, nil)
if err != nil {

View File

@@ -754,8 +754,10 @@ func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interfa
if (outStore.OpenTime2 == 0 && outStore.CloseTime2 != 0) || (outStore.OpenTime2 != 0 && outStore.CloseTime2 == 0) {
return 0, errors.New(fmt.Sprintf("门店营业时间2设置不合法时间范围2 [%v] 至 [%v]", outStore.OpenTime1, outStore.CloseTime1))
}
if outStore.OpenTime2 > outStore.OpenTime1 {
return 0, errors.New(fmt.Sprintf("门店营业时间设置不合法!第二段营业时间应该在第一段营业时间之后!"))
if outStore.OpenTime1 != 0 && outStore.CloseTime1 != 0 && outStore.OpenTime2 != 0 && outStore.CloseTime2 != 0 {
if outStore.OpenTime2 < outStore.CloseTime1 {
return 0, errors.New(fmt.Sprintf("门店营业时间设置不合法!第二段营业时间应该在第一段营业时间之后!"))
}
}
if beginAt, endAt := GetTimeMixByInt(outStore.OpenTime1, outStore.CloseTime1, outStore.OpenTime2, outStore.CloseTime2); beginAt != 0 && endAt != 0 {
return 0, errors.New(fmt.Sprintf("两段门店营业时间不可交叉时间范围1 [%v] 至 [%v], 时间范围2 [%v] 至 [%v]", outStore.OpenTime1, outStore.CloseTime1, outStore.OpenTime2, outStore.CloseTime2))

View File

@@ -79,6 +79,9 @@ type StoreSkuExt struct {
RealEarningPrice int `json:"realEarningPrice"`
StatusSaleBegin int16 `json:"statusSaleBegin"` //商品可售时间范围
StatusSaleEnd int16 `json:"statusSaleEnd"`
Count int `json:"count"`
Times int `json:"times"`
}
@@ -451,7 +454,8 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo
t4.sub_store_id, t4.price bind_price, IF(t4.unit_price IS NOT NULL, t4.unit_price, t1.price) unit_price, t4.status store_sku_status, t4.auto_sale_at,
t4.ebai_id, t4.mtwm_id,
t4.jd_sync_status, t4.ebai_sync_status, t4.mtwm_sync_status,
t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price
t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price,
t4.status_sale_begin, t4.status_sale_end
` + sql
var tmpList []*tGetStoresSkusInfo
beginTime := time.Now()

View File

@@ -441,7 +441,8 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
}
return skuList
}
task := tasksch.NewParallelTask("syncStoreSkuNew", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx,
isContinueWhenError2 := true
task := tasksch.NewParallelTask("syncStoreSkuNew", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError2), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
step := batchItemList[0].(int)
// globals.SugarLogger.Debugf("step:%d", step)
@@ -462,7 +463,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagDeletedMask)
}
return nil, len(successList), err
}, ctx, task, deleteList, 1 /*singleStoreHandler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus)*/, isContinueWhenError)
}, ctx, task, deleteList, 1 /*singleStoreHandler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus)*/, isContinueWhenError2)
}
case 1:
if len(createList) > 0 {
@@ -494,7 +495,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
updateStoreSku(dao.GetDB(), vendorID, successList, model.SyncFlagNewMask)
}
return nil, len(successList), err
}, ctx, task, createList, 1 /*singleStoreHandler.GetStoreSkusBatchSize(partner.FuncCreateStoreSkus)*/, isContinueWhenError)
}, ctx, task, createList, 1 /*singleStoreHandler.GetStoreSkusBatchSize(partner.FuncCreateStoreSkus)*/, isContinueWhenError2)
}
case 2:
if len(updateList) > 0 {
@@ -507,7 +508,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
updateStoreSku(dao.GetDB(), vendorID, successList, model.SyncFlagModifiedMask)
}
return nil, len(successList), err
}, ctx, task, updateList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkus), isContinueWhenError)
}, ctx, task, updateList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkus), isContinueWhenError2)
}
case 3:
for k, list := range [][]*partner.StoreSkuInfo{stockList /*, onlineList*/} {
@@ -526,7 +527,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagStockMask)
}
return nil, len(successList), err
}, ctx, task, list, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStock), isContinueWhenError)
}, ctx, task, list, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStock), isContinueWhenError2)
}
}
case 4, 5:
@@ -550,7 +551,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagSaleMask)
}
return nil, len(successList), err
}, ctx, task, statusList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStatus), isContinueWhenError)
}, ctx, task, statusList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStatus), isContinueWhenError2)
}
case 6:
if len(priceList) > 0 {
@@ -565,7 +566,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagPriceMask)
}
return nil, len(successList), err
}, ctx, task, priceList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusPrice), isContinueWhenError)
}, ctx, task, priceList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusPrice), isContinueWhenError2)
}
case 7:
if len(reorderSkuMap) > 0 {
@@ -573,7 +574,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
for vendorCatID := range reorderSkuMap {
vendorCatIDs = append(vendorCatIDs, vendorCatID)
}
reorderTask := tasksch.NewParallelTask("门店商品排序", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
reorderTask := tasksch.NewParallelTask("门店商品排序", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError2), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
vendorCatID := batchItemList[0].(string)
skuList := reorderSkuMap[vendorCatID]

View File

@@ -146,11 +146,14 @@ func doDailyWork() {
cms.SyncStoresCourierInfo(jxcontext.AdminCtx, nil, false, true)
netprinter.RebindAllPrinters(jxcontext.AdminCtx, false, true)
// cms.CurVendorSync.FullSyncStoresSkus(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDJD}, nil, false, true, true)
cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDJD}, nil, false, nil, []int{27379}, model.SyncFlagSaleMask|model.SyncFlagPriceMask, true, true)
syncFlag := model.SyncFlagPriceMask
if (time.Now().Unix()/24*3600)%10 == 0 {
syncFlag |= model.SyncFlagSaleMask
}
cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDJD}, nil, false, nil, []int{27379}, syncFlag, true, true)
SaveImportantTaskID(TaskNameSyncStoreSku, SpecialTaskID)
taskID, _ := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDEBAI, model.VendorIDMTWM}, nil, false, nil, nil, model.SyncFlagSaleMask|model.SyncFlagPriceMask, true, true)
taskID, _ := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDEBAI, model.VendorIDMTWM}, nil, false, nil, nil, syncFlag, true, true)
SaveImportantTaskID(TaskNameSyncStoreSku, taskID)
InitEx()

View File

@@ -8,11 +8,13 @@ import (
"image/png"
"net/http"
"regexp"
"strings"
"sync"
"time"
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
"git.rosy.net.cn/jx-callback/business/partner/delivery"
"github.com/360EntSecGroup-Skylar/excelize"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
@@ -1302,3 +1304,58 @@ func FixMtwmCategory(ctx *jxcontext.Context, mtwmStoreIDs []int, isAsync, isCont
}
return hint, err
}
func JdStoreInfo1125() (hint string, err error) {
fileName := "/Users/xujianhua/Downloads/老格恢复拓店进度.xlsx"
db := dao.GetDB()
storeList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, model.StoreStatusAll, model.StoreIsSyncYes, "")
if err == nil {
var validStoreList []*dao.StoreDetail
for _, v := range storeList {
if v.Status != model.StoreStatusDisabled && v.CreatedAt.Sub(utils.Str2Time("2019-10-01")) > 0 {
storeInfo, err := api.JdAPI.GetStoreInfoByStationNo2(v.VendorStoreID)
if err == nil && storeInfo.CreateTime.GoTime().Sub(utils.Str2Time("2019-10-25")) > 0 {
if storeDetail, err := dao.GetStoreDetail(db, v.StoreID, v.VendorID); err == nil {
validStoreList = append(validStoreList, storeDetail)
}
}
}
}
getStoreList := func(lng, lat, lng2, lat2 int) (vendorStoreIDs []string) {
for _, v := range validStoreList {
if v.Lng >= lng && v.Lng <= lng2 && v.Lat >= lat && v.Lat <= lat2 {
vendorStoreIDs = append(vendorStoreIDs, v.VendorStoreID)
}
}
return vendorStoreIDs
}
sheetName := "老格明细"
file, err2 := excelize.OpenFile(fileName)
if err = err2; err == nil {
// globals.SugarLogger.Debug(err, file)
rows, err2 := file.GetRows(sheetName)
if err = err2; err == nil {
str2Coords := func(str string) (lng, lat int) {
list := strings.Split(str, ",")
if len(list) >= 2 {
lng, lat = jxutils.StandardCoordinate2Int(utils.Str2Float64WithDefault(list[1], 0)), jxutils.StandardCoordinate2Int(utils.Str2Float64WithDefault(list[0], 0))
}
return lng, lat
}
for i := 1; i < len(rows); i++ {
lng, lat := str2Coords(rows[i][8])
lng2, lat2 := str2Coords(rows[i][7])
vendorStoreIDs := getStoreList(lng, lat, lng2, lat2)
// fmt.Printf("%d,%v", i, vendorStoreIDs)
countInfo := fmt.Sprintf("京西已拓%d", len(vendorStoreIDs))
axis, _ := excelize.CoordinatesToCellName(5, i+1)
file.SetCellStr(sheetName, axis, countInfo)
axis2, _ := excelize.CoordinatesToCellName(6, i+1)
file.SetCellStr(sheetName, axis2, strings.Join(vendorStoreIDs, ","))
}
file.SaveAs("ffff.xlsx")
}
}
}
return hint, err
}

View File

@@ -0,0 +1,26 @@
package tempop
import (
"testing"
"git.rosy.net.cn/jx-callback/globals/api2"
"git.rosy.net.cn/jx-callback/globals/testinit"
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/elm"
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm"
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/weimob/wsc"
)
func init() {
testinit.Init()
api2.Init()
}
func TestJdStoreInfo1125(t *testing.T) {
_, err := JdStoreInfo1125()
if err != nil {
t.Fatal(err)
}
}

View File

@@ -6,16 +6,25 @@ import (
"io"
"math"
"mime/multipart"
"strings"
"sync"
"time"
"unicode"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/utils"
"github.com/360EntSecGroup-Skylar/excelize"
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/platformapi/weimobapi"
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
"git.rosy.net.cn/jx-callback/business/jxutils/excel"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals"
@@ -26,64 +35,156 @@ import (
type SheetParam struct {
SkuIDCol int
SkuPriceCol int
SkuNameCol int
OrgSkuIdCol int
OrgSkuPriceCol int
OrgSkuNameCol int
SkuRow int
}
type DataSuccessLock struct {
dataSuccessList []DataSuccess
locker sync.RWMutex
}
type DataFailedLock struct {
dataFailedList []DataFailed
locker sync.RWMutex
}
type DataSuccess struct {
NameID string `json:"商品nameID"`
Name string `json:"商品名称"`
Unit string `json:"单位"`
OrgPrice float64 `json:"原价"`
NowPrice float64 `json:"现价"`
MixPrice float64 `json:"涨跌"`
}
type DataFailed struct {
GoodsID string `json:"商品ID"`
GoodsName string `json:"商品名称"`
Comment string `json:"备注"`
}
type Data struct {
GoodsID string `json:"商品编码"`
GoodsName string `json:"商品名称"`
GoodsNum int `json:"订货数量"`
}
type ExcelParam struct {
SpuCode string
Name string
Price float64
}
type OrderList struct {
Name string `json:"name"`
Phone string `json:"phone"`
OrderNo int64 `json:"orderNo"`
}
var (
sheetMap = map[string]*SheetParam{
"蔬菜": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 14,
SkuNameCol: 1,
OrgSkuIdCol: 5,
OrgSkuPriceCol: 8,
OrgSkuNameCol: 6,
SkuRow: 2,
}, "水果": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 14,
SkuNameCol: 1,
OrgSkuIdCol: 5,
OrgSkuPriceCol: 8,
OrgSkuNameCol: 6,
SkuRow: 2,
}, "肉禽": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 12,
SkuNameCol: 1,
OrgSkuIdCol: 4,
OrgSkuPriceCol: 7,
OrgSkuNameCol: 5,
SkuRow: 1,
}, "净配": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 12,
SkuNameCol: 1,
OrgSkuIdCol: 4,
OrgSkuPriceCol: 7,
OrgSkuNameCol: 5,
SkuRow: 1,
}, "水产": &SheetParam{
SkuIDCol: 1,
SkuPriceCol: 15,
SkuNameCol: 2,
OrgSkuIdCol: 6,
OrgSkuPriceCol: 9,
OrgSkuNameCol: 7,
SkuRow: 1,
}, "干货": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 13,
SkuNameCol: 1,
OrgSkuIdCol: 4,
OrgSkuPriceCol: 7,
OrgSkuNameCol: 5,
SkuRow: 2,
}, "MINI肉禽价格": &SheetParam{
SkuIDCol: 1,
SkuPriceCol: 5,
SkuNameCol: 2,
OrgSkuIdCol: -1,
OrgSkuPriceCol: -1,
OrgSkuNameCol: -1,
SkuRow: 1,
},
}
titleListSuccess = []string{
"商品nameID",
"商品名称",
"单位",
"原价",
"现价",
"涨跌",
}
titleListFailed = []string{
"商品ID",
"商品名称",
"备注",
}
titleList = []string{
"商品编码",
"商品名称",
"订货数量",
}
dataSuccess DataSuccessLock
dataFailed DataFailedLock
)
const (
parallelCount = 5
UpdateGoodsShelfStatusCount = 50 //微盟下架商品api限制一次50个
fileExt = ".xlsx"
)
func (d *DataSuccessLock) AppendData(dataSuccess DataSuccess) {
d.locker.Lock()
defer d.locker.Unlock()
d.dataSuccessList = append(d.dataSuccessList, dataSuccess)
}
func (d *DataFailedLock) AppendData2(dataFailed DataFailed) {
d.locker.Lock()
defer d.locker.Unlock()
d.dataFailedList = append(d.dataFailedList, dataFailed)
}
func LoadExcelByYongHui(ctx *jxcontext.Context, files []*multipart.FileHeader, isAsync, isContinueWhenError bool) (hint string, err error) {
if len(files) == 0 {
return "", errors.New("没有文件上传!")
@@ -99,11 +200,12 @@ func LoadExcelByYongHui(ctx *jxcontext.Context, files []*multipart.FileHeader, i
func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
skuMap = make(map[string]float64)
skuMap = make(map[string]*ExcelParam)
errMsg string
costPrice float64 //成本价
goodsList []*weimobapi.GoodsInfo
goodsIDListForPutAway []interface{}
isCompare bool
)
db := dao.GetDB()
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
@@ -121,7 +223,7 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
if rowNum < sheetParam.SkuRow {
continue
}
GetCellIntoMap(sheetParam.SkuIDCol, sheetParam.SkuPriceCol, sheetParam.OrgSkuIdCol, sheetParam.OrgSkuPriceCol, skuMap, row, k, rowNum)
GetCellIntoMap(sheetParam, skuMap, row, k, rowNum)
if len(skuMap) < 1 {
errMsg += fmt.Sprintf("读取Excel数据失败Excel格式排版可能发生了变化sheetName: [%v]\n", k)
}
@@ -133,10 +235,14 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
//修改分组名
// 分类名格式为可定XX日
// XX为上传永辉 提供的 价格表时间 +2天
isCompare, err = UpdateClassifyAndGetLastClassify()
case 1:
//获取微盟所有商品
goodsList, err = GetWeiMobGoodsList()
param := &weimobapi.QueryGoodsListParam{
PageNum: 1,
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds,
}
goodsList, err = GetWeiMobGoodsList(param)
if err != nil {
baseapi.SugarLogger.Errorf("GetWeiMobGoodsList error:%v", err)
}
@@ -157,12 +263,15 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
for k, _ := range skuMap {
//表示excel上有微盟上没有
if goodsInfoAndDetailMap[k] == nil {
errMsg += fmt.Sprintf("在微盟上未找到该商品excel商品ID : [%v]\n", k)
outPutData := DataFailed{
GoodsID: k,
GoodsName: skuMap[k].Name,
Comment: "在微盟上未找到该商品",
}
dataFailed.AppendData2(outPutData)
// errMsg += fmt.Sprintf("在微盟上未找到该商品xxx", xxx)
}
}
// if errMsg != "" {
// return "", errors.New(errMsg)
// }
case 2:
//找出微盟上有excel上没有的有就更新没有就下架
taskFunc3 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
@@ -171,24 +280,28 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
spuCode := goodsDetail.OuterGoodsCode
if spuCode != "" {
//如果微盟商品里找得到excel中的商品
if skuMap[spuCode] != 0 {
if skuMap[spuCode] != nil {
//获取京西库商品
skuList, _ := dao.GetSkus(db, nil, []int{int(utils.Str2Int64(goodsDetail.SkuMap.SingleSku.OuterSkuCode))}, nil, nil)
if len(skuList) == 0 {
return "", errors.New(fmt.Sprintf("在京西库中未找到该商品name_id : [%v]\n", goodsDetail.SkuMap.SingleSku.OuterSkuCode))
outPutData := DataFailed{
GoodsID: spuCode,
GoodsName: skuMap[spuCode].Name,
Comment: "在京西库中未找到该商品",
}
dataFailed.AppendData2(outPutData)
// return "", errors.New(fmt.Sprintf("在京西库中未找到该商品name_id : [%v]\n", goodsDetail.SkuMap.SingleSku.OuterSkuCode))
} else {
if skuList[0].Unit == "份" {
if goodsDetail.SkuMap.SingleSku.B2CSku.Weight == 0 {
costPrice = skuMap[spuCode]
costPrice = skuMap[spuCode].Price
} else {
costPrice = Float64Round(0.5 / goodsDetail.SkuMap.SingleSku.B2CSku.Weight * skuMap[spuCode])
costPrice = Float64Round(0.5 / goodsDetail.SkuMap.SingleSku.B2CSku.Weight * skuMap[spuCode].Price)
}
} else {
costPrice = skuMap[spuCode]
costPrice = skuMap[spuCode].Price
}
// if errMsg == "" {
_, _, err = updateWeiMobGoods(costPrice, skuMap[spuCode], goodsDetail)
// }
_, _, _ = updateWeiMobGoods(costPrice, skuMap[spuCode].Price, skuList[0].Unit, isCompare, goodsDetail)
}
} else {
//下架微盟商品
@@ -197,7 +310,7 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
}
return retVal, err
}
taskParallel3 := tasksch.NewParallelTask("根据获取的微盟所有商品并更新", tasksch.NewParallelConfig().SetParallelCount(parallelCount).SetIsContinueWhenError(isContinueWhenError), ctx, taskFunc3, goodsList)
taskParallel3 := tasksch.NewParallelTask("根据获取的微盟所有商品并更新", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc3, goodsList)
tasksch.HandleTask(taskParallel3, task, true).Run()
goodsIDListForPutAwayInterface, err2 := taskParallel3.GetResult(0)
if err = err2; err != nil {
@@ -206,7 +319,6 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
goodsIDListForPutAway = goodsIDListForPutAwayInterface
case 3:
// 批量下架微盟商品
// if errMsg == "" {
taskFunc4 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
int64Slice := []int64{}
for _, v := range batchItemList {
@@ -218,14 +330,15 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
taskParallel4 := tasksch.NewParallelTask("下架微盟商品", tasksch.NewParallelConfig().SetParallelCount(parallelCount).SetBatchSize(UpdateGoodsShelfStatusCount), ctx, taskFunc4, goodsIDListForPutAway)
tasksch.HandleTask(taskParallel4, task, true).Run()
_, err = taskParallel4.GetResult(0)
// }
}
if errMsg != "" {
return result, errors.New(errMsg)
case 4:
WriteToExcel(task, dataSuccess.dataSuccessList, dataFailed.dataFailedList)
}
// if errMsg != "" {
// return result, errors.New(errMsg)
// }
return result, err
}
taskSeq := tasksch.NewSeqTask2("读取永辉Excel文件修改微盟商品价格可售状态-序列任务", ctx, isContinueWhenError, taskSeqFunc, 4)
taskSeq := tasksch.NewSeqTask2("读取永辉Excel文件修改微盟商品价格可售状态-序列任务", ctx, isContinueWhenError, taskSeqFunc, 5)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
@@ -265,13 +378,14 @@ func GetGoodsInfoAndDetailMap(goodsList []*weimobapi.GoodsInfo) (goodsMap map[st
// return list
// }
func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.GoodsDetailInfo) (goodsID int64, skuMap map[string]int64, err error) {
func updateWeiMobGoods(costPrice, salePrice float64, unit string, isCompare bool, goodsDetail *weimobapi.GoodsDetailInfo) (goodsID int64, skuMap map[string]int64, err error) {
var (
categoryList []*weimobapi.CategoryList
skuListInfo = goodsDetail.SkuList[0]
skuListParam []*weimobapi.SkuList
categoryID int
deliveryTypeListSlice []int64
newSkuTitle string
)
//查询配送方式
@@ -298,16 +412,51 @@ func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.Good
return 0, nil, errors.New(fmt.Sprintf("未查询到此商品的分类信息goodsID : [%v] ,", goodsDetail.GoodsID))
}
//获取分组
//商品分组原有的分组IDs
selectedClassifyList := goodsDetail.SelectedClassifyList
var selectedClassifyListID []int64
selectedClassifyListIDMap := make(map[int64]int64)
if len(selectedClassifyList) > 0 {
for _, v := range selectedClassifyList {
for _, vv := range v.ChildrenClassify {
selectedClassifyListID = append(selectedClassifyListID, vv.ClassifyID)
for _, v := range v.ChildrenClassify {
selectedClassifyListIDMap[v.ClassifyID] = v.ClassifyID
}
}
}
//上次上传价格和这次上传价格对比
// 4、微盟商品。两个重要分组
// 降价超0.2元,与前一日数据对比,需要将此类商品增加分类到这里,不改变原分类
// 涨价超0.2元,与前一日数据对比,需要将此类商品增加分类到这里,不改变原分类
// 其他商品,取消 这两个分类
// 同一天第二次上传的处理,需要注意是与前一天价格的对比,不是当天的价格对比。
// 5. 涨价和跌价值保留2位小数
// 需要在每个商品中增加↑0.01或↓0.02。
// 显示在商品最前的括号里,如果没有括号,需要增加。都用小写的括号,大写括号需要删除。
// 包装菜需要增加“精”,其他不需要加字,比如:
// (精↓2.11)新土豆1kg/袋
// (↓2.11)新土豆1kg
//salePrice 这次上传的价格 goodsDetail.SkuMap.SingleSku.SalePrice 上次上传的价格 priceMix 两次上传价格差 priceMixRound 保留两位后的价格差
if !isCompare {
priceMix := salePrice - goodsDetail.SkuMap.SingleSku.SalePrice
if priceMix > 0.2 {
delete(selectedClassifyListIDMap, 1064198248)
delete(selectedClassifyListIDMap, 1065246248)
selectedClassifyListIDMap[1064198248] = 1064198248
} else if priceMix < -0.2 {
delete(selectedClassifyListIDMap, 1064198248)
delete(selectedClassifyListIDMap, 1065246248)
selectedClassifyListIDMap[1065246248] = 1065246248
} else {
delete(selectedClassifyListIDMap, 1064198248)
delete(selectedClassifyListIDMap, 1065246248)
}
priceMixRound := Float64Round(priceMix)
newSkuTitle = GetNewSkuTitle(priceMixRound, goodsDetail.Title, goodsDetail.OuterGoodsCode)
} else {
newSkuTitle = goodsDetail.Title
}
b2CSku := &weimobapi.B2CSku{
Weight: skuListInfo.B2CSku.Weight,
Volume: skuListInfo.B2CSku.Volume,
@@ -329,7 +478,7 @@ func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.Good
goods := &weimobapi.Goods{
B2CGoods: b2CGoods,
SkuList: skuListParam,
Title: goodsDetail.Title,
Title: newSkuTitle,
IsMultiSku: goodsDetail.IsMultiSku,
IsPutAway: weimobapi.GoodsTypeNormal,
GoodsImageURL: goodsDetail.GoodsImageURL,
@@ -337,22 +486,38 @@ func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.Good
CategoryID: categoryID,
OuterGoodsCode: goodsDetail.OuterGoodsCode,
PointDeductRatio: goodsDetail.PointDeductRatio,
SelectedClassifyIDList: selectedClassifyListID,
SelectedClassifyIDList: Map2Int64Slice(selectedClassifyListIDMap),
}
updateGoodsParam := &weimobapi.UpdateGoodsParam{
Goods: goods,
}
if globals.EnableStoreWrite {
goodsID, skuMap, err = api.WeimobAPI.UpdateGoods3(updateGoodsParam)
if err != nil {
if errExt, ok := err.(*utils.ErrorWithCode); ok {
outPutData := DataFailed{
GoodsID: goodsDetail.OuterGoodsCode,
GoodsName: goodsDetail.Title,
Comment: errExt.ErrMsg(),
}
dataFailed.AppendData2(outPutData)
}
} else {
outPutData := DataSuccess{
NameID: goodsDetail.SkuMap.SingleSku.OuterSkuCode,
Name: goodsDetail.Title,
Unit: unit,
OrgPrice: goodsDetail.SkuMap.SingleSku.SalePrice,
NowPrice: salePrice,
MixPrice: Float64Round(salePrice - goodsDetail.SkuMap.SingleSku.SalePrice),
}
dataSuccess.AppendData(outPutData)
}
}
return goodsID, skuMap, err
}
func GetWeiMobGoodsList() (goodsList []*weimobapi.GoodsInfo, err error) {
param := &weimobapi.QueryGoodsListParam{
PageNum: 1,
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds,
}
func GetWeiMobGoodsList(param *weimobapi.QueryGoodsListParam) (goodsList []*weimobapi.GoodsInfo, err error) {
for {
goodsInfoList, _, err := api.WeimobAPI.QueryGoodsList(param)
if err != nil {
@@ -378,52 +543,427 @@ func IsChineseChar(str string) bool {
return false
}
func GetCellIntoMap(skuIDCol, skuPriceCol, orgSkuIDCol, orgSkuPriceCol int, skuMap map[string]float64, row []string, sheetName string, rowNum int) {
func GetCellIntoMap(sheetParam *SheetParam, skuMap map[string]*ExcelParam, row []string, sheetName string, rowNum int) {
var (
skuID string
orgSkuID string
skuPrice float64
orgSkuPrice float64
skuID string
orgSkuID string
skuPrice float64
orgSkuPrice float64
skuName string
orgSkuName string
skuIDCol = sheetParam.SkuIDCol
skuPriceCol = sheetParam.SkuPriceCol
skuNameCol = sheetParam.SkuNameCol
orgSkuIDCol = sheetParam.OrgSkuIdCol
orgSkuPriceCol = sheetParam.OrgSkuPriceCol
orgSkuNameCol = sheetParam.OrgSkuNameCol
)
for k, cell := range row {
if !IsChineseChar(cell) && cell != "" {
if k == skuIDCol && skuIDCol >= 0 {
skuID = cell
if cell != "" {
if !IsChineseChar(cell) {
if k == skuIDCol && skuIDCol >= 0 {
skuID = cell
}
if k == skuPriceCol && skuPriceCol >= 0 {
skuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
}
if k == orgSkuIDCol && orgSkuIDCol >= 0 {
orgSkuID = "0" + cell
}
if k == orgSkuPriceCol && orgSkuPriceCol >= 0 {
orgSkuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
}
}
if k == skuPriceCol && skuPriceCol >= 0 {
skuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
if k == skuNameCol && skuNameCol >= 0 {
skuName = cell
}
if k == orgSkuIDCol && orgSkuIDCol >= 0 {
orgSkuID = "0" + cell
}
if k == orgSkuPriceCol && orgSkuPriceCol >= 0 {
orgSkuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
if k == orgSkuNameCol && orgSkuNameCol >= 0 {
orgSkuName = cell
}
}
}
if skuMap[skuID] != 0 && skuMap[skuID] != skuPrice {
if skuPrice > skuMap[skuID] {
skuMap[skuID] = skuPrice
if len(skuMap) > 0 {
if skuMap[skuID] != nil {
if skuMap[skuID].Price != 0 && skuMap[skuID].Price != skuPrice && skuPrice != 0 {
if skuPrice > skuMap[skuID].Price {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
}
} else {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
}
} else if skuPrice != 0 {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
}
if skuMap[orgSkuID] != nil {
if skuMap[orgSkuID].Price != 0 && skuMap[orgSkuID].Price != orgSkuPrice && orgSkuPrice != 0 {
if orgSkuPrice > skuMap[orgSkuID].Price {
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
} else if orgSkuPriceCol >= 0 && orgSkuIDCol >= 0 && orgSkuNameCol >= 0 {
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
} else if orgSkuPrice != 0 {
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
// fmt.Sprintf("读取excel表格出错有商品ID重复且价格不同,sheetName : [%v] ,行数 : [%v] , 商品编码 [%v] , 价格:[%v]\n", sheetName, rowNum, skuID, skuPrice)
} else {
skuMap[skuID] = skuPrice
}
if skuMap[orgSkuID] != 0 && skuMap[orgSkuID] != orgSkuPrice {
if orgSkuPrice > skuMap[orgSkuID] {
skuMap[orgSkuID] = orgSkuPrice
}
// fmt.Sprintf("读取excel表格出错有商品ID重复且价格不同,sheetName : [%v] ,行数 : [%v], 商品编码 [%v] , 价格:[%v]\n", sheetName, rowNum, orgSkuID, orgSkuPrice)
} else if orgSkuPriceCol >= 0 && orgSkuIDCol >= 0 {
skuMap[orgSkuID] = orgSkuPrice
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
delete(skuMap, "")
}
func BuildSkuMap(id, name string, price float64, skuMap map[string]*ExcelParam) {
excelParam := &ExcelParam{
SpuCode: id,
Price: price,
Name: name,
}
skuMap[id] = excelParam
}
func Float64Round(f float64) (flt float64) {
return math.Round(f*100) / 100
}
func UpdateClassifyName() {
func Map2Int64Slice(m map[int64]int64) (result []int64) {
for _, v := range m {
result = append(result, v)
}
return result
}
func UpdateClassifyAndGetLastClassify() (isCompare bool, err error) {
var lastTitle string
classfiyList, err := api.WeimobAPI.QueryClassifyInfoList()
if len(classfiyList) > 0 {
for _, v := range classfiyList {
if v.ClassifyID == 1065244148 {
lastTitle = v.Title
}
}
}
title := "可定"
now := time.Now()
afterDay := now.AddDate(0, 0, 2).Day()
title += utils.Int2Str(afterDay) + "日"
if lastTitle == title {
return true, err
} else {
err = api.WeimobAPI.UpdateClassify(1065244148, title, "")
return false, err
}
}
func GetNewSkuTitle(priceMixRound float64, orgTitle, outerGoodsCode string) (name string) {
var prefix = ""
title1 := strings.ReplaceAll(orgTitle, "", "(")
title := strings.ReplaceAll(title1, "", ")")
if outerGoodsCode[0:1] != "0" {
prefix += "(精"
if priceMixRound > 0 {
prefix += "↑"
} else if priceMixRound < 0 {
prefix += "↓"
} else {
prefix += ")"
return GetReplaceNewTitle(title, prefix)
}
} else {
if priceMixRound > 0 {
prefix += "(↑"
} else if priceMixRound < 0 {
prefix += "(↓"
} else {
return GetReplaceNewTitle(title, prefix)
}
}
prefix += utils.Float64ToStr(math.Abs(priceMixRound)) + ")"
return GetReplaceNewTitle(title, prefix)
}
func GetReplaceNewTitle(title, prefix string) (newTitle string) {
if title[0:1] == "(" {
return strings.Replace(title, title[0:strings.Index(title, ")")+1], prefix, 1)
} else {
return prefix + title
}
}
func WriteToExcel(task *tasksch.SeqTask, dataSuccess []DataSuccess, dataFailed []DataFailed) (err error) {
var sheetList1 []*excel.Obj2ExcelSheetConfig
var sheetList2 []*excel.Obj2ExcelSheetConfig
var downloadURL1, downloadURL2, fileName1, fileName2 string
excelConf1 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: dataSuccess,
CaptionList: titleListSuccess,
}
sheetList1 = append(sheetList1, excelConf1)
excelConf2 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: dataFailed,
CaptionList: titleListFailed,
}
sheetList2 = append(sheetList2, excelConf2)
if excelConf1 != nil {
downloadURL1, fileName1, err = UploadExeclAndPushMsg(sheetList1, "已更新商品")
} else {
baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!")
}
if excelConf2 != nil {
downloadURL2, fileName2, err = UploadExeclAndPushMsg(sheetList2, "缺少商品_微盟")
} else {
baseapi.SugarLogger.Debug("WriteToExcel: dataFailed is nil!")
}
if err != nil {
baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName1, fileName2, err)
} else {
noticeMsg := fmt.Sprintf("[详情点我]path1=%s, path2=%s \n", globals.BackstageHost, downloadURL1, downloadURL2)
task.SetNoticeMsg(noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s ,%s success, downloadURL1:%s ,downloadURL2:%s", fileName1, fileName2, downloadURL1, downloadURL2)
}
return err
}
func UploadExeclAndPushMsg(sheetList []*excel.Obj2ExcelSheetConfig, name string) (downloadURL, fileName string, err error) {
excelBin := excel.Obj2Excel(sheetList)
timeStr := utils.Int64ToStr(time.Now().Unix())
fileName = name + timeStr + fileExt
baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", fileName)
downloadURL, err = jxutils.UploadExportContent(excelBin, fileName)
return downloadURL, fileName, err
}
func UpdateJxPriceByWeimob(ctx *jxcontext.Context, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
storeSkuBindInfoList []interface{}
skuBindInfos []*cms.StoreSkuBindInfo
)
//获取微盟所有上架商品
queryParameter := &weimobapi.QueryGoodsListRequestVo{
GoodsStatus: weimobapi.GoodsTypeNormal,
}
param := &weimobapi.QueryGoodsListParam{
PageNum: 1,
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds,
QueryParameter: queryParameter,
}
goodsList, err := GetWeiMobGoodsList(param)
if err != nil {
baseapi.SugarLogger.Errorf("GetWeiMobGoodsList error:%v", err)
}
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
v := batchItemList[0].(*weimobapi.GoodsInfo)
goodsDetail, err := api.WeimobAPI.QueryGoodsDetail(v.GoodsID)
if err != nil {
baseapi.SugarLogger.Errorf("QueryGoodsDetail error:%v", err)
}
if goodsDetail.OuterGoodsCode != "" && goodsDetail.IsPutAway == weimobapi.GoodsTypeNormal {
nameID := int(utils.Str2Int64(goodsDetail.SkuMap.SingleSku.OuterSkuCode))
unitPrice := int(utils.Float64TwoInt64(goodsDetail.SkuMap.SingleSku.CostPrice * 100))
storeSkuBindInfo := &cms.StoreSkuBindInfo{
NameID: nameID,
UnitPrice: unitPrice,
}
retVal = []*cms.StoreSkuBindInfo{storeSkuBindInfo}
}
return retVal, err
}
taskParallel := tasksch.NewParallelTask("获取微盟商品", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc, goodsList)
tasksch.HandleTask(taskParallel, task, true).Run()
storeSkuBindInfoList, err = taskParallel.GetResult(0)
case 1:
for _, v := range storeSkuBindInfoList {
skuBindInfos = append(skuBindInfos, v.(*cms.StoreSkuBindInfo))
}
cms.UpdateStoresSkus(ctx, storeIDs, skuBindInfos, isAsync, isContinueWhenError)
}
return result, err
}
taskSeq := tasksch.NewSeqTask2("根据微盟商品更新京西价", ctx, isContinueWhenError, taskSeqFunc, 2)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
hint = "1"
} else {
hint = taskSeq.GetID()
}
return hint, err
}
func GetWeimobOrders(ctx *jxcontext.Context, fromTime, toTime string, params map[string]interface{}) (result []*OrderList, err error) {
if fromTime != "" && toTime != "" {
fromTimeParam := utils.Str2Time(fromTime).UnixNano() / 1e6
toTimeParam := utils.Str2Time(toTime).UnixNano() / 1e6
if params["keyword"] != nil {
if jxutils.GetPossibleVendorIDFromVendorOrderID(params["keyword"].(string)) > model.VendorIDUnknown {
resultList, err := GetSingleOrderResultList(params)
result = append(result, resultList...)
return result, err
} else {
orderList, err := GetWeimobOrdersList(fromTimeParam, toTimeParam, params["keyword"].(string))
return orderList, err
}
} else {
orderList, err := GetWeimobOrdersList(fromTimeParam, toTimeParam, "")
return orderList, err
}
}
if fromTime == "" && toTime == "" && params["keyword"] != nil {
if jxutils.GetPossibleVendorIDFromVendorOrderID(params["keyword"].(string)) > model.VendorIDUnknown {
resultList, err := GetSingleOrderResultList(params)
result = append(result, resultList...)
return result, err
} else {
orderList, err := GetWeimobOrdersList(0, 0, params["keyword"].(string))
return orderList, err
}
}
return result, err
}
func GetWeimobOrdersList(fromTimeParam, toTimeParam int64, keyword string) (aList []*OrderList, err error) {
var queryParameter *weimobapi.MerchantOrderListQueryParameter
if fromTimeParam == 0 && toTimeParam == 0 {
queryParameter = &weimobapi.MerchantOrderListQueryParameter{
CreateStartTime: time.Now().AddDate(0, -2, 0).UnixNano() / 1e6,
CreateEndTime: time.Now().UnixNano() / 1e6,
}
} else {
queryParameter = &weimobapi.MerchantOrderListQueryParameter{
CreateStartTime: fromTimeParam,
CreateEndTime: toTimeParam,
}
}
param := &weimobapi.QueryOrdersListParam{
PageNum: 1,
PageSize: weimobapi.QueryOrdersListPageSize,
QueryParameter: queryParameter,
}
for {
orderList, _, err2 := api.WeimobAPI.QueryOrdersList(param)
err = err2
if len(orderList) > 0 {
if keyword != "" {
for _, v := range orderList {
if ContainsKeyword(v, keyword) {
var aOrder = &OrderList{
Name: v.ReceiverName,
OrderNo: v.OrderNo,
Phone: v.ReceiverMobile,
}
aList = append(aList, aOrder)
}
}
} else {
for _, v := range orderList {
var aOrder = &OrderList{
Name: v.ReceiverName,
OrderNo: v.OrderNo,
Phone: v.ReceiverMobile,
}
aList = append(aList, aOrder)
}
}
}
if len(orderList) < param.PageSize {
break
}
param.PageNum++
}
return aList, err
}
func GetWeimobOrderDetail(orderNo int64) (order *weimobapi.OrderDetail, err error) {
return api.WeimobAPI.QueryOrderDetail2(orderNo, false)
}
func GetSingleOrderResultList(params map[string]interface{}) (result []*OrderList, err error) {
weimobOrderID := params["keyword"].(string)
orderSingle, err := GetWeimobOrderDetail(utils.Str2Int64(weimobOrderID))
orderList := &OrderList{
Name: orderSingle.DeliveryDetail.LogisticsDeliveryDetail.ReceiverName,
Phone: orderSingle.DeliveryDetail.LogisticsDeliveryDetail.ReceiverMobile,
OrderNo: orderSingle.OrderNo,
}
result = append(result, orderList)
return result, err
}
func ContainsKeyword(v *weimobapi.OrderInfo, keyword string) bool {
return strings.Contains(v.ReceiverName, keyword) || strings.Contains(utils.Int64ToStr(v.OrderNo), keyword) || strings.Contains(v.ReceiverMobile, keyword)
}
func GetWeimobOrdersExcel(ctx *jxcontext.Context, OrderNo string) (err error) {
var (
DataFineList []*Data //精品
DataHairyList []*Data //毛菜
)
orderSingle, err := GetWeimobOrderDetail(utils.Str2Int64(OrderNo))
itemList := orderSingle.ItemList
for _, v := range itemList {
if v.GoodsCode[0:1] == "0" {
DataHairy := &Data{
GoodsID: v.GoodsCode,
GoodsName: v.GoodsTitle,
GoodsNum: v.SkuNum,
}
DataHairyList = append(DataHairyList, DataHairy)
} else {
DataFine := &Data{
GoodsID: v.GoodsCode,
GoodsName: v.GoodsTitle,
GoodsNum: v.SkuNum,
}
DataFineList = append(DataFineList, DataFine)
}
}
WriteToExcel2(ctx, DataFineList, DataHairyList)
return err
}
func WriteToExcel2(ctx *jxcontext.Context, DataFineList, DataHairyList []*Data) (err error) {
var (
sheetList1 []*excel.Obj2ExcelSheetConfig
sheetList2 []*excel.Obj2ExcelSheetConfig
downloadURL1, downloadURL2 string
fileName1, fileName2 string
noticeMsg string
)
excelConf1 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: DataFineList,
CaptionList: titleList,
}
sheetList1 = append(sheetList1, excelConf1)
excelConf2 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: DataHairyList,
CaptionList: titleList,
}
sheetList2 = append(sheetList2, excelConf2)
noticeMsg += "[详情点我]"
if len(DataFineList) > 0 {
downloadURL1, fileName1, err = UploadExeclAndPushMsg(sheetList1, "京西采购_精品")
noticeMsg += "path1=" + downloadURL1 + " "
} else {
baseapi.SugarLogger.Debug("WriteToExcel: DataFineList is nil!")
}
if len(DataHairyList) > 0 {
downloadURL2, fileName2, err = UploadExeclAndPushMsg(sheetList2, "京西采购_毛菜")
noticeMsg += "path2=" + downloadURL2
} else {
baseapi.SugarLogger.Debug("WriteToExcel: DataHairyList is nil!")
}
if err != nil {
baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName1, fileName2, err)
} else {
if authInfo, err := ctx.GetV2AuthInfo(); err == nil {
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, authInfo.UserID, "导出微盟订单商品成功", noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s ,%s success, downloadURL1:%s ,downloadURL2:%s", fileName1, fileName2, downloadURL1, downloadURL2)
}
}
return err
}

View File

@@ -466,7 +466,7 @@ func GetVendorName(vendorID int) (vendorName string) {
func CaculateSkuEarningPrice(shopPrice, salePrice int64, storePayPercentage int) (earningPrice int64) {
earningPrice = salePrice
if shopPrice > 0 && shopPrice < earningPrice {
if salePrice == 0 || shopPrice > 0 && shopPrice < earningPrice {
earningPrice = shopPrice
}
if storePayPercentage <= 0 {

View File

@@ -63,7 +63,7 @@ func GetStatisticsReportForOrders(db *DaoDB, storeIDs []int, fromDate time.Time,
LEFT JOIN
(
SELECT
a.store_id,
IF(a.jx_store_id <> 0,a.jx_store_id,store_id) store_id,
COUNT(*) order_counts,
SUM(sale_price) sale_price,
SUM(actual_pay_price) actual_pay_price,
@@ -88,11 +88,11 @@ func GetStatisticsReportForOrders(db *DaoDB, storeIDs []int, fromDate time.Time,
sqlParams = append(sqlParams, fromDate, toDate)
}
if len(storeIDs) > 0 {
sql += ` AND a.store_id IN(` + GenQuestionMarks(len(storeIDs)) + `)`
sql += ` AND IF(a.jx_store_id != 0, a.jx_store_id, a.store_id) IN(` + GenQuestionMarks(len(storeIDs)) + `)`
sqlParams = append(sqlParams, storeIDs)
}
sql += `
GROUP BY a.store_id
GROUP BY 1
)s
ON s.store_id = c.id
`
@@ -136,7 +136,7 @@ func GetGetStatisticsReportForAfsOrders(db *DaoDB, storeIDs []int, fromDate time
LEFT JOIN
(
SELECT
a.store_id,
IF(a.jx_store_id <> 0,a.jx_store_id,store_id) store_id,
COUNT(*) order_counts,
SUM(sale_price) sale_price,
SUM(actual_pay_price) actual_pay_price,
@@ -160,11 +160,11 @@ func GetGetStatisticsReportForAfsOrders(db *DaoDB, storeIDs []int, fromDate time
sqlParams = append(sqlParams, fromDate, toDate)
}
if len(storeIDs) > 0 {
sql += ` AND a.store_id IN(` + GenQuestionMarks(len(storeIDs)) + `)`
sql += ` AND IF(a.jx_store_id != 0, a.jx_store_id, a.store_id) IN(` + GenQuestionMarks(len(storeIDs)) + `)`
sqlParams = append(sqlParams, storeIDs)
}
sql += `
GROUP BY a.store_id
GROUP BY 1
)s
ON s.store_id = c.id
`

View File

@@ -236,9 +236,9 @@ var (
StoreAuditStatusRejected: "拒绝",
}
StorePriceTypeName = map[int]string{
StoreChangePriceTypeDirect: "可直接改价",
StoreChangePriceTypeBossDisabled: "禁止改价",
StoreChangePriceTypeManagedStore: "直营门店",
StoreChangePriceTypeDirect: "普通门店",
StoreChangePriceTypeBossDisabled: "普通门店禁止改价",
StoreChangePriceTypeManagedStore: "直营门店禁止改价",
}
)

View File

@@ -18,6 +18,10 @@ import (
"git.rosy.net.cn/jx-callback/business/model"
)
const (
actMapDuration = 2 * time.Hour
)
type LogicUpdateInfo struct {
Item interface{}
KVs map[string]interface{}
@@ -31,6 +35,8 @@ var (
jdapi.PromotionStateCanceled: model.ActStatusCanceled,
jdapi.PromotionStateEnded: model.ActStatusEnded,
}
actMap jxutils.SyncMapWithTimeout
)
func splitPromotionSku(skus []*jdapi.PromotionSku, maxCount int) (skusList [][]*jdapi.PromotionSku) {
@@ -62,22 +68,25 @@ func jdSkuActStatus2Jx(jdActState int) int {
func CreatePromotionInfos(promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
if globals.EnableJdStoreWrite {
if promotionType == model.ActSkuDirectDown {
return getAPI("").CreatePromotionInfosSingle(name, beginDate, endDate, outInfoId, advertising, traceId)
infoId, err = getAPI("").CreatePromotionInfosSingle(name, beginDate, endDate, outInfoId, advertising, traceId)
} else {
return getAPI("").CreatePromotionInfosLimitTime(name, beginDate, endDate, outInfoId, advertising, traceId)
infoId, err = getAPI("").CreatePromotionInfosLimitTime(name, beginDate, endDate, outInfoId, advertising, traceId)
}
} else {
infoId = jxutils.GenFakeID()
}
if err == nil {
actMap.StoreWithTimeout(infoId, 1, actMapDuration)
}
return infoId, err
}
func CreatePromotionRules(promotionType int, infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
if globals.EnableJdStoreWrite {
if promotionType == model.ActSkuDirectDown {
return getAPI("").CreatePromotionRulesSingle(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
err = getAPI("").CreatePromotionRulesSingle(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
} else {
return getAPI("").CreatePromotionRulesLimitTime(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
err = getAPI("").CreatePromotionRulesLimitTime(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
}
}
return err
@@ -133,9 +142,9 @@ func ConfirmPromotion(promotionType int, infoId int64, outInfoId, traceId string
func CancelPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
if globals.EnableJdStoreWrite {
if promotionType == model.ActSkuDirectDown {
return getAPI("").CancelPromotionSingle(infoId, outInfoId, traceId)
err = getAPI("").CancelPromotionSingle(infoId, outInfoId, traceId)
} else {
return getAPI("").CancelPromotionLimitTime(infoId, outInfoId, traceId)
err = getAPI("").CancelPromotionLimitTime(infoId, outInfoId, traceId)
}
}
return err
@@ -144,9 +153,9 @@ func CancelPromotion(promotionType int, infoId int64, outInfoId, traceId string)
func AdjustPromotionTime(promotionType int, infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
if globals.EnableJdStoreWrite {
if promotionType == model.ActSkuDirectDown {
return getAPI("").AdjustPromotionTimeSingle(infoId, outInfoId, endDate, traceId)
err = getAPI("").AdjustPromotionTimeSingle(infoId, outInfoId, endDate, traceId)
} else {
return getAPI("").AdjustPromotionTimeLimitTime(infoId, outInfoId, endDate, traceId)
err = getAPI("").AdjustPromotionTimeLimitTime(infoId, outInfoId, endDate, traceId)
}
}
return err
@@ -155,9 +164,9 @@ func AdjustPromotionTime(promotionType int, infoId int64, outInfoId string, endD
func AdjustPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*jdapi.PromotionSku, traceId string) (skusResult []*jdapi.PromotionSku, err error) {
if globals.EnableJdStoreWrite {
if promotionType == model.ActSkuDirectDown {
return getAPI("").AdjustPromotionSkuSingle(infoId, outInfoId, skus, traceId)
skusResult, err = getAPI("").AdjustPromotionSkuSingle(infoId, outInfoId, skus, traceId)
} else {
return getAPI("").AdjustPromotionSkuLimitTime(infoId, outInfoId, skus, traceId)
skusResult, err = getAPI("").AdjustPromotionSkuLimitTime(infoId, outInfoId, skus, traceId)
}
}
return skusResult, err
@@ -312,19 +321,22 @@ func OnActMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
func (c *PurchaseHandler) onActMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
if msg.StatusID == jdapi.PromotionStatusSingleOK || msg.StatusID == jdapi.PromotionStatusLimitTimeOK {
promotionID := msg.BillID
// 等几秒再执行的原因是防止通过后台自己创建时,本地还没有建好,消息就过来,导致重复记录
// 可能的问题是在重启时丢失消息
utils.AfterFuncWithRecover(5*time.Second, func() {
if !partner.CurActManager.IsVendorActExist(jxcontext.AdminCtx, promotionID, model.VendorIDJD) {
act, actStoreSkuList, err := getActFromJD(promotionID)
if err == nil && len(actStoreSkuList) > 0 {
_, err = partner.CurActManager.CreateActFromVendor(jxcontext.AdminCtx, act, actStoreSkuList)
intPromotionID := utils.Str2Int64(promotionID)
if _, ok := actMap.Load(intPromotionID); !ok {
utils.CallFuncAsync(func() {
if !partner.CurActManager.IsVendorActExist(jxcontext.AdminCtx, promotionID, model.VendorIDJD) {
act, actStoreSkuList, err := getActFromJD(promotionID)
if err == nil && len(actStoreSkuList) > 0 {
_, err = partner.CurActManager.CreateActFromVendor(jxcontext.AdminCtx, act, actStoreSkuList)
}
if err != nil {
retVal = jdapi.Err2CallbackResponse(err, promotionID)
}
}
if err != nil {
retVal = jdapi.Err2CallbackResponse(err, promotionID)
}
}
})
})
} else {
actMap.Delete(intPromotionID)
}
}
return retVal
}

View File

@@ -43,7 +43,7 @@ func OnFinancialMsg(msg *mtwmapi.CallbackMsg) (err error) {
func (p *PurchaseHandler) OrderFinancialDetail2Refund(orderFinancial *model.OrderFinancial, orderData url.Values) (afsOrder *model.AfsOrder) {
afsOrder = &model.AfsOrder{
VendorID: model.VendorIDMTWM,
AfsOrderID: orderData.Get("order_id"),
AfsOrderID: orderData.Get("refund_id"),
VendorOrderID: orderData.Get("order_id"),
AfsCreatedAt: utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp"))),
// BoxMoney: orderFinancial.BoxMoney,

View File

@@ -121,7 +121,9 @@ func openTimeMtwm2JX(vendorOpenTime string) (opTimeList []int16) {
timePairs := strings.Split(vendorOpenTime, ",")
for _, v := range timePairs {
times := strings.Split(v, "-")
opTimeList = append(opTimeList, jxutils.StrTime2JxOperationTime(times[0]+":00", 700), jxutils.StrTime2JxOperationTime(times[1]+":00", 2000))
if len(times) >= 2 {
opTimeList = append(opTimeList, jxutils.StrTime2JxOperationTime(times[0]+":00", 700), jxutils.StrTime2JxOperationTime(times[1]+":00", 2000))
}
}
return opTimeList
}

View File

@@ -514,20 +514,6 @@ func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *mode
return mobile, err
}
// func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) {
// if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted {
// params = &partner.StatusActionParams{ // PickDeadline没有设置时才有效美团外卖要求在5分钟内拣货不然订单会被取消
// Timeout: pickupOrderDelay,
// }
// } else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup {
// params = &partner.StatusActionParams{ // 立即达订单有效,自配送延时召唤配送
// Timeout: callDeliveryDelay,
// TimeoutGap: callDeliveryDelayGap,
// }
// }
// return params
// }
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
if globals.EnableMtwmStoreWrite {
if isAgree {

View File

@@ -2,6 +2,7 @@ package mtwm
import (
"fmt"
"net/url"
"strings"
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
@@ -119,8 +120,9 @@ func (c *PurchaseHandler) onAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwma
}
afsOrder.PmSubsidyMoney += afsOrder.RefundMoney - afsOrder.SkuUserMoney
} else {
if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDMTWM); err2 == nil {
afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg.FormData)
if afsOrder = c.createAfsOrder(msg.FormData); afsOrder != nil {
// if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDMTWM); err2 == nil {
// afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg.FormData)
afsOrder.AfsOrderID = orderStatus.VendorOrderID
afsOrder.RefundType = model.AfsTypeFullRefund
afsOrder.AppealType = model.AfsAppealTypeRefund
@@ -139,6 +141,52 @@ func (c *PurchaseHandler) onAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwma
return mtwmapi.Err2CallbackResponse(err, "")
}
func (p *PurchaseHandler) createAfsOrder(orderData url.Values) (afsOrder *model.AfsOrder) {
afsOrder = &model.AfsOrder{
VendorID: model.VendorIDMTWM,
AfsOrderID: orderData.Get("refund_id"),
VendorOrderID: orderData.Get("order_id"),
AfsCreatedAt: utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp"))),
}
if afsOrder.AfsOrderID == "" {
afsOrder.AfsOrderID = afsOrder.VendorOrderID
}
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
globals.SugarLogger.Debug(utils.Format4Output(order, false))
if err == nil {
afsOrder.JxStoreID = order.JxStoreID
afsOrder.VendorStoreID = order.VendorStoreID
afsOrder.StoreID = order.StoreID
} else {
globals.SugarLogger.Warnf("mtwm AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrder", afsOrder.VendorOrderID)
return nil
}
for _, sku := range order.Skus {
orderSkuFinancial := &model.OrderSkuFinancial{
VendorID: sku.VendorID,
VendorOrderID: sku.VendorOrderID,
// OrderFinancialID: sku.VendorOrderID,
// ConfirmTime: afsOrder.AfsCreateAt,
VendorStoreID: afsOrder.VendorStoreID,
StoreID: afsOrder.StoreID,
JxStoreID: afsOrder.JxStoreID,
VendorSkuID: sku.VendorSkuID,
SkuID: sku.SkuID,
PromotionType: sku.PromotionType,
Name: sku.SkuName,
ShopPrice: sku.ShopPrice,
SalePrice: sku.SalePrice,
Count: sku.Count,
// UserMoney: sku.UserMoney,
// PmSubsidyMoney: sku.PmSubsidyMoney,
IsAfsOrder: 1,
}
afsOrder.Skus = append(afsOrder.Skus, orderSkuFinancial)
}
return afsOrder
}
func (c *PurchaseHandler) callbackAfsMsg2Status(msg *mtwmapi.CallbackMsg) (orderStatus *model.OrderStatus) {
refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
orderStatus = &model.OrderStatus{
@@ -153,6 +201,8 @@ func (c *PurchaseHandler) callbackAfsMsg2Status(msg *mtwmapi.CallbackMsg) (order
}
if refundData.RefundID > 0 {
orderStatus.VendorOrderID = utils.Int64ToStr(refundData.RefundID)
} else {
orderStatus.VendorOrderID = orderStatus.RefVendorOrderID
}
return orderStatus
}

View File

@@ -25,6 +25,9 @@ const (
const (
defVendorCatID = 200001903 // 生菜
specialStoreID = "8171010"
// specialStoreID = "2523687"
)
var (
@@ -197,12 +200,35 @@ func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) {
return mtwmapi.IsErrSkuNotExist(err)
}
// func duplicateStoreSkuList(storeSkuList []*dao.StoreSkuSyncInfo, index int) (newStoreSkuList []*dao.StoreSkuSyncInfo) {
// newStoreSkuList = make([]*dao.StoreSkuSyncInfo, len(storeSkuList))
// for k, v := range storeSkuList {
// tmp := *v
// tmp.SkuName = fmt.Sprintf("%s.%d", tmp.SkuName, index)
// tmp.SkuID = index*1000000 + tmp.SkuID
// newStoreSkuList[k] = &tmp
// }
// return newStoreSkuList
// }
func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) {
return p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false)
successList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false)
// if err == nil && vendorStoreID == specialStoreID {
// for i := 0; i < 2; i++ {
// p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true)
// }
// }
return successList, err
}
func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) {
return p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true)
successList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true)
// if err == nil && vendorStoreID == specialStoreID {
// for i := 0; i < 2; i++ {
// p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true)
// }
// }
return successList, err
}
// 对于多门店平台来说storeSkuList中只有SkuID与VendorSkuID有意义
@@ -235,7 +261,15 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI
foodData["category_name"] = storeSku.VendorCatID
}
foodData["is_sold_out"] = skuStatusJX2Mtwm(storeSku.MergedStatus)
foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, storeSku.Img2), ",")
if true { // vendorStoreID == specialStoreID {
img2 := storeSku.Img2
if img2 == "" {
img2 = storeSku.Img
}
foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, img2, storeSku.Img, storeSku.Img, storeSku.Img), ",")
} else {
foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, storeSku.Img2), ",")
}
if storeSku.DescImg != "" {
foodData["picture_contents"] = storeSku.DescImg
}

View File

@@ -18,17 +18,19 @@ import (
)
func GetComposedCode(c *beego.Controller, code string) (composedCode string) {
composedCode = code
referer := c.Ctx.Request.Referer()
globals.SugarLogger.Debugf("GetComposedCode referer:%s", referer)
index := strings.Index(referer, "//")
if index > 0 {
list := strings.Split(referer[index+2:], "/")
if len(list) >= 2 {
composedCode = strings.Join([]string{
list[1],
code,
}, ",")
if code != "" {
composedCode = code
referer := c.Ctx.Request.Referer()
globals.SugarLogger.Debugf("GetComposedCode referer:%s", referer)
index := strings.Index(referer, "//")
if index > 0 {
list := strings.Split(referer[index+2:], "/")
if len(list) >= 2 {
composedCode = strings.Join([]string{
list[1],
code,
}, ",")
}
}
}
return composedCode

View File

@@ -381,9 +381,9 @@ func (c *User2Controller) GetSelfInfo() {
// @Title 根据小程序jsCode修改用户信息
// @Description 根据小程序jsCode修改用户信息
// @Param token header string true "认证token"
// @Param jsCode query string true "小程序jsCode"
// @Param data query string true "加密数据"
// @Param iv query string true "iv"
// @Param jsCode query string false "小程序jsCode"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /UpdateUserByMiniInfo [put]

View File

@@ -4,6 +4,7 @@ import (
"io"
"git.rosy.net.cn/jx-callback/business/jxstore/yonghui"
"git.rosy.net.cn/jx-callback/business/jxutils"
"github.com/astaxie/beego"
)
@@ -14,7 +15,7 @@ type YongHuiController struct {
// @Title 读取永辉excel文件
// @Description 读取永辉excel文件
// @Param token header string false "认证token"
// @Param token header string true "认证token"
// @Param isAsync query bool true "是否异步,缺省是同步"
// @Param isContinueWhenError query bool true "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
@@ -42,3 +43,52 @@ func (c *YongHuiController) LoadExcelByYongHui() {
})
}
}
// @Title 根据微盟商品更新京西价格
// @Description 根据微盟商品更新京西价格
// @Param token header string true "认证token"
// @Param storeIDs formData string true "门店ID列表"
// @Param isAsync formData bool true "是否异步,缺省是同步"
// @Param isContinueWhenError formData bool true "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /UpdateJxPriceByWeimob [post]
func (c *YongHuiController) UpdateJxPriceByWeimob() {
c.callUpdateJxPriceByWeimob(func(params *tYonghuiUpdateJxPriceByWeimobParams) (retVal interface{}, errCode string, err error) {
var storeIDList []int
if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDList); err == nil {
retVal, err = yonghui.UpdateJxPriceByWeimob(params.Ctx, storeIDList, params.IsAsync, params.IsContinueWhenError)
}
return retVal, "", err
})
}
// @Title 查询微盟订单
// @Description 查询微盟订单
// @Param token header string true "认证token"
// @Param keyword query string false "查询关键字"
// @Param fromTime formData string false "订单起始时间 (yyyy-mm-dd 00:00:00)"
// @Param toTime formData string false "订单结束时间 (yyyy-mm-dd 00:00:00)"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetWeimobOrders [post]
func (c *YongHuiController) GetWeimobOrders() {
c.callGetWeimobOrders(func(params *tYonghuiGetWeimobOrdersParams) (retVal interface{}, errCode string, err error) {
retVal, err = yonghui.GetWeimobOrders(params.Ctx, params.FromTime, params.ToTime, params.MapData)
return retVal, "", err
})
}
// @Title 根据微盟订单号生成Excel
// @Description 根据微盟订单号生成Excel
// @Param token header string true "认证token"
// @Param orderNo formData string true "订单号"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetWeimobOrdersExcel [post]
func (c *YongHuiController) GetWeimobOrdersExcel() {
c.callGetWeimobOrdersExcel(func(params *tYonghuiGetWeimobOrdersExcelParams) (retVal interface{}, errCode string, err error) {
err = yonghui.GetWeimobOrdersExcel(params.Ctx, params.OrderNo)
return retVal, "", err
})
}

View File

@@ -2016,6 +2016,24 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"],
beego.ControllerComments{
Method: "GetWeimobOrders",
Router: `/GetWeimobOrders`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"],
beego.ControllerComments{
Method: "GetWeimobOrdersExcel",
Router: `/GetWeimobOrdersExcel`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"],
beego.ControllerComments{
Method: "LoadExcelByYongHui",
@@ -2025,4 +2043,13 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"],
beego.ControllerComments{
Method: "UpdateJxPriceByWeimob",
Router: `/UpdateJxPriceByWeimob`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
}