同步错误

This commit is contained in:
苏尹岚
2019-12-30 08:47:42 +08:00
106 changed files with 4008 additions and 1412 deletions

View File

@@ -31,29 +31,6 @@ type tStoreSkuBindAndVendorSkuID struct {
func init() {
}
func (c *OrderManager) LoadPendingOrders() []*model.GoodsOrder {
db := orm.NewOrm()
var orders []*model.GoodsOrder
tillTime := time.Now().Add(-pendingOrderGapMax)
_, err := db.Raw(`
SELECT *
FROM goods_order
WHERE order_created_at >= ?
AND status < ?
`, tillTime, model.OrderStatusEndBegin).QueryRows(&orders)
if err != nil {
globals.SugarLogger.Warnf("LoadPendingOrders load pending orders error:%v", err)
return nil
}
for _, order := range orders {
utils.CallFuncLogError(func() error {
_, err = db.QueryTable("order_sku").Filter("vendor_order_id", order.VendorOrderID).Filter("vendor_id", order.VendorID).All(&order.Skus)
return err
}, "LoadPendingOrders order:%v", order)
}
return orders
}
// msgVendorStatus的意思是事件本身的类型类似有时收到NewOrder事件去取订单状态不一定就是New的
// OnOrderAdjust也类似而OrderStatus要记录的是消息所以添加这个
func (c *OrderManager) OnOrderNew(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) {
@@ -97,6 +74,7 @@ func (c *OrderManager) OnOrderNew(order *model.GoodsOrder, orderStatus *model.Or
// todo 调整单的处理可能还需要再细化一点,当前只是简单的删除重建
func (c *OrderManager) OnOrderAdjust(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) {
globals.SugarLogger.Debugf("OnOrderAdjust orderID:%s, status:%d", order.VendorOrderID, order.Status)
if order.ConsigneeMobile2 == "" && jxutils.IsStringLikeMobile(order.ConsigneeMobile) {
order.ConsigneeMobile2 = order.ConsigneeMobile
}
@@ -185,6 +163,33 @@ func (c *OrderManager) OnOrderStatusChanged(vendorOrgCode string, orderStatus *m
isDuplicated, order, err := c.addOrderStatus(orderStatus, db)
if err == nil {
dao.Commit(db)
if orderStatus.Status == model.OrderStatusWaybillTipChanged {
if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil {
if handler := partner.GetWaybillTipUpdater(orderStatus.RefVendorID); handler != nil {
tipFee, err2 := handler.GetWaybillTip(jxcontext.AdminCtx, vendorOrgCode, order.VendorStoreID, orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, "")
if err2 == nil {
order.WaybillTipMoney = tipFee
c.UpdateOrderFields(order, []string{"WaybillTipMoney"})
}
}
}
} else if orderStatus.Status == model.OrderStatusFinished {
if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil {
// 当前只针对三方运单更新配送费信息
if order.WaybillVendorID >= 0 && order.VendorWaybillID != "" && order.WaybillVendorID != order.VendorID {
if waybill, err2 := c.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID); err2 == nil {
if handler := partner.GetWaybillTipUpdater(waybill.WaybillVendorID); handler != nil {
tipFee, err2 := handler.GetWaybillTip(jxcontext.AdminCtx, waybill.VendorOrgCode, "", order.VendorOrderID, waybill.VendorWaybillID, waybill.VendorWaybillID2)
if err2 == nil && waybill.TipFee != tipFee {
waybill.ActualFee += tipFee - waybill.TipFee
waybill.TipFee = tipFee
dao.UpdateEntity(db, waybill, "TipFee", "ActualFee")
}
}
}
}
}
}
if !isDuplicated {
if order != nil {
order.Skus = c.loadOrderSku(db, order.VendorOrderID, order.VendorID)
@@ -234,7 +239,7 @@ func setFakeOrderFlag(db *dao.DaoDB, order *model.GoodsOrder) {
}
func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao.DaoDB) (isDuplicated bool, err error) {
globals.SugarLogger.Debugf("SaveOrder orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID)
globals.SugarLogger.Debugf("SaveOrder orderID:%s, VendorStoreID:%s, status:%d", order.VendorOrderID, order.VendorStoreID, order.Status)
// 忽略查找JX信息错误
c.updateOrderOtherInfo(order, db)
order.ID = 0
@@ -259,7 +264,7 @@ func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao
if dao.GetRow(db, orderStatus, `
SELECT *
FROM order_status
WHERE order_type = ? AND vendor_order_id = ? AND vendor_id = ?
WHERE order_type = ? AND vendor_order_id = ? AND vendor_id = ? AND status > 0
ORDER BY status_time DESC
LIMIT 1
`, model.OrderTypeOrder, order.VendorOrderID, order.VendorID) == nil {
@@ -394,7 +399,7 @@ func updateSingleOrderEarningPrice(order *model.GoodsOrder, db *dao.DaoDB) {
skuIDMap[v.SkuID] = 1
}
if len(skuIDMap) > 0 {
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt)
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, model.ActTypeAll, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt)
if err != nil {
globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku promotion info for error:%v", err)
}

View File

@@ -273,7 +273,7 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af
var actStoreSkuMap *jxutils.ActStoreSkuMap
if len(skuIDMap) > 0 {
if order2, err2 := c.LoadOrder(order.VendorOrderID, order.VendorID); err2 == nil {
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order2.OrderCreatedAt, order2.OrderCreatedAt)
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, model.ActTypeAll, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order2.OrderCreatedAt, order2.OrderCreatedAt)
if err != nil {
globals.SugarLogger.Errorf("updateAfsOrderSkuOtherInfo can not get sku promotion info for error:%v", err)
return err

View File

@@ -85,7 +85,10 @@ func (c *OrderManager) OnOrderComments(orderCommentList []*model.OrderComment) (
isNewComment = true
if orderComment.IsReplied == 0 && time.Now().Sub(orderComment.CommentCreatedAt) < time.Duration(orderComment.ModifyDuration)*time.Hour {
if storeDetail, err2 := dao.GetStoreDetail(db, orderComment.StoreID, orderComment.VendorID); err2 == nil {
c.replyOrderComment(storeDetail.VendorOrgCode, orderComment)
if storeDetail.AutoReplyType == model.AutoReplyAll ||
orderComment.Score > JX_BAD_COMMENTS_MAX_LEVEL && storeDetail.AutoReplyType == model.AutoReplyGoodComment {
c.replyOrderComment(storeDetail.VendorOrgCode, orderComment)
}
}
}
}

View File

@@ -115,8 +115,11 @@ func (c *OrderManager) GetStatusDuplicatedCount(status *model.OrderStatus) (dupl
// todo 最好还是改成全事件回放算了
func LoadPendingOrders() {
orders := FixedOrderManager.LoadPendingOrders()
globals.SugarLogger.Infof("LoadPendingOrders orders count:%d", len(orders))
orders, err := dao.LoadPendingOrders(dao.GetDB(), time.Now().Add(-pendingOrderGapMax), model.OrderStatusEndBegin)
globals.SugarLogger.Infof("LoadPendingOrders orders count:%d, err:%v", len(orders), err)
if err != nil {
return
}
ordersCount := len(orders)
if ordersCount > 0 {

View File

@@ -23,6 +23,9 @@ import (
const (
maxLastHours = 7 * 24 // 最多只能查询7天内的订单数据
defLastHours = 2 * 24 // 缺省是两天内的订单
orderSubTimeImmediatelyArrive = 8
orderSubTimeDelayArrive = 5
)
type tWaybillExt struct {
@@ -96,8 +99,7 @@ func (c *OrderManager) GetOrderSkuInfo(ctx *jxcontext.Context, vendorOrderID str
t1.sku_name,
IF(t1.shop_price = 0, t1.sale_price, t1.shop_price) shop_price,
t1.sale_price,
t1.earning_price,
CAST(IF(t1.earning_price <> 0, t1.earning_price, IF(t1.shop_price <> 0 && t1.shop_price < t1.sale_price, t1.shop_price, t1.sale_price) * IF(t5.pay_percentage > 0, t5.pay_percentage, ?) / 100) AS SIGNED) real_earning_price,
CAST(IF(t1.earning_price <> 0, t1.earning_price, IF(t1.shop_price <> 0 && t1.shop_price < t1.sale_price, t1.shop_price, t1.sale_price) * IF(t5.pay_percentage > 0, t5.pay_percentage, ?) / 100) AS SIGNED) earning_price,
t1.weight,
t1.sku_type,
t1.promotion_type,
@@ -159,7 +161,7 @@ func (c *OrderManager) GetOrderInfo(ctx *jxcontext.Context, vendorOrderID string
return nil, err
}
func (c *OrderManager) GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded bool) (bills []*model.Waybill, err error) {
func (c *OrderManager) GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded, isGetPos bool) (bills []*model.WaybillExt, err error) {
globals.SugarLogger.Debugf("GetOrderWaybillInfo orderID:%s", vendorOrderID)
db := dao.GetDB()
sql := `
@@ -176,7 +178,26 @@ func (c *OrderManager) GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID
sqlParams = append(sqlParams, model.OrderStatusEndBegin)
}
err = dao.GetRows(db, &bills, sql, sqlParams...)
globals.SugarLogger.Infof("GetOrderWaybillInfo orderID:%s failed with error:%v", vendorOrderID, err)
if err == nil && isGetPos {
var taskBills []*model.WaybillExt
for _, v := range bills {
if v.Status >= model.WaybillStatusAccepted && v.Status <= model.WaybillStatusDelivering {
if handler := partner.GetRidderPositionGetter(v.WaybillVendorID); handler != nil {
taskBills = append(taskBills, v)
}
}
}
if len(taskBills) > 0 {
task := tasksch.NewParallelTask("GetOrderWaybillInfo", nil, ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
waybill := batchItemList[0].(*model.WaybillExt)
waybill.Lng, waybill.Lat, err = partner.GetRidderPositionGetter(waybill.WaybillVendorID).GetRidderPosition(ctx, waybill.VendorOrderID, waybill.VendorOrderID, waybill.VendorWaybillID, waybill.VendorWaybillID2)
return nil, err
}, taskBills)
tasksch.HandleTask(task, nil, false).Run()
task.GetResult(0)
}
}
return bills, err
}
@@ -937,6 +958,7 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in
}
if len(dateVendorList) > 0 {
var missingOrderList []*tOrderVendorPair
var updateOrderStatusList []*model.GoodsOrder
db := dao.GetDB()
vendorStoreIDMap := make(map[int]string)
if storeID > 0 {
@@ -987,8 +1009,21 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in
for _, v := range orderList {
pair := v.(*tOrderVendorPair)
if localOrderMap[jxutils.ComposeUniversalOrderID(pair.VendorOrderID, pair.VendorID)] == nil {
goodsOrder := localOrderMap[jxutils.ComposeUniversalOrderID(pair.VendorOrderID, pair.VendorID)]
if goodsOrder == nil {
missingOrderList = append(missingOrderList, pair)
} else {
if !model.IsOrderFinalStatus(goodsOrder.Status) {
if goodsOrder.BusinessType == model.BusinessTypeImmediate {
if time.Now().Sub(goodsOrder.CreatedAt).Hours() >= orderSubTimeImmediatelyArrive {
updateOrderStatusList = append(updateOrderStatusList, goodsOrder)
}
} else {
if time.Now().Sub(goodsOrder.ExpectedDeliveredTime).Hours() >= orderSubTimeDelayArrive {
updateOrderStatusList = append(updateOrderStatusList, goodsOrder)
}
}
}
}
}
case 1:
@@ -1008,9 +1043,26 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in
}, missingOrderList)
tasksch.HandleTask(task2, task, true).Run()
result, err = task2.GetResult(0)
case 2:
task3 := tasksch.NewParallelTask("AmendMissingOrders UpdateOrders", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
goodsOrder := batchItemList[0].(*model.GoodsOrder)
if handler := partner.GetPurchaseOrderHandlerFromVendorID(goodsOrder.VendorID); handler != nil {
status, err2 := handler.GetOrderStatus(goodsOrder.VendorOrgCode, goodsOrder.VendorOrderID)
if err = err2; err == nil {
if model.IsOrderFinalStatus(status) {
goodsOrder.Status = status
_, err = dao.UpdateEntity(db, goodsOrder, "Status")
}
}
}
return retVal, err
}, updateOrderStatusList)
tasksch.HandleTask(task3, task, true).Run()
_, err = task3.GetResult(0)
}
return result, err
}, 2)
}, 3)
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
result, err2 := task.GetResult(0)

View File

@@ -1,11 +1,17 @@
package orderman
import (
"fmt"
"time"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals"
@@ -19,6 +25,17 @@ var (
model.WaybillStatusRefuseFailedGetGoods: model.OrderStatusRefuseFailedGetGoods,
model.WaybillStatusDeliverFailed: model.OrderStatusDeliverFailed,
}
complaintReasonsMap = map[int]string{
1: "骑手态度恶劣",
2: "骑手接单后未取货",
3: "骑手取货太慢",
4: "骑手送货太慢",
5: "货品未送达",
6: "货品有损坏",
7: "骑手违规收取顾客其他费用",
69: "骑手恶意取消订单",
71: "骑手提前点击取货/送达",
}
)
func (w *OrderManager) LoadPendingWaybills() []*model.Waybill {
@@ -85,6 +102,9 @@ func (w *OrderManager) onWaybillNew(bill2 *model.Waybill, db *dao.DaoDB) (isDupl
func (w *OrderManager) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
var isDuplicated bool
if bill.ActualFee == 0 {
bill.ActualFee = bill.DesiredFee + bill.TipFee
}
bill.CourierMobile = jxutils.FormalizeMobile(bill.CourierMobile)
db := dao.GetDB()
dao.Begin(db)
@@ -220,3 +240,26 @@ func (c *OrderManager) LoadWaybill(vendorWaybillID string, waybillVendorID int)
}
return bill, err
}
func GetComplaintReasons() (complaintReasonList []*dadaapi.ComplaintReason) {
for k, v := range complaintReasonsMap {
complaintReason := &dadaapi.ComplaintReason{
ID: k,
Reason: v,
}
complaintReasonList = append(complaintReasonList, complaintReason)
}
return complaintReasonList
}
func ComplaintRider(ctx *jxcontext.Context, vendorOrderID string, vendorID, waybillVendorID, complaintID int) (err error) {
db := dao.GetDB()
p := partner.GetDeliveryPlatformFromVendorID(waybillVendorID).Handler
wayBillList, err := dao.GetWayBillByOrderID(db, model.OrderStatusFinished, vendorID, waybillVendorID, vendorOrderID)
if err == nil && len(wayBillList) > 0 {
err = p.ComplaintRider(wayBillList[0], complaintID, complaintReasonsMap[complaintID])
} else {
return fmt.Errorf("未查询到到相关订单,订单状态要求必须是完成!订单号:[%v] ,厂商:[%v],运送厂商:[%v]", vendorOrderID, vendorID, waybillVendorID)
}
return err
}

View File

@@ -37,8 +37,14 @@ func (c *BaseScheduler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool
globals.SugarLogger.Infof("PickupGoods orderID:%s", order.VendorOrderID)
if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusAccepted {
if c.IsReallyCallPlatformAPI {
err = utils.CallFuncLogErrorWithInfo(func() error {
return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).PickupGoods(order, isSelfDelivery, userName)
handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID)
err = utils.CallFuncLogErrorWithInfo(func() (err error) {
if err = handler.PickupGoods(order, isSelfDelivery, userName); err != nil {
if status, err2 := handler.GetOrderStatus(order.VendorOrgCode, order.VendorOrderID); err2 == nil && status >= model.OrderStatusFinished {
err = nil
}
}
return err
}, "PickupGoods orderID:%s", order.VendorOrderID)
}
} else {

View File

@@ -236,6 +236,69 @@ func (c *BaseScheduler) ConfirmSelfTake(ctx *jxcontext.Context, vendorOrderID st
return err
}
func (c *BaseScheduler) SetOrderWaybillTip(ctx *jxcontext.Context, vendorOrderID string, vendorID int, tipFee int64) (err error) {
order, err2 := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID)
if err = err2; err == nil {
err = c.SetOrderWaybillTipByOrder(ctx, order, tipFee)
}
return err
}
func isWaybillCanAddTip(waybill *model.Waybill) (isCan bool) {
isCan = waybill.Status >= model.WaybillStatusNew && waybill.Status < model.WaybillStatusAccepted && partner.GetWaybillTipUpdater(waybill.WaybillVendorID) != nil
return isCan
}
func (c *BaseScheduler) SetOrderWaybillTipByOrder(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee int64) (err error) {
roundTipFee := tipFee / 100 * 100
if roundTipFee != tipFee {
return fmt.Errorf("小费必须是1元的整数倍")
}
if order.WaybillTipMoney >= tipFee {
return fmt.Errorf("当前小费已经是%s元想要设置%s元", jxutils.IntPrice2StandardString(order.WaybillTipMoney), jxutils.IntPrice2StandardString(tipFee))
}
db := dao.GetDB()
storeDetail, err2 := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID)
if err = err2; err != nil {
return err
}
// 如果平台支持设置配送小费,必须要成功设置
if handler := partner.GetWaybillTipUpdater(order.VendorID); handler != nil {
if err = handler.UpdateWaybillTip(ctx, order.VendorOrgCode, order.VendorStoreID, order.VendorOrderID, "", "", utils.Int2Str(storeDetail.CityCode), tipFee); err != nil {
return err
}
}
order.WaybillTipMoney = tipFee
partner.CurOrderManager.UpdateOrderFields(order, []string{"WaybillTipMoney"})
waybills, err := dao.GetWayBillByOrderID(db, 0, order.VendorID, 0, order.VendorOrderID)
if err == nil {
var waybills2 []*model.Waybill
for _, v := range waybills {
// 必须是三方配送
if !model.IsWaybillPlatformOwn(v) && isWaybillCanAddTip(v) {
waybills2 = append(waybills2, v)
}
}
if len(waybills2) > 0 {
task := tasksch.NewParallelTask("SetOrderWaybillTipByOrder", nil, ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
waybill := batchItemList[0].(*model.Waybill)
handler := partner.GetWaybillTipUpdater(waybill.WaybillVendorID)
if err == nil {
err = handler.UpdateWaybillTip(ctx, waybill.VendorOrgCode, storeDetail.VendorStoreID, waybill.VendorOrderID, waybill.VendorWaybillID, waybill.VendorWaybillID2, utils.Int2Str(storeDetail.CityCode), tipFee)
}
return nil, err
}, waybills2)
tasksch.HandleTask(task, nil, false).Run()
_, err = task.GetResult(0)
}
}
return err
}
func (c *BaseScheduler) confirmSelfTake(ctx *jxcontext.Context, order *model.GoodsOrder, selfTakeCode string) (err error) {
globals.SugarLogger.Debugf("confirmSelfTake orderID:%s, selfTakeCode:%s", order.VendorOrderID, selfTakeCode)
if order.VendorID == model.VendorIDJD {

View File

@@ -6,11 +6,14 @@ import (
"sync"
"time"
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/jxutils/netprinter"
"git.rosy.net.cn/jx-callback/business/jxutils/smsmsg"
"git.rosy.net.cn/jx-callback/business/msghub"
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/basesch"
@@ -157,6 +160,7 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e
s.autoPickupTimeoutMinute = int(storeDetail.AutoPickup)
s.isDeliveryCompetition = storeDetail.DeliveryCompetition != 0
}
globals.SugarLogger.Debugf("updateOrderStoreFeature2 orderID:%s, isDeliveryCompetition:%t", order.VendorOrderID, s.isDeliveryCompetition)
return err
}
@@ -175,7 +179,7 @@ func (w *WatchOrderInfo) StopTimer(statusType, vendorID, status int) {
for _, timerInfo := range w.timerList {
if (statusType == -1 || statusType == timerInfo.statusType) &&
(vendorID == -1 || vendorID == timerInfo.vendorID) &&
(status == -1 || status <= timerInfo.status) {
(status == -1 || status >= timerInfo.status) {
if timerInfo.timer != nil {
timerInfo.timer.Stop()
timerInfo.timer = nil
@@ -187,6 +191,10 @@ func (w *WatchOrderInfo) StopTimer(statusType, vendorID, status int) {
w.timerList = newTimerList
}
func (w *WatchOrderInfo) AddTimer(timerInfo *tTimerInfo) {
w.timerList = append(w.timerList, timerInfo)
}
func (w *WatchOrderInfo) GetCreateWaybillTimeout() (timeoutSecond int) {
// if w.timerStatusType == scheduler.TimerStatusTypeWaybill && w.timerStatus == model.WaybillStatusNew {
// timeoutSecond = int(w.timerTime.Sub(time.Now()) / time.Second)
@@ -267,7 +275,7 @@ func init() {
return nil
},
ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool {
return savedOrderInfo.autoPickupTimeoutMinute > 0
return savedOrderInfo.autoPickupTimeoutMinute > 0 && savedOrderInfo.order.Status < model.OrderStatusFinishedPickup
},
},
model.OrderStatusFinishedPickup: &StatusActionConfig{
@@ -304,7 +312,6 @@ func init() {
order.VendorID == bill.WaybillVendorID &&
savedOrderInfo.isDeliveryCompetition &&
model.IsOrderDeliveryByPlatform(order) &&
order.DeliveryType != model.OrderDeliveryTypeSelfTake &&
isOrderCanSwitch2SelfDeliver(order) &&
(order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin)
},
@@ -325,9 +332,8 @@ func init() {
order.VendorID == bill.WaybillVendorID &&
savedOrderInfo.isDeliveryCompetition &&
model.IsOrderDeliveryByPlatform(order) &&
order.DeliveryType != model.OrderDeliveryTypeSelfTake &&
isOrderCanSwitch2SelfDeliver(order) &&
(order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin)
(order.Status >= model.OrderStatusAccepted && order.Status < model.OrderStatusEndBegin) // 运单与订单时间有错序的情况放开订单条件至OrderStatusAccepted
},
},
//*/
@@ -453,24 +459,35 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo
if !isPending {
if order.Status > model.OrderStatusEndBegin {
s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
} else if model.IsOrderHaveWaybill(order) {
globals.SugarLogger.Debugf("OnWaybillStatusChanged multiple waybill created, bill:%v", bill)
if model.IsWaybillPlatformOwn(bill) { // 是购物平台运单
if !model.IsOrderHaveOwnWaybill(order) { // 既有运单不是购物平台运单
globals.SugarLogger.Infof("OnWaybillStatusChanged bill:%v purchase platform bill came later than others, strange!!!", bill)
oldBill := savedOrderInfo.waybills[order.WaybillVendorID]
if oldBill != nil {
s.ProxyCancelWaybill(order, oldBill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
} else {
globals.SugarLogger.Warnf("OnWaybillStatusChanged bill:%v, oldBill is null, strange!!!", bill)
} else {
needAddTip := order.WaybillTipMoney > 0 && !model.IsWaybillPlatformOwn(bill)
if model.IsOrderHaveWaybill(order) {
globals.SugarLogger.Debugf("OnWaybillStatusChanged multiple waybill created, bill:%v", bill)
if model.IsWaybillPlatformOwn(bill) { // 是购物平台运单
if !model.IsOrderHaveOwnWaybill(order) { // 既有运单不是购物平台运单
globals.SugarLogger.Infof("OnWaybillStatusChanged bill:%v purchase platform bill came later than others, strange!!!", bill)
oldBill := savedOrderInfo.waybills[order.WaybillVendorID]
if oldBill != nil {
s.ProxyCancelWaybill(order, oldBill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
} else {
globals.SugarLogger.Warnf("OnWaybillStatusChanged bill:%v, oldBill is null, strange!!!", bill)
}
}
s.updateOrderByBill(order, nil, false)
if time.Now().Sub(order.OrderCreatedAt) < 2*time.Minute { // 京东一些门店设置成了接单即拣货完成,这种情况下自动调用拣货完成
s.autoPickupGood(savedOrderInfo)
}
} else {
needAddTip = false
s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
}
}
if needAddTip {
if handler := partner.GetWaybillTipUpdater(bill.WaybillVendorID); handler != nil {
if storeDetail, err2 := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID); err2 == nil {
handler.UpdateWaybillTip(jxcontext.AdminCtx, order.VendorOrgCode, order.VendorStoreID, order.VendorOrderID, bill.VendorWaybillID, bill.VendorWaybillID2, utils.Int2Str(storeDetail.CityCode), order.WaybillTipMoney)
}
}
s.updateOrderByBill(order, nil, false)
if time.Now().Sub(order.OrderCreatedAt) < 2*time.Minute { // 京东一些门店设置成了接单即拣货完成,这种情况下自动调用拣货完成
s.autoPickupGood(savedOrderInfo)
}
} else {
s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
}
}
flag2Clear := model.WaybillVendorID2Mask(bill.WaybillVendorID)
@@ -840,6 +857,7 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Wa
ts.StopTimer(statusType, vendorID, status)
}, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID))
})
savedOrderInfo.AddTimer(timerInfo)
}
globals.SugarLogger.Debugf("resetTimer, orderID:%s, statusType:%d, status:%d, timeout:%v", order.VendorOrderID, statusType, status, timeout)
} else {
@@ -1184,29 +1202,41 @@ func (s *DefScheduler) watchOrderWaybills(savedOrderInfo *WatchOrderInfo) {
savedOrderInfo.SetOrder(order)
if isNeedWatch3rdWaybill(order) {
if isNeedWatchWaybillTip(order) {
// tipFee := getWaybillTip(order)
// if tipFee > order.WaybillTipMoney {
// vendorStatus := fmt.Sprintf("应设置小费:%s", jxutils.IntPrice2StandardCurrencyString(tipFee))
// remark := ""
// if false {
// err = s.SetOrderWaybillTipByOrder(jxcontext.AdminCtx, order, tipFee)
// if err == nil {
// vendorStatus += "成功"
// } else {
// vendorStatus += "失败"
// remark = fmt.Sprint(err)
// }
// } else {
// vendorStatus += "空操作"
// }
// partner.CurOrderManager.OnOrderMsg(order, vendorStatus, remark)
// }
if handler, ok := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).(partner.IAddWaybillTip); ok && handler != nil {
var remark string
tipFee := getWaybillTip(order)
vendorStatus := fmt.Sprintf("设置小费:%s", jxutils.IntPrice2StandardCurrencyString(tipFee))
if curTipFee, err := handler.GetWaybillTip(jxcontext.AdminCtx, order); err == nil {
tipFee2Add := tipFee - curTipFee
vendorStatus += fmt.Sprintf(", 本次添加:%s", jxutils.IntPrice2StandardCurrencyString(tipFee2Add))
if false { //tipFee2Add > 0 {
err := handler.AddWaybillTip(jxcontext.AdminCtx, order, tipFee2Add)
if err == nil {
vendorStatus += "成功"
order.WaybillTipMoney += tipFee2Add
partner.CurOrderManager.UpdateOrderFields(order, []string{"WaybillTipMoney"})
} else {
vendorStatus += "失败"
remark = fmt.Sprint(err)
}
tipFee2Add := tipFee - order.WaybillTipMoney
vendorStatus += fmt.Sprintf(", 本次添加:%s", jxutils.IntPrice2StandardCurrencyString(tipFee2Add))
if false { //tipFee2Add > 0 {
err := handler.UpdateWaybillTip(jxcontext.AdminCtx, order.VendorOrgCode, order.VendorStoreID, order.VendorOrderID, order.VendorOrderID, "", "", tipFee)
if err == nil {
vendorStatus += "成功"
order.WaybillTipMoney = tipFee
partner.CurOrderManager.UpdateOrderFields(order, []string{"WaybillTipMoney"})
} else {
vendorStatus += "空操作"
vendorStatus += "失败"
remark = fmt.Sprint(err)
}
} else {
vendorStatus += "失败"
remark = fmt.Sprint(err)
vendorStatus += "空操作"
}
partner.CurOrderManager.OnOrderMsg(order, vendorStatus, remark)
}
@@ -1251,18 +1281,35 @@ func OnDefSchConfChanged(key, value string) {
}
}
func setFakeActualPayPrice(order *model.GoodsOrder) (newOrder *model.GoodsOrder) {
orderCopy := *order
storeDetail, err := dao.GetStoreDetail(dao.GetDB(), order.JxStoreID, order.VendorID)
if err == nil {
if storeDetail.PayPercentage < 50 {
orderCopy.ActualPayPrice = order.TotalShopMoney * (100 - int64(storeDetail.PayPercentage/2)) * 100
} else {
orderCopy.ActualPayPrice = order.EarningPrice
}
}
newOrder = &orderCopy
return newOrder
}
func (s *DefScheduler) notifyNewOrder(order *model.GoodsOrder) {
if order.Flag&model.OrderFlagMaskFake == 0 {
utils.CallFuncAsync(func() {
order = setFakeActualPayPrice(order)
netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order)
weixinmsg.NotifyNewOrder(order)
smsmsg.NotifyNewOrder(order)
OrderProfitWarning(order)
})
}
}
func (s *DefScheduler) notifyUserApplyCancel(order *model.GoodsOrder, cancelReason string) {
utils.CallFuncAsync(func() {
order = setFakeActualPayPrice(order)
weixinmsg.NotifyUserApplyCancel(order, cancelReason)
})
}
@@ -1270,6 +1317,7 @@ func (s *DefScheduler) notifyUserApplyCancel(order *model.GoodsOrder, cancelReas
func (s *DefScheduler) notifyOrderCanceled(order *model.GoodsOrder) {
if order.Flag&model.OrderFlagMaskFake == 0 {
utils.CallFuncAsync(func() {
order = setFakeActualPayPrice(order)
weixinmsg.NotifyOrderCanceled(order)
smsmsg.NotifyOrderCanceled(order)
})
@@ -1291,3 +1339,46 @@ func isOrderCanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool) {
}
return isCan
}
//订单预计利润若低于0则向门店运营负责人发送钉钉消息
func OrderProfitWarning(order *model.GoodsOrder) {
var (
operatorName string
operatorPhone string
noticeMsg string
profit float64
storeID int
)
db := dao.GetDB()
if order == nil {
return
}
if order.TotalShopMoney == 0 {
globals.SugarLogger.Debugf("OrderProfitWarning TotalShopMoney=0 orderID:%s", order.VendorOrderID)
return
}
storeID = jxutils.GetShowStoreIDFromOrder(order)
storeDetail, err := dao.GetStoreDetail(db, storeID, order.VendorID)
if storeDetail != nil && err == nil {
payPercentage := storeDetail.PayPercentage
if payPercentage >= 50 {
profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney-order.EarningPrice-order.DistanceFreightMoney-order.WaybillTipMoney)) / 100
} else {
profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney*int64(payPercentage)/200)) / 100
}
if profit < 0 {
if storeDetail.OperatorPhone != "" {
operatorName = storeDetail.OperatorName
operatorPhone = storeDetail.OperatorPhone
} else if storeDetail.OperatorPhone2 != "" {
operatorName = storeDetail.OperatorName2
operatorPhone = storeDetail.OperatorPhone2
}
noticeMsg = fmt.Sprintf("利润 [%v],运营负责人:[%v]门店ID[%v]平台门店ID[%v],门店名:[%v],订单号(点击进入详情)%v", profit, operatorName, order.StoreID, order.VendorStoreID, order.StoreName, globals.BackstageHost+"/#/ordermanager/"+order.VendorOrderID)
user, err := dao.GetUserByID(db, "mobile", operatorPhone)
if user != nil && err == nil {
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "警告此订单利润低于0", noticeMsg)
}
}
}
}

View File

@@ -214,13 +214,13 @@ func (s *DefScheduler) QueryOrderWaybillFeeInfoEx(ctx *jxcontext.Context, vendor
if err != nil {
return nil, err
}
waybillList, err := partner.CurOrderManager.GetOrderWaybillInfo(ctx, vendorOrderID, vendorID, true)
waybillList, err := partner.CurOrderManager.GetOrderWaybillInfo(ctx, vendorOrderID, vendorID, true, false)
if err != nil {
return nil, err
}
waybillMap := make(map[int]*model.Waybill)
for _, bill := range waybillList {
waybillMap[bill.WaybillVendorID] = bill
waybillMap[bill.WaybillVendorID] = &bill.Waybill
}
deliveryFeeMap = make(map[int]*partner.WaybillFeeInfo)
@@ -238,7 +238,7 @@ func (s *DefScheduler) QueryOrderWaybillFeeInfoEx(ctx *jxcontext.Context, vendor
if storeCourier.Status != model.StoreStatusOpened {
feeInfo = &partner.WaybillFeeInfo{
ErrCode: partner.WaybillFeeErrCodeCourierNotOpen,
ErrStr: fmt.Sprintf("%d配送门店没有启用", storeCourier.VendorID),
ErrStr: fmt.Sprintf("暂未开通,联系运营"),
}
} else {
if handler := partner.GetDeliveryPlatformFromVendorID(storeCourier.VendorID); handler != nil {

View File

@@ -113,7 +113,7 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac
skuIDs := jxutils.IntMap2List(skuIDMap)
// 判断活动是否重叠的检查,当前忽略京东平台及所有结算信息
if !(len(vendorIDs) == 1 && vendorIDs[0] == model.VendorIDJD || act.Type == model.ActSkuFake) {
effectActStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, storeIDs, skuIDs, act.BeginAt, act.EndAt)
effectActStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, act.Type, storeIDs, skuIDs, act.BeginAt, act.EndAt)
if err != nil {
globals.SugarLogger.Errorf("GetEffectiveActStoreSkuInfo can not get sku promotion info for error:%v", err)
return nil, nil, nil, err
@@ -138,62 +138,64 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac
for _, vendorID := range vendorIDs {
storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID)
if err = err2; err == nil {
if storeDetail.IsSync != 0 && storeDetail.Status != model.StoreStatusDisabled && storeDetail.VendorStatus != model.StoreStatusDisabled {
for _, v := range oneStoreSkuParam {
validVendorMap[vendorID] = 1
validSkuMap[v.SkuID] = 1
v.ActID = act.ID
actSkuMap := &model.ActStoreSkuMap{
ActID: act.ID,
StoreID: storeID,
SkuID: v.SkuID,
VendorID: vendorID,
}
v.OriginalPrice = actSkuMap.VendorPrice
storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]
if storeSkuInfo != nil {
jxPrice := storeSkuInfo.Price
actSkuMap.VendorPrice = int64(getVendorPriceFromStoreSkuBind(storeSkuInfo, vendorID))
v.OriginalPrice = int64(jxPrice)
}
var err2 error
if act.Type != model.ActSkuFake { // 非结算,要计算实际活动价格
if storeSkuInfo == nil {
v.ErrMsg = fmt.Sprintf("门店:%d没有关注商品:%d", v.StoreID, v.SkuID)
wrongSkuList = append(wrongSkuList, v)
continue
if storeDetail.IsSync != 0 {
if act.Type == model.ActSkuFake ||
storeDetail.Status != model.StoreStatusDisabled && storeDetail.VendorStatus != model.StoreStatusDisabled {
for _, v := range oneStoreSkuParam {
validVendorMap[vendorID] = 1
validSkuMap[v.SkuID] = 1
v.ActID = act.ID
actSkuMap := &model.ActStoreSkuMap{
ActID: act.ID,
StoreID: storeID,
SkuID: v.SkuID,
VendorID: vendorID,
}
if !(vendorID == model.VendorIDJX || act.Type == model.ActSkuFake) {
actSkuMap.SyncStatus = model.SyncFlagNewMask
storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]
if storeSkuInfo != nil {
jxPrice := storeSkuInfo.Price
actSkuMap.VendorPrice = int64(getVendorPriceFromStoreSkuBind(storeSkuInfo, vendorID))
v.OriginalPrice = int64(jxPrice)
}
if v.ActPrice != 0 {
actSkuMap.ActualActPrice = v.ActPrice
} else {
percentage := act.PricePercentage
if v.PricePercentage != 0 {
percentage = v.PricePercentage
var err2 error
if act.Type != model.ActSkuFake { // 非结算,要计算实际活动价格
if storeSkuInfo == nil {
v.ErrMsg = fmt.Sprintf("门店:%d没有关注商品:%d", v.StoreID, v.SkuID)
wrongSkuList = append(wrongSkuList, v)
continue
}
actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(int(actSkuMap.VendorPrice), percentage, 0))
if actSkuMap.ActualActPrice > 10 {
actSkuMap.ActualActPrice = int64(math.Floor(float64(actSkuMap.ActualActPrice)/10) * 10)
if !(vendorID == model.VendorIDJX || act.Type == model.ActSkuFake) {
actSkuMap.SyncStatus = model.SyncFlagNewMask
}
if v.ActPrice != 0 {
actSkuMap.ActualActPrice = v.ActPrice
} else {
percentage := act.PricePercentage
if v.PricePercentage != 0 {
percentage = v.PricePercentage
}
actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(int(actSkuMap.VendorPrice), percentage, 0))
if actSkuMap.ActualActPrice > 10 {
actSkuMap.ActualActPrice = int64(math.Floor(float64(actSkuMap.ActualActPrice)/10) * 10)
}
}
if actSkuMap.ActualActPrice <= 0 {
actSkuMap.ActualActPrice = 1
}
if err2 = checkDiscountValidation(vendorIDs, act.Type, float64(actSkuMap.ActualActPrice)*100/float64(actSkuMap.VendorPrice)); err2 != nil {
v.ErrMsg = err2.Error()
v.ActualActPrice = actSkuMap.ActualActPrice
v.VendorPrice = actSkuMap.VendorPrice
wrongSkuList = append(wrongSkuList, v)
}
}
if actSkuMap.ActualActPrice <= 0 {
actSkuMap.ActualActPrice = 1
}
if err2 = checkDiscountValidation(vendorIDs, act.Type, float64(actSkuMap.ActualActPrice)*100/float64(actSkuMap.VendorPrice)); err2 != nil {
v.ErrMsg = err2.Error()
v.ActualActPrice = actSkuMap.ActualActPrice
v.VendorPrice = actSkuMap.VendorPrice
wrongSkuList = append(wrongSkuList, v)
if err2 == nil {
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
}
}
if err2 == nil {
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
}
wholeValidVendorMap[vendorID] = 1
}
wholeValidVendorMap[vendorID] = 1
}
} else if !dao.IsNoRowsError(err) {
return nil, nil, nil, err
@@ -318,8 +320,12 @@ func checkDiscountValidation(vendorIDs []int, actType int, pricePercentage float
} else if len(vendorIDs) > 0 && vendorIDs[0] == model.VendorIDMTWM && pricePercentageMin < minDiscount4SkuDirectDownMTWM {
err = fmt.Errorf("美团平台%s活动折扣必须大于:%d", model.ActTypeName[actType], minDiscount4SkuDirectDownMTWM)
}
} else if actType == model.ActSkuSecKill && pricePercentageMax > maxDiscount4SkuSecKill {
err = fmt.Errorf("%s活动折扣必须小于:%d", model.ActTypeName[actType], maxDiscount4SkuSecKill)
} else if actType == model.ActSkuSecKill {
if len(vendorIDs) > 0 && vendorIDs[0] == model.VendorIDMTWM && pricePercentageMax > minDiscount4SkuDirectDownMTWM {
err = fmt.Errorf("美团平台%s活动折扣必须小于:%d", model.ActTypeName[actType], minDiscount4SkuDirectDownMTWM)
} else if pricePercentageMax > maxDiscount4SkuSecKill {
err = fmt.Errorf("%s活动折扣必须小于:%d", model.ActTypeName[actType], maxDiscount4SkuSecKill)
}
}
return err
}
@@ -341,8 +347,6 @@ func checkActValidation(act *model.Act, vendorIDs []int) (err error) {
errList.AddErr(fmt.Errorf("必须指定缺省活动折扣"))
} else if err = checkDiscountValidation(vendorIDs, act.Type, float64(act.PricePercentage)); err != nil {
errList.AddErr(err)
} else if act.Type == model.ActSkuSecKill && vendorIDMap[model.VendorIDMTWM] == 1 {
errList.AddErr(fmt.Errorf("%s平台不支持%s活动", model.VendorChineseNames[model.VendorIDMTWM], model.ActTypeName[model.ActSkuSecKill]))
}
} else if act.Type == model.ActSkuFake {
@@ -611,7 +615,7 @@ func GetActStoreSkuInfo(ctx *jxcontext.Context, actID int, vendorIDs []int, keyw
return nil, err
}
for _, v := range actStoreSkuList {
v.SkuName = jxutils.ComposeSkuName(v.Prefix, v.SkuNameName, v.Comment, v.Unit, v.SpecQuality, v.SpecUnit, 0)
v.SkuName = jxutils.ComposeSkuName(v.Prefix, v.SkuNameName, v.Comment, v.Unit, v.SpecQuality, v.SpecUnit, 0, v.ExPrefix, v.ExPrefixBegin, v.ExPrefixEnd)
}
if pageSize > 0 && pageSize != model.UnlimitedPageSize {
pagedInfo := &model.PagedInfo{
@@ -760,7 +764,7 @@ func SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, actID int, vendor
if vendorIDs == nil {
vendorIDs = partner.GetVendorIDsFromActMap(actMap)
}
if len(vendorIDs) == 0 || actMap[vendorIDs[0]].Type == model.ActSkuFake {
if len(vendorIDs) == 0 || vendorIDs[0] == model.VendorIDJX || actMap[vendorIDs[0]].Type == model.ActSkuFake {
return "", nil
}
task := tasksch.NewParallelTask("SyncAct", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
@@ -888,16 +892,15 @@ func RefreshPageActs(ctx *jxcontext.Context, vendorIDs []int, createdFrom time.T
return hint, err
}
func DeleteSkusFromAct(ctx *jxcontext.Context, vendorID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
func DeleteSkusFromAct(ctx *jxcontext.Context, vendorID int, actTypes, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
actMap := make(map[int]*model.Act)
for _, skuID := range skuIDs {
pagedInfo, err2 := dao.QueryActs(db, 0, 0, -1, -1, "", vendorID, []int{model.ActStatusCreated}, []int{model.ActSkuDirectDown, model.ActSkuSecKill}, nil, 0, skuID, 0,
pagedInfo, err2 := dao.QueryActs(db, 0, 0, -1, -1, "", vendorID, []int{model.ActStatusCreated}, actTypes, nil, 0, skuID, 0,
utils.DefaultTimeValue, utils.DefaultTimeValue, time.Now().Add(-24*30*3*time.Hour), utils.DefaultTimeValue)
if err = err2; err != nil {
return "", err
}
// globals.SugarLogger.Debug(utils.Format4Output(pagedInfo, false))
for _, v := range pagedInfo.Data {
actMap[v.Act.ID] = &v.Act
}
@@ -951,7 +954,7 @@ func DeleteSkusFromAct(ctx *jxcontext.Context, vendorID int, skuIDs []int, isAsy
return hint, err
}
func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, storeSkuList []*ActStoreSkuParam, isAsync bool) (hint string, err error) {
func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, storeSkuList []*ActStoreSkuParam, lockTime time.Time, isAsync bool) (hint string, err error) {
var wrongSkuList []*ActStoreSkuParam
var storeSkuBindList []*model.StoreSkuBind
@@ -985,13 +988,15 @@ func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, s
}
}
if storeSkuBind != nil {
dao.SetStoreSkuBindVendorPrice(storeSkuBind, vendorID, vendorPrice)
dao.SetStoreSkuBindVendorPrice(storeSkuBind, vendorID, vendorPrice, lockTime)
if vendorID != model.VendorIDJX {
dao.SetStoreSkuBindSyncStatus(storeSkuBind, vendorID, dao.GetStoreSkuBindSyncStatus(storeSkuBind, vendorID)|model.SyncFlagPriceMask)
}
storeSkuBind.LastOperator = ctx.GetUserName()
storeSkuBindList = append(storeSkuBindList, storeSkuBind)
}
} else if dao.IsNoRowsError(err) { // 忽略不存在错
err = nil
} else {
errList.AddErr(fmt.Errorf("获取门店:%d商品:%d出错:%s", v.StoreID, v.SkuID, err))
}

View File

@@ -100,6 +100,8 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
"storePriceTypeName": model.StorePriceTypeName,
"payStatusName": model.PayStatusName,
"refundStatusName": model.RefundStatusName,
"autoReplyTypeName": model.AutoReplyTypeName,
"complaintReasons": model.ComplaintReasons,
},
}
}

View File

@@ -7,6 +7,12 @@ import (
"strings"
"time"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/jx-callback/globals/api"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/baseapi/utils/errlist"
"git.rosy.net.cn/jx-callback/business/jxutils"
@@ -54,7 +60,7 @@ func GetVendorCategories(ctx *jxcontext.Context, vendorID int, parentID string)
// parentID 为-1表示所有
func GetCategories(ctx *jxcontext.Context, parentID int) (catList []*dao.SkuCategoryWithVendor, err error) {
db := dao.GetDB()
cats, err := dao.GetCategories(db, parentID, nil)
cats, err := dao.GetCategories(db, parentID, 0, nil)
if err == nil {
var ids []int
for _, v := range cats {
@@ -516,7 +522,10 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
t1.status,
t1.is_spu,
t1.desc_img,
t1.upc`
t1.upc,
t1.ex_prefix,
t1.ex_prefix_begin,
t1.ex_prefix_end`
if isBySku {
sql += `,
t2.id`
@@ -545,6 +554,9 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
t1.upc,
t1.jd_id,
t1.jd_sync_status,
t1.ex_prefix,
t1.ex_prefix_begin,
t1.ex_prefix_end,
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"id":', t2.id, ',"comment":"', t2.comment, '","status":', t2.status,
',"createdAt":"', CONCAT(REPLACE(t2.created_at," ","T"),"+08:00"), '","updatedAt":"', CONCAT(REPLACE(t2.updated_at," ","T"),"+08:00"),
'","lastOperator":"', t2.last_operator, '","specQuality":', t2.spec_quality, ',"specUnit":"', t2.spec_unit,
@@ -575,6 +587,7 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
var skuIDs []int
for _, skuName := range skuNamesInfo.SkuNames {
skuName.FullName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, "", "", 0, "", 0, skuName.ExPrefix, skuName.ExPrefixBegin, skuName.ExPrefixEnd)
if skuName.SkusStr != "" {
if err = utils.UnmarshalUseNumber([]byte(skuName.SkusStr), &skuName.Skus); err != nil {
dao.Rollback(db)
@@ -646,17 +659,14 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s
if hasSensitiveWord, err := CheckHasSensitiveWord(skuNameExt.Name); hasSensitiveWord {
return nil, err
}
upc := utils.Pointer2String(skuNameExt.Upc)
if upc == "" {
skuNameExt.Upc = nil
} else if !jxutils.IsUpcValid(upc) {
return nil, fmt.Errorf("upc:%s不合法请仔细检查", upc)
}
db := dao.GetDB()
if skuNameExt.Upc != "" {
err = dao.GetEntity(db, &skuNameExt.SkuName, "Upc")
if err == nil {
return nil, fmt.Errorf("UPC:%s重复", skuNameExt.Upc)
} else if !dao.IsNoRowsError(err) {
return nil, err
}
err = nil
}
skuNameExt.SkuName.Status = model.SkuStatusNormal
if skuNameExt.IsSpu == 1 {
return nil, fmt.Errorf("不允许创建多规格商品")
@@ -776,19 +786,14 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
valid = utils.RemoveGeneralMapKeys(valid, model.FieldSpecQuality, model.FieldSpecUnit)
_, hasPlaces := payload["places"]
if len(valid) > 0 || hasPlaces {
globals.SugarLogger.Debugf("UpdateSkuName valid:%s", utils.Format4Output(valid, false))
if upc, _ := valid["upc"].(string); upc != "" {
skuName := &model.SkuName{
Upc: upc,
if valid["Upc"] != nil {
if upc, _ := valid["Upc"].(string); upc == "" {
valid["Upc"] = nil
} else if !jxutils.IsUpcValid(upc) {
return 0, fmt.Errorf("upc:%s不合法请仔细检查", upc)
}
err = dao.GetEntity(db, skuName, "Upc")
if err == nil {
return 0, fmt.Errorf("UPC:%s重复", upc)
} else if !dao.IsNoRowsError(err) {
return 0, err
}
err = nil
}
globals.SugarLogger.Debugf("UpdateSkuName valid:%s", utils.Format4Output(valid, false))
for _, imgName := range []string{"img", "img2"} {
if valid[imgName] != nil {
if imgStr := utils.Interface2String(valid[imgName]); imgStr != "" {
@@ -846,7 +851,6 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
}
}
}
skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil)
if err = err2; err == nil {
for _, v := range skuList {
@@ -865,7 +869,6 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
}
}
}
skuIDs, err2 := dao.GetSkuIDByNames(db, []int{nameID})
if err = err2; err != nil {
dao.Rollback(db)
@@ -1289,3 +1292,146 @@ func SortCategorySkus(ctx *jxcontext.Context, catID int, skuIDList []int) (err e
}
return err
}
func GetJdUpcCodeByName(ctx *jxcontext.Context, name, upcCode string) (productInfos []*jdapi.ProductInfo, err error) {
var (
pageNo = 5
pageSize = 30
pageNoList []int
)
if name == "" && upcCode == "" {
return nil, fmt.Errorf("至少输入一个条件查询商品名或者upc码")
}
for i := 1; i < pageNo+1; i++ {
pageNoList = append(pageNoList, i)
}
task := tasksch.NewParallelTask("获取京东商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
pageNum := batchItemList[0].(int)
productInfo, err := api.JdAPI.GetJdUpcCodeByName(name, upcCode, pageNum, pageSize)
if err != nil {
return retVal, err
}
for _, v := range productInfo {
_, name, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.OriginalName)
v.Name = name
v.SpecQuality = specQuality
v.SpecUnit = specUnit
}
retVal = productInfo
return retVal, err
}, pageNoList)
tasksch.HandleTask(task, nil, true).Run()
productInfoInterface, err := task.GetResult(0)
for _, v := range productInfoInterface {
productInfos = append(productInfos, v.(*jdapi.ProductInfo))
}
return productInfos, err
}
func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
fromTimeP time.Time
toTimeP time.Time
db = dao.GetDB()
)
if fromTime != "" {
fromTimeP = utils.Time2Date(utils.Str2Time(fromTime))
}
if toTime != "" {
toTimeP = utils.Time2Date(utils.Str2Time(toTime))
}
if toTimeP.Before(fromTimeP) {
return "", fmt.Errorf("结束时间不可以小于开始时间!开始时间:[%v],结束时间:[%v]", fromTimeP, toTimeP)
}
task := tasksch.NewParallelTask("批量设置商品前缀", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
step := batchItemList[0].(int)
now := utils.Time2Date(time.Now())
switch step {
case 0:
task := tasksch.NewParallelTask("批量设置商品前缀", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
nameID := batchItemList[0].(int)
payload := map[string]interface{}{
"exPrefix": exPrefix,
"exPrefixBegin": fromTimeP,
"exPrefixEnd": toTimeP,
}
if now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) >= 0 {
_, err = UpdateSkuName(ctx, nameID, payload)
} else if now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0 {
payload["exPrefixBegin"] = nil
payload["exPrefixEnd"] = nil
_, err = UpdateSkuName(ctx, nameID, payload)
} else {
skuList, err := dao.GetSkus(db, nil, []int{nameID}, nil, nil)
if err == nil && len(skuList) > 0 {
if skuList[0].ExPrefixBegin != nil {
_, err = UpdateSkuName(ctx, nameID, payload)
CurVendorSync.SyncStoresSkus2(ctx, db, partner.GetSingleStoreVendorIDs(), nil, false, []int{skuList[0].ID}, nil, model.SyncFlagModifiedMask, true, true)
} else {
skuName := &model.SkuName{
ExPrefix: exPrefix,
ExPrefixBegin: &fromTimeP,
ExPrefixEnd: &toTimeP,
}
skuName.ID = nameID
skuName.LastOperator = ctx.GetLoginID()
skuName.UpdatedAt = time.Now()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
_, err = dao.UpdateEntity(db, skuName, "ExPrefix", "ExPrefixBegin", "ExPrefixEnd", "LastOperator", "UpdatedAt")
dao.Commit(db)
}
}
}
return retVal, err
}, nameIDs)
tasksch.HandleTask(task, nil, true).Run()
_, err = task.GetResult(0)
case 1:
if (now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) >= 0) || (now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0) {
var skuIDs []int
skuList, err2 := dao.GetSkus(db, nil, nameIDs, nil, nil)
if err = err2; err == nil {
if len(skuList) > 0 {
for _, v := range skuList {
skuIDs = append(skuIDs, v.ID)
}
CurVendorSync.SyncStoresSkus2(ctx, db, partner.GetSingleStoreVendorIDs(), nil, false, skuIDs, nil, model.SyncFlagModifiedMask, true, true)
}
}
}
}
return retVal, err
}, []int{0, 1})
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
_, err = task.GetResult(0)
hint = "1"
} else {
hint = task.GetID()
}
return hint, err
}
func SetSingleStoreSkuSyncModifyStatus(db *dao.DaoDB, vendorIDs []int) (err error) {
_, err = dao.UpdateStoreSkuBindSyncStatusForExPrefix(db, vendorIDs)
return err
}
func SetMultiStoreSkuSyncModifyStatus(db *dao.DaoDB, vendorIDs []int) (err error) {
_, err = dao.UpdateSkuSyncStatusForExPrefix(db, vendorIDs)
return err
}
func DeleteSkuNameExPrefixOverdue(db *dao.DaoDB) (err error) {
_, err = dao.DeleteSkuNameExPrefixOverdue(db)
return err
}

View File

@@ -11,6 +11,7 @@ import (
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/360EntSecGroup-Skylar/excelize"
@@ -145,6 +146,11 @@ type VendorStoreExcel struct {
OperatorName2 string `json:"运营负责人2"`
}
type JdStoreLevelExt struct {
Level string `json:"level`
PageNo int `json:"pageNo"`
}
var (
ErrMissingInput = errors.New("没有有效的输入参数")
ErrCanNotFindVendor = errors.New("vendorID参数不合法")
@@ -167,6 +173,7 @@ var (
"deliveryRangeType": 1,
"deliveryRange": 1,
"status": 1,
"promoteInfo": 1,
}
WatchVendorStoreTimeList = []string{
@@ -204,6 +211,7 @@ var (
"18328080405": "18328080405", //肖娜娜的手机
"13350726500": "13350726500", //谭翔心
"15928865396": "15928865396", //何佳梦
"18048531223": "18048531223", //石老板
}
)
@@ -830,6 +838,10 @@ func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interfa
}
}
if valid["promoteInfo"] != nil {
valid["promoteInfo"] = strings.ReplaceAll(valid["promoteInfo"].(string), "{phone}", store.Tel1)
}
for k, _ := range valid {
if roleMap[k] != "" {
if authInfo, err := ctx.GetV2AuthInfo(); err == nil {
@@ -1042,6 +1054,7 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, vendorID int, vend
userName := ctx.GetUserName()
storeMap.StoreID = storeID
storeMap.VendorID = vendorID
storeMap.VendorOrgCode = vendorOrgCode
storeMap.Status = model.StoreStatusOpened
storeMap.DeliveryType = model.StoreDeliveryTypeByStore
storeMap.SyncStatus = 0
@@ -1137,6 +1150,12 @@ func UpdateStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendor
if valid["status"] != nil {
syncStatus |= model.SyncFlagStoreStatus
}
if vendorStoreName, ok := valid["vendorStoreName"].(string); ok {
if utf8.RuneCountInString(vendorStoreName) > jdapi.MaxStoreNameLen && vendorID == model.VendorIDJD {
return 0, fmt.Errorf("门店名称不允许超过13位")
}
syncStatus |= model.SyncFlagStoreName
}
for _, v := range [][]string{
[]string{
"pricePercentagePack",
@@ -1177,7 +1196,7 @@ func UpdateStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendor
panic(r)
}
}()
if valid["status"] != nil { // 对于store vendor map只有Status改变才需要同步到厂商
if valid["status"] != nil || valid["vendorStoreName"] != nil { // 对于store vendor map只有Status改变才需要同步到厂商
num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, storeMap, valid, userName, map[string]interface{}{
model.FieldStoreID: storeID,
model.FieldVendorID: vendorID,
@@ -1210,7 +1229,7 @@ func UpdateStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendor
}
}
dao.Commit(db)
if vendorID != model.VendorIDJX && (valid["status"] != nil || valid["freightDeductionPack"] != nil) {
if vendorID != model.VendorIDJX && (valid["status"] != nil || valid["freightDeductionPack"] != nil || valid["vendorStoreName"] != nil) {
_, err = CurVendorSync.SyncStore(ctx, db, vendorID, storeID, false, userName)
}
}
@@ -2529,13 +2548,13 @@ func StoreStatus2Chinese(status int) (str string) {
}
}
func GetStorePriceScore(ctx *jxcontext.Context, storeIDs []int, fromScore, toScore, sort int, snapDate string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
func GetStorePriceScore(ctx *jxcontext.Context, storeIDs, vendorIDs []int, fromScore, toScore, sort int, snapDate string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
var snapDateParam time.Time
db := dao.GetDB()
if snapDate != "" {
snapDateParam = utils.Str2Time(snapDate)
}
storePriceScore, totalCount, err := dao.GetStorePriceScore(db, storeIDs, fromScore, toScore, sort, snapDateParam, offset, pageSize)
storePriceScore, totalCount, err := dao.GetStorePriceScore(db, storeIDs, vendorIDs, fromScore, toScore, sort, snapDateParam, offset, pageSize)
pagedInfo = &model.PagedInfo{
Data: storePriceScore,
TotalCount: totalCount,
@@ -2543,14 +2562,10 @@ func GetStorePriceScore(ctx *jxcontext.Context, storeIDs []int, fromScore, toSco
return pagedInfo, err
}
func CreateStorePriceScore(ctx *jxcontext.Context, forRefresh bool) (err error) {
func CreateStorePriceScore(ctx *jxcontext.Context) (err error) {
db := dao.GetDB()
var snapshotAt time.Time
if forRefresh {
snapshotAt = utils.Time2Date(time.Now().AddDate(0, 0, -1))
} else {
snapshotAt = utils.Time2Date(time.Now())
}
snapshotAt = utils.Time2Date(time.Now().AddDate(0, 0, -1))
storePriceScoreSnapshot, err := dao.GetStorePriceScoreSnapshot(db, snapshotAt)
if len(storePriceScoreSnapshot) > 0 {
dao.Begin(db)
@@ -2574,6 +2589,51 @@ func CreateStorePriceScore(ctx *jxcontext.Context, forRefresh bool) (err error)
}
}
dao.Commit(db)
globals.SugarLogger.Debugf("CreateStorePriceScore")
}
return err
}
func RefreshJdLevel(ctx *jxcontext.Context) (err error) {
db := dao.GetDB()
storeMapList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, model.StoreStatusOpened, -1, "")
if len(storeMapList) > 0 {
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
task := tasksch.NewParallelTask("更新京东门店等级", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
v := batchItemList[0].(*model.StoreMap)
var (
pageLimit = 5
pageNo = 1
level string
)
for ; pageNo < pageLimit+1; pageNo++ {
level, err = jd.GetAPI(v.VendorOrgCode).GetJdStoreLevel(v.VendorOrgCode, v.VendorStoreID, pageNo)
if err != nil {
return retVal, err
}
if level != "" {
break
}
if pageNo == pageLimit {
level = ""
}
}
v.JdStoreLevel = level
_, err = dao.UpdateEntity(db, v, "JdStoreLevel")
return retVal, err
}, storeMapList)
tasksch.HandleTask(task, nil, true).Run()
_, err = task.GetResult(0)
dao.Commit(db)
}
return err
}

View File

@@ -18,6 +18,7 @@ import (
"git.rosy.net.cn/jx-callback/business/jxutils/excel"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
"git.rosy.net.cn/jx-callback/globals/api/apimanager"
"git.rosy.net.cn/jx-callback/business/partner"
@@ -42,6 +43,13 @@ const (
CopyStoreSkuModeUpdatePrice = "updatePrice" // 增量复制价格
)
//通用写入Excel
type ExcelParam struct {
DataList interface{}
SheetName string
TitleList []string
}
// UpdateStoreSku用API调用时
type StoreSkuBindSkuInfo struct {
SkuID int `json:"skuID"`
@@ -117,6 +125,14 @@ type SheetParam struct {
SkuRow int
}
type DataVendorStoreSkuPrice struct {
StoreID string `json:"门店ID"`
StoreName string `json:"门店名"`
SkuID int `json:"商品ID"`
SkuName string `json:"商品名"`
VendorPrice string `json:"平台价"`
}
type DataSuccess struct {
NameID int `json:"商品NameID"`
Name string `json:"商品名称"`
@@ -139,7 +155,7 @@ type DataLock struct {
}
const (
maxStoreNameBind = 3000 // 最大门店SkuName bind个数
maxStoreNameBind = 10000 // 最大门店SkuName bind个数
maxStoreNameBind2 = 10000 // 最大门店乘SkuName个数
AutoSaleAtStr = "22:00:00"
@@ -151,7 +167,14 @@ var (
"18180948107": 1, // 徐
// "13684045763": 1, // 周
}
dataLock DataLock
dataLock DataLock
titleListVendorStoreSkuPrice = []string{
"门店ID",
"门店名",
"商品ID",
"商品名",
"平台价",
}
titleListSuccess = []string{
"商品NameID",
"商品名称",
@@ -319,6 +342,12 @@ func getGetStoresSkusBaseSQL(db *dao.DaoDB, storeIDs, skuIDs []int, isFocus bool
sqlParams = append(sqlParams, skuID)
}
}
if lockTimeStr, ok := params["lockTime"].(string); ok && lockTimeStr != "" {
if timeList, err2 := jxutils.BatchStr2Time(lockTimeStr); err2 == nil {
sql += " AND (t4.jd_lock_time > ? OR t4.mtwm_lock_time > ? OR t4.ebai_lock_time > ? OR t4.jx_lock_time > ?)"
sqlParams = append(sqlParams, timeList[0], timeList[0], timeList[0], timeList[0])
}
}
if isFocus {
if params["fromStatus"] != nil {
fromStatus := params["fromStatus"].(int)
@@ -451,6 +480,7 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo
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_lock_time, t4.ebai_lock_time, t4.mtwm_lock_time, t4.jx_lock_time,
t4.status_sale_begin, t4.status_sale_end
`, jdVendorIDField) + sql
var tmpList []*tGetStoresSkusInfo
@@ -862,9 +892,9 @@ func uniqueStoreNameBind(skuBindInfos []*StoreSkuBindInfo) (outSkuBindInfos []*S
}
func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isScale bool) (needSyncSkus []int, err error) {
if len(storeIDs)*len(skuBindInfos) > maxStoreNameBind2 {
return nil, fmt.Errorf("门店商品信息大于%d", maxStoreNameBind2)
}
// if len(storeIDs)*len(skuBindInfos) > maxStoreNameBind2 {
// return nil, fmt.Errorf("门店商品信息大于%d", maxStoreNameBind2)
// }
storeIDs = uniqueStoreIDs(storeIDs)
skuBindInfos = uniqueStoreNameBind(skuBindInfos)
@@ -991,11 +1021,24 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
setStoreSkuBindStatus(skuBind, model.SyncFlagNewMask)
dao.WrapAddIDCULDEntity(skuBind, userName)
globals.SugarLogger.Debug(utils.Format4Output(skuBind, false))
if err = dao.CreateEntity(db, skuBind); err != nil {
dao.Rollback(db)
return nil, err
if deletedSku := dao.GetDeletedStoreSkuBind(db, skuBind.StoreID, skuBind.SkuID); deletedSku == nil {
if err = dao.CreateEntity(db, skuBind); err != nil {
dao.Rollback(db)
return nil, err
}
num = 1
} else {
// 需要处理,在删除某个门店商品,同步失败的情况下,又把商品重新关注。
// 所以统一处理成恢复删除的记录,这样避免问题
skuBind.ID = deletedSku.ID
// vendorSkuID的赋值意义不大
skuBind.MtwmID = deletedSku.MtwmID
skuBind.EbaiID = deletedSku.EbaiID
if num, err = dao.UpdateEntity(db, skuBind); err != nil {
dao.Rollback(db)
return nil, err
}
}
num = 1
}
} else {
skuBind = &v.StoreSkuBind
@@ -1090,12 +1133,13 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
return skuIDs, err
}
func getSkuSaleStatus(inSkuBind *StoreSkuBindSkuInfo, skuBindInfo *StoreSkuBindInfo) int {
func getSkuSaleStatus(inSkuBind *StoreSkuBindSkuInfo, skuNameBindInfo *StoreSkuBindInfo) int {
tempSale := 0
if inSkuBind != nil {
tempSale = inSkuBind.IsSale
} else {
tempSale = skuBindInfo.IsSale
}
if tempSale == 0 {
tempSale = skuNameBindInfo.IsSale
}
if tempSale == -1 {
return model.StoreSkuBindStatusDontSale
@@ -2139,12 +2183,118 @@ func GetTopSkusByStoreIDs(ctx *jxcontext.Context, storeIDs []int) (storeSkuNameE
return storeSkuNameExt, err
}
func GetTopCategorysByStoreIDs(ctx *jxcontext.Context, storeIDs []int) (skuCategory []*model.SkuCategory, err error) {
func GetTopSkusByCityCode(ctx *jxcontext.Context, cityCode, storeID int) (skuNameAndPlaceList []*dao.SkuNameAndPlace, err error) {
db := dao.GetDB()
orderCreate := time.Now().AddDate(0, -1, 0)
skuNameAndPlace, err := dao.GetTopSkusByCityCode(db, cityCode, orderCreate)
if storeID > 0 {
var skuNameList []*model.SkuName
//未关注不可售的商品nameID列表
sql := `
SELECT DISTINCT b.name_id id,1 brand_id
FROM store_sku_bind a
JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ?
WHERE a.deleted_at = ?
AND a.store_id = ?
AND a.status <> ?
AND b.name_id NOT IN(SELECT DISTINCT b.name_id
FROM store_sku_bind a
JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ?
WHERE a.deleted_at = ?
AND a.store_id = ?
AND a.status = ?)
UNION
SELECT DISTINCT a.name_id id,0 brand_id
FROM sku a
LEFT JOIN (SELECT DISTINCT b.name_id
FROM store_sku_bind a
JOIN sku b ON a.sku_id = b.id
WHERE a.deleted_at = ?
AND store_id = ?)b ON a.name_id = b.name_id
WHERE a.status = ?
AND a.deleted_at = ?
AND b.name_id IS NULL
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
utils.DefaultTimeValue,
storeID,
model.StoreSkuBindStatusNormal,
utils.DefaultTimeValue,
utils.DefaultTimeValue,
storeID,
model.StoreSkuBindStatusNormal,
utils.DefaultTimeValue,
storeID,
model.StoreSkuBindStatusNormal,
utils.DefaultTimeValue,
}
err = dao.GetRows(db, &skuNameList, sql, sqlParams...)
var skuNameMap = make(map[int]*model.SkuName)
for _, v := range skuNameList {
skuNameMap[v.ID] = v
}
for _, v := range skuNameAndPlace {
if skuNameMap[v.ID] != nil {
midPrice, _ := dao.GetMidPriceByNameID(db, cityCode, v.ID, utils.Time2Date(time.Now().AddDate(0, 0, -1)))
if midPrice != 0 {
v.Price = midPrice
}
v.Type = skuNameMap[v.ID].BrandID
skuNameAndPlaceList = append(skuNameAndPlaceList, v)
}
}
} else {
skuNameAndPlaceList = append(skuNameAndPlaceList, skuNameAndPlace...)
}
i := 1
for _, v := range skuNameAndPlaceList {
v.Sequence = i
i++
}
if len(skuNameAndPlaceList) <= 100 {
return skuNameAndPlaceList, err
} else {
return skuNameAndPlaceList[0:100], err
}
}
func GetTopCategoriesByStoreIDs(ctx *jxcontext.Context, storeIDs []int) (skuCategory []*model.SkuCategory, err error) {
var (
skuCategory2 []*model.SkuCategory
skuCategoryMap = make(map[int]*model.SkuCategory)
limit = 10
)
if len(storeIDs) == 0 {
return skuCategory, err
}
db := dao.GetDB()
skuCategory, err = dao.GetTopCategorysByStoreIDs(db, storeIDs)
skuCategory, err = dao.GetTopCategoriesByStoreIDs(db, storeIDs, limit)
//若大于等于10个就不用做下面的操作
if len(skuCategory) >= limit {
return skuCategory, err
}
if len(skuCategory) > 0 {
for _, v := range skuCategory {
skuCategoryMap[v.ID] = v
}
}
//推荐分类若不满10个则填满10个
if (len(skuCategory) < limit && len(skuCategory) > 0) || len(skuCategory) == 0 {
skuCategory2, err = dao.GetCategories(db, -1, 1, nil)
if len(skuCategory2) > 0 {
for _, v := range skuCategory2 {
if skuCategoryMap[v.ID] == nil {
if !strings.Contains(v.Name, "赠品") {
skuCategory = append(skuCategory, v)
}
}
if len(skuCategory) >= limit {
break
}
}
}
}
if err != nil {
return nil, err
}
@@ -2155,7 +2305,7 @@ func RefershStoreSkusMidPrice(ctx *jxcontext.Context, storeIDs []int) (err error
db := dao.GetDB()
_, err = dao.RefershStoreSkusMidPrice(db, storeIDs)
if err == nil {
CreateStorePriceScore(ctx, true)
CreateStorePriceScore(ctx)
}
return err
}
@@ -2443,3 +2593,319 @@ func IsChineseChar(str string) bool {
}
return false
}
func GetStoreCategories(ctx *jxcontext.Context, storeID, parentID int) (catList []*model.SkuCategory, err error) {
return dao.GetStoreSkuCategories(dao.GetDB(), storeID, parentID)
}
func GetVendorStoreSkuPrice(ctx *jxcontext.Context, vendorIDs []int, skuID int, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
storeSkuListJD []DataVendorStoreSkuPrice
storeSkuListMT []DataVendorStoreSkuPrice
storeSkuListEB []DataVendorStoreSkuPrice
excelParamList []ExcelParam
)
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
for _, v := range vendorIDs {
vendorID := v
handler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler)
handlerStore := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IStoreHandler)
for _, v := range apimanager.CurAPIManager.GetAppOrgCodeList(vendorID) {
vendorStoreIDs, err2 := handlerStore.GetAllStoresVendorID(ctx, v)
err = err2
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
vendorStoreID := batchItemList[0].(string)
var (
inStoreSkuList []*partner.StoreSkuInfo
storeDetail *dao.StoreDetail
inStoreSku = &partner.StoreSkuInfo{}
outStoreSkuList []*partner.StoreSkuInfo
)
db := dao.GetDB()
skuNameList, err := dao.GetSkus(db, []int{skuID}, nil, nil, nil)
if err != nil {
return retVal, err
}
if partner.IsMultiStore(vendorID) {
multiHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IMultipleStoresHandler)
storeDetail, err = multiHandler.ReadStore(ctx, v, vendorStoreID)
if len(skuNameList) > 0 {
inStoreSku.VendorSkuID = utils.Int64ToStr(skuNameList[0].JdID)
}
} else {
singleHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreHandler)
storeDetail, err = singleHandler.ReadStore(ctx, v, vendorStoreID)
inStoreSku.SkuID = skuID
}
inStoreSkuList = append(inStoreSkuList, inStoreSku)
storeDetail2, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID)
if storeDetail2 != nil {
outStoreSkuList, err = handler.GetStoreSkusBareInfo(ctx, v, task, storeDetail2.ID, vendorStoreID, inStoreSkuList)
} else {
outStoreSkuList, err = handler.GetStoreSkusBareInfo(ctx, v, task, 0, vendorStoreID, inStoreSkuList)
}
if storeDetail != nil {
if len(outStoreSkuList) == 0 {
data := DataVendorStoreSkuPrice{
StoreID: vendorStoreID,
StoreName: storeDetail.Name,
SkuID: skuID,
SkuName: skuNameList[0].Name,
VendorPrice: "",
}
retVal = []DataVendorStoreSkuPrice{data}
} else {
data := DataVendorStoreSkuPrice{
StoreID: vendorStoreID,
StoreName: storeDetail.Name,
SkuID: skuID,
SkuName: skuNameList[0].Name,
VendorPrice: utils.Float64ToStr(utils.Str2Float64(utils.Int64ToStr(outStoreSkuList[0].VendorPrice)) / 100),
}
retVal = []DataVendorStoreSkuPrice{data}
}
}
return retVal, err
}
taskParallel := tasksch.NewParallelTask("获取各平台所有门店某商品价格", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, taskFunc, vendorStoreIDs)
tasksch.HandleTask(taskParallel, task, true).Run()
storeSkuList, _ := taskParallel.GetResult(0)
for _, v := range storeSkuList {
if vendorID == model.VendorIDJD {
storeSkuListJD = append(storeSkuListJD, v.(DataVendorStoreSkuPrice))
}
if vendorID == model.VendorIDEBAI {
storeSkuListEB = append(storeSkuListEB, v.(DataVendorStoreSkuPrice))
}
if vendorID == model.VendorIDMTWM {
storeSkuListMT = append(storeSkuListMT, v.(DataVendorStoreSkuPrice))
}
}
}
}
excelParam1 := ExcelParam{
DataList: storeSkuListJD,
TitleList: titleListVendorStoreSkuPrice,
SheetName: "京东平台",
}
excelParam2 := ExcelParam{
DataList: storeSkuListEB,
TitleList: titleListVendorStoreSkuPrice,
SheetName: "饿百平台",
}
excelParam3 := ExcelParam{
DataList: storeSkuListMT,
TitleList: titleListVendorStoreSkuPrice,
SheetName: "美团平台",
}
excelParamList = append(excelParamList, excelParam1, excelParam2, excelParam3)
case 1:
WriteToExcelNormal(task, "各平台"+utils.Int2Str(skuID)+"商品所有门店价格", excelParamList)
}
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 WriteToExcelNormal(task *tasksch.SeqTask, fileName string, excelParam []ExcelParam) (err error) {
var sheetList []*excel.Obj2ExcelSheetConfig
for _, v := range excelParam {
if v.DataList != nil {
excelConf := &excel.Obj2ExcelSheetConfig{
Title: v.SheetName,
Data: v.DataList,
CaptionList: v.TitleList,
}
sheetList = append(sheetList, excelConf)
}
}
downloadURL, fileNameResult, err := jxutils.UploadExeclAndPushMsg(sheetList, fileName)
if err != nil {
baseapi.SugarLogger.Errorf("WriteToExcel:upload %s failed error:%v", fileNameResult, err)
} else {
noticeMsg := fmt.Sprintf("[详情点我]path=%s \n", downloadURL)
task.SetNoticeMsg(noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s success, downloadURL:%s", fileNameResult, downloadURL)
}
return err
}
func FocusStoreSkusByExcel(ctx *jxcontext.Context, files []*multipart.FileHeader, isAsync, isContinueWhenError bool) (hint string, err error) {
if len(files) == 0 {
return "", errors.New("没有文件上传!")
}
fileHeader := files[0]
file, err := fileHeader.Open()
hint, err = FocusStoreSkusByExcelBin(ctx, file, isAsync, isContinueWhenError)
file.Close()
return hint, err
}
func FocusStoreSkusByExcelBin(ctx *jxcontext.Context, reader io.Reader, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
skuMap = make(map[int]int)
skuNameMap = make(map[int]int)
skuBindInfos []*StoreSkuBindInfo
db = dao.GetDB()
storeIDs []int
skuIDs []int
)
sheetParam := &SheetParam{
OutSkuIDCol: 1,
SkuPriceCol: 3,
SkuRow: 1,
}
// xlsx, err := excelize.OpenFile("111.xlsx")
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
xlsx, err := excelize.OpenReader(reader)
if err != nil {
return result, err
}
rows, _ := xlsx.GetRows(xlsx.GetSheetName(1))
for rowNum, row := range rows {
if rowNum < sheetParam.SkuRow {
continue
}
GetCellForFocusStoreSkus(db, rowNum, row, sheetParam, skuMap)
}
case 1:
for k, _ := range skuMap {
skuIDs = append(skuIDs, k)
}
skuList, err := dao.GetSkus(db, skuIDs, nil, nil, nil)
if err != nil && len(skuList) == 0 {
return result, err
}
for _, v := range skuList {
var (
price int
specQuality float64
)
if v.Unit == model.SpecialUnit {
if v.SpecUnit == model.SpecUnitNames[1] || v.SpecUnit == model.SpecUnitNames[2] {
specQuality = float64(v.SpecQuality) * 1000
} else {
specQuality = float64(v.SpecQuality)
}
price = int(utils.Float64TwoInt64(utils.Int2Float64(model.SpecialSpecQuality) / specQuality * utils.Int2Float64(skuMap[v.ID])))
} else {
price = skuMap[v.ID]
}
if skuNameMap[v.NameID] < price {
skuNameMap[v.NameID] = price
}
}
for k, v := range skuNameMap {
skuBindInfo := &StoreSkuBindInfo{
NameID: k,
UnitPrice: v,
IsFocus: 1,
IsSale: 1,
}
skuBindInfos = append(skuBindInfos, skuBindInfo)
}
storeList, err := dao.GetStoreList(db, nil, nil, "")
for _, v := range storeList {
storeIDs = append(storeIDs, v.ID)
}
case 2:
UpdateStoresSkus(ctx, storeIDs, skuBindInfos, false, isAsync, isContinueWhenError)
}
return result, err
}
taskSeq := tasksch.NewSeqTask2("根据Excel中skuID批量关注商品", ctx, isContinueWhenError, taskSeqFunc, 3)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
hint = "1"
} else {
hint = taskSeq.GetID()
}
return hint, err
}
func GetCellForFocusStoreSkus(db *dao.DaoDB, rowNum int, row []string, sheetParam *SheetParam, skuMap map[int]int) {
var (
skuID int
price int
)
for k, cell := range row {
if k == sheetParam.OutSkuIDCol {
skuID = int(utils.Str2Int64(cell))
}
if k == sheetParam.SkuPriceCol {
price = int(utils.Float64TwoInt64(utils.Str2Float64(cell) * 100))
}
}
skuMap[skuID] = price
}
func FocusStoreSkusBySku(ctx *jxcontext.Context, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
skuBindInfos []*StoreSkuBindInfo
skuNameMap = make(map[int][]*StoreSkuBindSkuInfo)
storeIDs []int
)
db := dao.GetDB()
skuList, err := dao.GetSkus(db, skuIDs, nil, nil, nil)
storeList, err := dao.GetStoreList(db, nil, nil, "")
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
for _, v := range storeList {
storeIDs = append(storeIDs, v.ID)
}
for _, v := range skuList {
skuNameMap[v.NameID] = append(skuNameMap[v.NameID], &StoreSkuBindSkuInfo{
SkuID: v.ID,
IsSale: 1,
})
}
case 1:
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
store := batchItemList[0].(*model.Store)
for k, v := range skuNameMap {
midPrice, _ := dao.GetMidPriceByNameID(db, store.CityCode, k, utils.Time2Date(time.Now().AddDate(0, 0, -1)))
skuBindInfo := &StoreSkuBindInfo{
NameID: k,
UnitPrice: midPrice,
IsFocus: 1,
Skus: v,
}
retVal = []*StoreSkuBindInfo{skuBindInfo}
}
return retVal, err
}
taskParallel := tasksch.NewParallelTask("根据skuID部分关注商品", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, taskFunc, storeList)
tasksch.HandleTask(taskParallel, task, true).Run()
result1, _ := taskParallel.GetResult(0)
for _, v := range result1 {
skuBindInfos = append(skuBindInfos, v.(*StoreSkuBindInfo))
}
case 2:
UpdateStoresSkus(ctx, storeIDs, skuBindInfos, false, isAsync, isContinueWhenError)
}
return result, err
}
taskSeq := tasksch.NewSeqTask2("根据skuID批量部分关注商品", ctx, isContinueWhenError, taskSeqFunc, 3)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
hint = "1"
} else {
hint = taskSeq.GetID()
}
return hint, err
}

View File

@@ -340,10 +340,10 @@ func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName strin
//多规格商品不用比较数量单位
if jxSkuInfo.IsSpu == 0 {
//jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..)
jxSkuDetailName = jxutils.ComposeSkuName(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, jxSkuInfo.SkuName.Unit, jxSkuInfo.Skus[0].SkuSpecQuality, jxSkuInfo.Skus[0].SkuSpecUnit, 0)
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, jxSkuInfo.SkuName.Unit, jxSkuInfo.Skus[0].SkuSpecQuality, jxSkuInfo.Skus[0].SkuSpecUnit, 0)
} else {
//jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..)
jxSkuDetailName = jxutils.ComposeSkuName(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, "", jxSkuInfo.Skus[0].SkuSpecQuality, "", 0)
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, "", jxSkuInfo.Skus[0].SkuSpecQuality, "", 0)
}
//jxSkuSaleStatus : 商品状态 skustatus 优先级高于 StoreSkuStatus
@@ -462,9 +462,9 @@ func CompareJxAndMultiVenderDepot(ctx *jxcontext.Context, vendorMap map[int]bool
var jxSkuDetailName string
//多规格商品不用比较数量单位
if jxSkuInfo.IsSpu == 0 {
jxSkuDetailName = jxutils.ComposeSkuName(jxSkuInfo.Prefix, jxSkuInfo.Name, jxSkuInfo.Comment, jxSkuInfo.Unit, jxSkuInfo.SpecQuality, jxSkuInfo.SpecUnit, 0)
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.Prefix, jxSkuInfo.Name, jxSkuInfo.Comment, jxSkuInfo.Unit, jxSkuInfo.SpecQuality, jxSkuInfo.SpecUnit, 0)
} else {
jxSkuDetailName = jxutils.ComposeSkuName(jxSkuInfo.Prefix, jxSkuInfo.Name, jxSkuInfo.Comment, "", jxSkuInfo.SpecQuality, "", 0)
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.Prefix, jxSkuInfo.Name, jxSkuInfo.Comment, "", jxSkuInfo.SpecQuality, "", 0)
}
vendorSkuInfoMap := filterVendorSkuInfoMap[skuid]

View File

@@ -18,7 +18,6 @@ import (
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/refutil"
)
type SyncErrResult struct {
@@ -80,36 +79,36 @@ var (
syncErrResultLock SyncErrResultLock
)
func (p *MultiStoreHandlerWrapper) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
if jxutils.IsEmptyID(cat.JdID) {
return nil
}
return p.IMultipleStoresHandler.DeleteCategory(db, cat, userName)
}
// func (p *MultiStoreHandlerWrapper) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
// if jxutils.IsEmptyID(cat.JdID) {
// return nil
// }
// return p.IMultipleStoresHandler.DeleteCategory(db, cat, userName)
// }
func (p *MultiStoreHandlerWrapper) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
if jxutils.IsEmptyID(cat.JdID) {
globals.SugarLogger.Warnf("UpdateCategory fakeid cat:%s should not get here", utils.Format4Output(cat, true))
return nil
}
return p.IMultipleStoresHandler.UpdateCategory(db, cat, userName)
}
// func (p *MultiStoreHandlerWrapper) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
// if jxutils.IsEmptyID(cat.JdID) {
// globals.SugarLogger.Warnf("UpdateCategory fakeid cat:%s should not get here", utils.Format4Output(cat, true))
// return nil
// }
// return p.IMultipleStoresHandler.UpdateCategory(db, cat, userName)
// }
func (p *MultiStoreHandlerWrapper) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
globals.SugarLogger.Debugf("wrapper DeleteSku, sku:%s", utils.Format4Output(sku, false))
if jxutils.IsEmptyID(sku.JdID) {
return nil
}
return p.IMultipleStoresHandler.DeleteSku(db, sku, userName)
}
// func (p *MultiStoreHandlerWrapper) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// globals.SugarLogger.Debugf("wrapper DeleteSku, sku:%s", utils.Format4Output(sku, false))
// if jxutils.IsEmptyID(sku.JdID) {
// return nil
// }
// return p.IMultipleStoresHandler.DeleteSku(db, sku, userName)
// }
func (p *MultiStoreHandlerWrapper) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
if jxutils.IsEmptyID(sku.JdID) {
globals.SugarLogger.Warnf("UpdateSku fakeid sku:%s should not get here", utils.Format4Output(sku, true))
return nil
}
return p.IMultipleStoresHandler.UpdateSku(db, sku, userName)
}
// func (p *MultiStoreHandlerWrapper) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// if jxutils.IsEmptyID(sku.JdID) {
// globals.SugarLogger.Warnf("UpdateSku fakeid sku:%s should not get here", utils.Format4Output(sku, true))
// return nil
// }
// return p.IMultipleStoresHandler.UpdateSku(db, sku, userName)
// }
func (v *VendorSync) GetStoreHandler(vendorID int) partner.IPurchasePlatformHandler {
return partner.GetPurchasePlatformFromVendorID(vendorID)
@@ -129,95 +128,95 @@ func (v *VendorSync) GetSingleStoreHandler(vendorID int) partner.ISingleStoreHan
return nil
}
func (v *VendorSync) syncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorID int, db *dao.DaoDB, cats []*model.SkuCategory, userName string) (err error) {
multiStoresHandler := v.GetMultiStoreHandler(vendorID)
syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[vendorID])
task := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[vendorID]), nil, ctx,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
cat := batchItemList[0].(*model.SkuCategory)
updateFields := []string{syncStatusFieldName}
syncStatus := refutil.GetObjFieldByName(cat, syncStatusFieldName).(int8)
if (syncStatus & model.SyncFlagDeletedMask) != 0 { //删除
if (syncStatus & model.SyncFlagNewMask) == 0 {
err = multiStoresHandler.DeleteCategory(db, cat, userName)
}
} else if (syncStatus & model.SyncFlagNewMask) != 0 { // 新增
err = multiStoresHandler.CreateCategory(db, cat, userName)
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
} else if (syncStatus & model.SyncFlagModifiedMask) != 0 { // 修改
err = multiStoresHandler.UpdateCategory(db, cat, userName)
if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.IntCode() == -3 {
err = nil
}
}
if err == nil {
refutil.SetObjFieldByName(cat, syncStatusFieldName, int8(0))
_, err = dao.UpdateEntity(db, cat, updateFields...)
}
return nil, err
}, cats)
tasksch.HandleTask(task, parentTask, false).Run()
_, err = task.GetResult(0)
return err
}
// func (v *VendorSync) syncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorID int, db *dao.DaoDB, cats []*model.SkuCategory, userName string) (err error) {
// multiStoresHandler := v.GetMultiStoreHandler(vendorID)
// syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[vendorID])
// task := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[vendorID]), nil, ctx,
// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
// cat := batchItemList[0].(*model.SkuCategory)
// updateFields := []string{syncStatusFieldName}
// syncStatus := refutil.GetObjFieldByName(cat, syncStatusFieldName).(int8)
// if (syncStatus & model.SyncFlagDeletedMask) != 0 { //删除
// if (syncStatus & model.SyncFlagNewMask) == 0 {
// err = multiStoresHandler.DeleteCategory(db, cat, userName)
// }
// } else if (syncStatus & model.SyncFlagNewMask) != 0 { // 新增
// err = multiStoresHandler.CreateCategory(db, cat, userName)
// updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
// } else if (syncStatus & model.SyncFlagModifiedMask) != 0 { // 修改
// err = multiStoresHandler.UpdateCategory(db, cat, userName)
// if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.IntCode() == -3 {
// err = nil
// }
// }
// if err == nil {
// refutil.SetObjFieldByName(cat, syncStatusFieldName, int8(0))
// _, err = dao.UpdateEntity(db, cat, updateFields...)
// }
// return nil, err
// }, cats)
// tasksch.HandleTask(task, parentTask, false).Run()
// _, err = task.GetResult(0)
// return err
// }
func (v *VendorSync) SyncCategory(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int, isAsync bool, userName string) (hint string, err error) {
if !globals.IsUseThingMap {
return v.oldSyncCategory(ctx, db, categoryID, isAsync, userName)
}
// if !globals.IsUseThingMap {
// return v.oldSyncCategory(ctx, db, categoryID, isAsync, userName)
// }
return SyncCategories(ctx, nil, nil, nil, []int{categoryID}, isAsync)
}
func (v *VendorSync) oldSyncCategory(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int, isAsync bool, userName string) (hint string, err error) {
globals.SugarLogger.Debug("SyncCategory")
hint, err = v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步分类信息:%d", categoryID), isAsync, false,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
vendorInfo := batchItemList[0].(*MultiStoreVendorInfo)
var cats []*model.SkuCategory
cond := make(map[string]interface{})
if categoryID > 0 {
cond[model.FieldID] = categoryID
} else {
cond[model.FieldLevel] = 1
}
err := dao.GetEntitiesByKV(db, &cats, cond, true)
if err == nil {
err = v.syncCategories(ctx, t, vendorInfo.VendorID, db, cats, userName)
}
if err != nil || categoryID > 0 {
return nil, err
}
cond[model.FieldLevel] = 2
err = dao.GetEntitiesByKV(db, &cats, cond, true)
if err == nil {
err = v.syncCategories(ctx, t, vendorInfo.VendorID, db, cats, userName)
}
return nil, err
})
return "", err
}
// func (v *VendorSync) oldSyncCategory(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int, isAsync bool, userName string) (hint string, err error) {
// globals.SugarLogger.Debug("SyncCategory")
// hint, err = v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步分类信息:%d", categoryID), isAsync, false,
// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
// vendorInfo := batchItemList[0].(*MultiStoreVendorInfo)
// var cats []*model.SkuCategory
// cond := make(map[string]interface{})
// if categoryID > 0 {
// cond[model.FieldID] = categoryID
// } else {
// cond[model.FieldLevel] = 1
// }
// err := dao.GetEntitiesByKV(db, &cats, cond, true)
// if err == nil {
// err = v.syncCategories(ctx, t, vendorInfo.VendorID, db, cats, userName)
// }
// if err != nil || categoryID > 0 {
// return nil, err
// }
// cond[model.FieldLevel] = 2
// err = dao.GetEntitiesByKV(db, &cats, cond, true)
// if err == nil {
// err = v.syncCategories(ctx, t, vendorInfo.VendorID, db, cats, userName)
// }
// return nil, err
// })
// return "", err
// }
func (v *VendorSync) SyncReorderCategories(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int, isAsync bool, userName string) (hint string, err error) {
if !globals.IsUseThingMap {
return v.oldSyncReorderCategories(ctx, db, categoryID, isAsync, userName)
}
// if !globals.IsUseThingMap {
// return v.oldSyncReorderCategories(ctx, db, categoryID, isAsync, userName)
// }
return SyncReorderCategories(ctx, -1, isAsync)
}
func (v *VendorSync) oldSyncReorderCategories(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int, isAsync bool, userName string) (hint string, err error) {
hint, err = v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("分类重排序:%d", categoryID), isAsync, false, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
vendorInfo := batchItemList[0].(*MultiStoreVendorInfo)
multiStoresHandler := v.GetMultiStoreHandler(vendorInfo.VendorID)
err2 := multiStoresHandler.ReorderCategories(db, categoryID, userName)
if err2 == nil {
cat := &model.SkuCategory{}
_, err2 = dao.UpdateEntityByKV(db, cat, utils.Params2Map(dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()]), 0), utils.Params2Map(model.FieldParentID, categoryID))
return nil, err2
}
return nil, err2
})
return "", err
}
// func (v *VendorSync) oldSyncReorderCategories(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int, isAsync bool, userName string) (hint string, err error) {
// hint, err = v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("分类重排序:%d", categoryID), isAsync, false, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
// vendorInfo := batchItemList[0].(*MultiStoreVendorInfo)
// multiStoresHandler := v.GetMultiStoreHandler(vendorInfo.VendorID)
// err2 := multiStoresHandler.ReorderCategories(db, categoryID, userName)
// if err2 == nil {
// cat := &model.SkuCategory{}
// _, err2 = dao.UpdateEntityByKV(db, cat, utils.Params2Map(dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()]), 0), utils.Params2Map(model.FieldParentID, categoryID))
// return nil, err2
// }
// return nil, err2
// })
// return "", err
// }
func (v *VendorSync) SyncStore(ctx *jxcontext.Context, db *dao.DaoDB, vendorID, storeID int, isAsync bool, userName string) (hint string, err error) {
globals.SugarLogger.Debugf("SyncStore, storeID:%d", storeID)
@@ -281,109 +280,109 @@ func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuI
}
func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []int, skuIDs []int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
if !globals.IsUseThingMap {
return v.oldSyncSkus(ctx, db, nameIDs, skuIDs, isAsync, isContinueWhenError, userName)
}
// if !globals.IsUseThingMap {
// return v.oldSyncSkus(ctx, db, nameIDs, skuIDs, isAsync, isContinueWhenError, userName)
// }
return SyncSkus(ctx, nil, nil, nil, nameIDs, skuIDs, isAsync)
}
func (v *VendorSync) oldSyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []int, skuIDs []int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameIDs:%v, skuIDs:%v, userName:%s", ctx.GetTrackInfo(), nameIDs, skuIDs, userName)
isManagedIt := !(len(nameIDs) > 0 && len(nameIDs) <= 2 || len(skuIDs) > 0 && len(skuIDs) < 8)
return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameIDs:%v, skuIDs:%v", nameIDs, skuIDs), isAsync, isManagedIt,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
var resultList []interface{}
vendorInfo := batchItemList[0].(*MultiStoreVendorInfo)
multiStoresHandler := v.GetMultiStoreHandler(vendorInfo.VendorID)
syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()])
dbField := dao.ConvertDBFieldPrefix(model.VendorNames[multiStoresHandler.GetVendorID()])
skuMap := make(map[int]bool)
sql := fmt.Sprintf(`
SELECT DISTINCT t2.*
FROM sku t1
JOIN sku_name t2 ON t2.id = t1.name_id
WHERE t1.%s_sync_status <> 0
`, dbField)
sqlParams := []interface{}{}
if len(nameIDs) > 0 {
sql += " AND t1.name_id IN (" + dao.GenQuestionMarks(len(nameIDs)) + ")"
sqlParams = append(sqlParams, nameIDs)
}
if len(skuIDs) > 0 {
sql += " AND t1.id IN(" + dao.GenQuestionMarks(len(skuIDs)) + ")"
sqlParams = append(sqlParams, skuIDs)
// func (v *VendorSync) oldSyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []int, skuIDs []int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
// globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameIDs:%v, skuIDs:%v, userName:%s", ctx.GetTrackInfo(), nameIDs, skuIDs, userName)
// isManagedIt := !(len(nameIDs) > 0 && len(nameIDs) <= 2 || len(skuIDs) > 0 && len(skuIDs) < 8)
// return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameIDs:%v, skuIDs:%v", nameIDs, skuIDs), isAsync, isManagedIt,
// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
// var resultList []interface{}
// vendorInfo := batchItemList[0].(*MultiStoreVendorInfo)
// multiStoresHandler := v.GetMultiStoreHandler(vendorInfo.VendorID)
// syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()])
// dbField := dao.ConvertDBFieldPrefix(model.VendorNames[multiStoresHandler.GetVendorID()])
// skuMap := make(map[int]bool)
// sql := fmt.Sprintf(`
// SELECT DISTINCT t2.*
// FROM sku t1
// JOIN sku_name t2 ON t2.id = t1.name_id
// WHERE t1.%s_sync_status <> 0
// `, dbField)
// sqlParams := []interface{}{}
// if len(nameIDs) > 0 {
// sql += " AND t1.name_id IN (" + dao.GenQuestionMarks(len(nameIDs)) + ")"
// sqlParams = append(sqlParams, nameIDs)
// }
// if len(skuIDs) > 0 {
// sql += " AND t1.id IN(" + dao.GenQuestionMarks(len(skuIDs)) + ")"
// sqlParams = append(sqlParams, skuIDs)
}
for _, v := range skuIDs {
skuMap[v] = true
}
sql += " ORDER BY t2.id"
// }
// for _, v := range skuIDs {
// skuMap[v] = true
// }
// sql += " ORDER BY t2.id"
var skuNameList []*model.SkuName
err := dao.GetRows(db, &skuNameList, sql, sqlParams...)
if err == nil && len(skuNameList) > 0 {
// todo 同一skuName下的sku顺序处理的原因是京东SPU特殊类型必须要序列化同步才能正常处理, db可能会有多线程问题
task := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[vendorInfo.VendorID]), tasksch.NewParallelConfig().SetParallelCount(10).SetIsContinueWhenError(isContinueWhenError), ctx,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
var resultList []interface{}
skuName := batchItemList[0].(*model.SkuName)
var skuList []*model.Sku
if err = dao.GetRows(db, &skuList, fmt.Sprintf(`
SELECT *
FROM sku
WHERE name_id = ? AND %s_sync_status <> 0
ORDER BY IF(spec_unit IN('kg', 'L'), 1000, 1) * spec_quality
`, dbField), skuName.ID); err == nil && len(skuList) > 0 {
for _, sku := range skuList {
syncStatus := refutil.GetObjFieldByName(sku, syncStatusFieldName).(int8)
globals.SugarLogger.Debugf("SyncSku trackInfo2:%s, skuID:%d, syncStatus:%d", ctx.GetTrackInfo(), sku.ID, syncStatus)
if (len(skuIDs) == 0 || skuMap[sku.ID]) && (syncStatus != 0) {
updateFields := []string{syncStatusFieldName}
if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除
if syncStatus&model.SyncFlagNewMask == 0 {
err = multiStoresHandler.DeleteSku(db, sku, userName)
}
} else if syncStatus&model.SyncFlagNewMask != 0 { // 新增
if err = multiStoresHandler.CreateSku(db, sku, userName); err == nil {
var tmpStruct struct {
MaxIndex int
}
// todo hard code 得到京东spu中sku的顺序以方便以后修改销售属性这个必须要每次重新从数据库取
if dao.GetRow(db, &tmpStruct, "SELECT MAX(sku_index) max_index FROM sku WHERE name_id = ? AND jd_id > 0 AND jd_id < 4024012631406 ", sku.NameID) == nil {
sku.SkuIndex = tmpStruct.MaxIndex + 1
updateFields = append(updateFields, "SkuIndex")
}
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
}
} else if syncStatus&model.SyncFlagModifiedMask != 0 { // 修改
err = multiStoresHandler.UpdateSku(db, sku, userName)
}
if err == nil {
refutil.SetObjFieldByName(sku, syncStatusFieldName, int8(0))
if _, err = dao.UpdateEntity(db, sku, updateFields...); err != nil {
break
} else {
resultList = append(resultList, 1)
}
}
}
}
}
if err == nil {
refutil.SetObjFieldByName(skuName, syncStatusFieldName, int8(0))
_, err = dao.UpdateEntity(db, skuName, syncStatusFieldName)
}
return resultList, err
}, skuNameList)
t.AddChild(task).Run()
result, err2 := task.GetResult(0)
if err = err2; err == nil {
resultList = append(resultList, result...)
}
}
return resultList, err
})
}
// var skuNameList []*model.SkuName
// err := dao.GetRows(db, &skuNameList, sql, sqlParams...)
// if err == nil && len(skuNameList) > 0 {
// // todo 同一skuName下的sku顺序处理的原因是京东SPU特殊类型必须要序列化同步才能正常处理, db可能会有多线程问题
// task := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[vendorInfo.VendorID]), tasksch.NewParallelConfig().SetParallelCount(10).SetIsContinueWhenError(isContinueWhenError), ctx,
// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
// var resultList []interface{}
// skuName := batchItemList[0].(*model.SkuName)
// var skuList []*model.Sku
// if err = dao.GetRows(db, &skuList, fmt.Sprintf(`
// SELECT *
// FROM sku
// WHERE name_id = ? AND %s_sync_status <> 0
// ORDER BY IF(spec_unit IN('kg', 'L'), 1000, 1) * spec_quality
// `, dbField), skuName.ID); err == nil && len(skuList) > 0 {
// for _, sku := range skuList {
// syncStatus := refutil.GetObjFieldByName(sku, syncStatusFieldName).(int8)
// globals.SugarLogger.Debugf("SyncSku trackInfo2:%s, skuID:%d, syncStatus:%d", ctx.GetTrackInfo(), sku.ID, syncStatus)
// if (len(skuIDs) == 0 || skuMap[sku.ID]) && (syncStatus != 0) {
// updateFields := []string{syncStatusFieldName}
// if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除
// if syncStatus&model.SyncFlagNewMask == 0 {
// err = multiStoresHandler.DeleteSku(db, sku, userName)
// }
// } else if syncStatus&model.SyncFlagNewMask != 0 { // 新增
// if err = multiStoresHandler.CreateSku(db, sku, userName); err == nil {
// var tmpStruct struct {
// MaxIndex int
// }
// // todo hard code 得到京东spu中sku的顺序以方便以后修改销售属性这个必须要每次重新从数据库取
// if dao.GetRow(db, &tmpStruct, "SELECT MAX(sku_index) max_index FROM sku WHERE name_id = ? AND jd_id > 0 AND jd_id < 4024012631406 ", sku.NameID) == nil {
// sku.SkuIndex = tmpStruct.MaxIndex + 1
// updateFields = append(updateFields, "SkuIndex")
// }
// updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
// }
// } else if syncStatus&model.SyncFlagModifiedMask != 0 { // 修改
// err = multiStoresHandler.UpdateSku(db, sku, userName)
// }
// if err == nil {
// refutil.SetObjFieldByName(sku, syncStatusFieldName, int8(0))
// if _, err = dao.UpdateEntity(db, sku, updateFields...); err != nil {
// break
// } else {
// resultList = append(resultList, 1)
// }
// }
// }
// }
// }
// if err == nil {
// refutil.SetObjFieldByName(skuName, syncStatusFieldName, int8(0))
// _, err = dao.UpdateEntity(db, skuName, syncStatusFieldName)
// }
// return resultList, err
// }, skuNameList)
// t.AddChild(task).Run()
// result, err2 := task.GetResult(0)
// if err = err2; err == nil {
// resultList = append(resultList, result...)
// }
// }
// return resultList, err
// })
// }
func (v *VendorSync) SyncStoresCategory(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, storeIDs []int, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
globals.SugarLogger.Debug("SyncStoresCategory")
@@ -572,6 +571,29 @@ func (v *VendorSync) AddCreateFlagForJxStoreSku(ctx *jxcontext.Context, vendorID
return hint, makeSyncError(err)
}
func (v *VendorSync) AmendAndPruneStoreStuff(ctx *jxcontext.Context, vendorIDs []int, storeIDs []int, isAsync, isContinueWhenError bool, optType int, isForceUpdate bool) (hint string, err error) {
globals.SugarLogger.Debug("AmendAndPruneStoreStuff")
hint, err = v.LoopStoresMap(ctx, dao.GetDB(), fmt.Sprintf("处理京西平台商家分类与商品差异:%v", storeIDs), isAsync, true, vendorIDs, storeIDs,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
if len(loopMapInfo.StoreMapList) > 1 {
loopStoreTask := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]),
tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
storeMap := batchItemList[0].(*model.StoreMap)
_, err = amendAndPruneStoreStuff(ctx, task, loopMapInfo.VendorID, storeMap.StoreID, storeMap.VendorStoreID, false, isContinueWhenError, optType, isForceUpdate)
return nil, err
}, loopMapInfo.StoreMapList)
t.AddChild(loopStoreTask).Run()
_, err = loopStoreTask.GetResult(0)
} else {
_, err = amendAndPruneStoreStuff(ctx, t, loopMapInfo.VendorID, loopMapInfo.StoreMapList[0].StoreID, loopMapInfo.StoreMapList[0].VendorStoreID, false, isContinueWhenError, optType, isForceUpdate)
}
return nil, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
}, isContinueWhenError)
return hint, makeSyncError(err)
}
func (v *VendorSync) LoopStoresMap2(ctx *jxcontext.Context, db *dao.DaoDB, taskName string, isAsync, isManageIt bool, vendorIDs []int, storeIDs []int, handler tasksch.WorkFunc, isContinueWhenError bool) (task tasksch.ITask, hint string, err error) {
var storeMapList []*model.StoreMap
if storeMapList, err = dao.GetStoresMapList(db, vendorIDs, storeIDs, model.StoreStatusAll, model.StoreIsSyncYes, ""); err != nil {
@@ -722,7 +744,7 @@ func (v *VendorSync) ChangeStoreSkuSaleStatus(ctx *jxcontext.Context, storeID in
skuIDs = append(skuIDs, v.SkuID)
}
vendorIDs := partner.GetPurchasePlatformVendorIDs()
dao.UpdateStoreSkuBindSyncStatus(db, vendorIDs, storeID)
dao.UpdateStoreSkuBindSyncStatusForSaleStatus(db, vendorIDs, storeID)
v.SyncStoresSkus(ctx, db, vendorIDs, storeIDs, skuIDs, false, isAsync, isContinueWhenError)
return err
}

View File

@@ -42,7 +42,7 @@ func getMultiStoreVendorInfoList() (list []*MultiStoreVendorInfo) {
func syncCategories(ctx *jxcontext.Context, db *dao.DaoDB, parentTask tasksch.ITask, catList []*dao.SkuStoreCatInfo, isAsync bool) (hint string, err error) {
if len(catList) > 0 {
// todo 按vendorID orgCode合并操作
task := tasksch.NewParallelTask(fmt.Sprintf("同步分类2:%D", len(catList)), tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
task := tasksch.NewParallelTask(fmt.Sprintf("同步分类2:%d", len(catList)), tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
catVendorInfo := batchItemList[0].(*dao.SkuStoreCatInfo)
if catVendorInfo.Level != 1 && catVendorInfo.ParentVendorCatID == "" {
@@ -84,10 +84,11 @@ func syncCategories(ctx *jxcontext.Context, db *dao.DaoDB, parentTask tasksch.IT
}
func SyncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs []int, appOrgCodes []string, catIDs []int, isAsync bool) (hint string, err error) {
globals.SugarLogger.Debugf("SyncCategories catIDs:%v", catIDs)
globals.SugarLogger.Debugf("SyncCategories vendorIDs:%v, appOrgCodes:%v, catIDs:%v", vendorIDs, appOrgCodes, catIDs)
db := dao.GetDB()
catList, err := dao.GetSkuCategoryWithVendor(db, vendorIDs, appOrgCodes, -1, catIDs, true)
if err == nil && len(catList) > 0 {
// TODO 同一平台不同账号会有影响needSyncParentIDs暂不处理
var needSyncParentIDs []int
for _, cat := range catList {
if cat.Level == 2 && cat.ParentVendorCatID == "" {
@@ -128,7 +129,7 @@ func SyncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs
}
func SyncSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs []int, appOrgCodes []string, nameIDs, skuIDs []int, isAsync bool) (hint string, err error) {
globals.SugarLogger.Debugf("SyncSkus nameIDs:%v, skuIDs:%v", nameIDs, skuIDs)
globals.SugarLogger.Debugf("SyncSkus vendorIDs:%v, appOrgCodes:%v, nameIDs:%v, skuIDs:%v", vendorIDs, appOrgCodes, nameIDs, skuIDs)
db := dao.GetDB()
skuList, err := dao.GetSkusWithVendor(db, vendorIDs, appOrgCodes, nameIDs, skuIDs, true)
if err == nil && len(skuList) > 0 {
@@ -142,7 +143,7 @@ func SyncSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs []int,
if skuVendorInfo.BindID == 0 {
return nil, fmt.Errorf("商品:%d的数据异常", skuVendorInfo.SkuID)
}
skuVendorInfo.SkuName = jxutils.ComposeSkuName(skuVendorInfo.Prefix, skuVendorInfo.Name, skuVendorInfo.Comment, skuVendorInfo.Unit, skuVendorInfo.SpecQuality, skuVendorInfo.SpecUnit, 0)
skuVendorInfo.SkuName = jxutils.ComposeSkuName(skuVendorInfo.Prefix, skuVendorInfo.Name, skuVendorInfo.Comment, skuVendorInfo.Unit, skuVendorInfo.SpecQuality, skuVendorInfo.SpecUnit, 0, skuVendorInfo.ExPrefix, skuVendorInfo.ExPrefixBegin, skuVendorInfo.ExPrefixEnd)
skuVendorInfo.MergedStatus = jxutils.MergeSkuStatus(skuVendorInfo.Status, skuVendorInfo.NameStatus)
if multiStoresHandler, ok := partner.GetPurchasePlatformFromVendorID(skuVendorInfo.VendorID).(partner.IMultipleStoresHandler); ok {
if model.IsSyncStatusDelete(skuVendorInfo.SkuSyncStatus) { //删除

View File

@@ -228,13 +228,16 @@ func calVendorPrice4StoreSku(inSku *dao.StoreSkuSyncInfo, pricePercentagePack mo
func formalizeStoreSkuList(inSkuList []*dao.StoreSkuSyncInfo) []*dao.StoreSkuSyncInfo {
for _, skuItem := range inSkuList {
skuItem.MergedStatus = jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus)
skuItem.SkuName = jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0)
skuItem.SkuName = jxutils.ComposeSkuNameSync(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0, skuItem.ExPrefix, skuItem.ExPrefixBegin, skuItem.ExPrefixEnd)
}
return inSkuList
}
func sku2Update(vendorID int, sku *dao.StoreSkuSyncInfo, syncStatus int8) (item *dao.KVUpdateItem) {
kvs := map[string]interface{}{}
if !isSkuLockTimeValid(sku) {
kvs[dao.GetVendorLockTimeStructField(model.VendorNames[vendorID])] = nil
}
if syncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 {
if model.IsSyncStatusNew(syncStatus) {
sku.SkuSyncStatus = 0
@@ -289,6 +292,10 @@ func updateStoreSku(db *dao.DaoDB, vendorID int, storeSkuList []*dao.StoreSkuSyn
return num, err
}
func isSkuLockTimeValid(sku *dao.StoreSkuSyncInfo) bool {
return sku.LockTime != nil && time.Now().Sub(*sku.LockTime) < 0
}
func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bool, vendorID, storeID int, nameIDs, skuIDs, excludeSkuIDs []int, useVendorPriceDirectly, isContinueWhenError bool) (err error) {
db := dao.GetDB()
storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID)
@@ -334,7 +341,8 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
}
now := jxutils.OperationTime2HourMinuteFormat(time.Now())
for _, sku := range skus {
if !useVendorPriceDirectly {
if !useVendorPriceDirectly &&
!isSkuLockTimeValid(sku) {
sku.VendorPrice = 0
}
sku.MergedStatus = MergeSkuSaleStatusWithStoreOpTime(sku, storeDetail, now)
@@ -354,14 +362,18 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo
} else if model.IsSyncStatusNew(sku.SkuSyncStatus) {
calVendorPrice4StoreSku(sku, storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage))
if singleStoreHandler == nil {
sku.SkuSyncStatus |= model.SyncFlagSaleMask | model.SyncFlagPriceMask
bareSku = storeSkuSyncInfo2Bare(sku)
stockList = append(stockList, bareSku)
priceList = append(priceList, bareSku)
if sku.MergedStatus == model.SkuStatusNormal {
onlineList = append(onlineList, bareSku)
if dao.IsVendorThingIDEmpty(sku.VendorSkuID) {
// todo 多平台商品库没有正常创建,直接跳过
} else {
offlineList = append(offlineList, bareSku)
sku.SkuSyncStatus |= model.SyncFlagSaleMask | model.SyncFlagPriceMask
bareSku = storeSkuSyncInfo2Bare(sku)
stockList = append(stockList, bareSku)
priceList = append(priceList, bareSku)
if sku.MergedStatus == model.SkuStatusNormal {
onlineList = append(onlineList, bareSku)
} else {
offlineList = append(offlineList, bareSku)
}
}
} else {
if sku.MergedStatus == model.SkuStatusNormal {
@@ -703,11 +715,13 @@ func amendAndPruneStoreStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, v
if (opType == AmendPruneOnlyPrune || opType == AmendPruneAll) && len(sku2Delete) > 0 {
_, err = putils.FreeBatchStoreSkuInfo("删除门店商品", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) {
if _, err = handler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err != nil {
// 如果删除失败尝试设置不可售假定删除批处理SIZE小于等于设置门店商品可售批处理SIZE
handler.UpdateStoreSkusStatus(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList, model.SkuStatusDontSale)
if batchedStoreSkuList[0].Status == model.SkuStatusNormal {
// 如果删除失败尝试设置不可售假定删除批处理SIZE小于等于设置门店商品可售批处理SIZE
handler.UpdateStoreSkusStatus(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList, model.SkuStatusDontSale)
}
}
return nil, 0, err
}, ctx, task, sku2Delete, handler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus), isContinueWhenError)
}, ctx, task, sku2Delete, 1 /*handler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus)*/, isContinueWhenError)
}
sku2Delete = nil
case 2:

View File

@@ -33,7 +33,7 @@ func TestFreeBatchStoreSkuInfo(t *testing.T) {
}
func TestGetTimeMixByInt(t *testing.T) {
var (
const (
time1 = 1100
time2 = 2300
time3 = 1200

View File

@@ -9,6 +9,7 @@ import (
"git.rosy.net.cn/jx-callback/business/jxstore/report"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/baseapi/utils/errlist"
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch"
"git.rosy.net.cn/jx-callback/business/jxstore/act"
@@ -34,8 +35,11 @@ var (
dailyWorkTimeList = []string{
"20:30:00",
}
priceReferTimeList = []string{
"01:00:00",
}
createStorePriceTimeList = []string{
"23:00:00",
"02:00:00",
}
refreshPageActTimeList = []string{
"7:00:00",
@@ -113,7 +117,7 @@ func Init() {
}, 5*time.Second, 1*time.Hour)
ScheduleTimerFuncByInterval(func() {
defsch.FixedScheduler.ConfirmSelfTakeOrders(jxcontext.AdminCtx, nil, time.Now().Add(-48*time.Hour), time.Now().Add(-30*time.Minute), true, true)
defsch.FixedScheduler.ConfirmSelfTakeOrders(jxcontext.AdminCtx, []int{model.VendorIDJD}, time.Now().Add(-48*time.Hour), time.Now().Add(-30*time.Minute), true, true)
}, 5*time.Second, 10*time.Minute)
ScheduleTimerFunc("auto enable remote store", func() {
@@ -129,7 +133,7 @@ func Init() {
act.RefreshPageActs(jxcontext.AdminCtx, []int{model.VendorIDEBAI}, time.Now().Add(-30*24*time.Hour), false)
}, refreshPageActTimeList)
ScheduleTimerFunc("UpdateActStatusByTime", func() {
dao.UpdateActStatusByTime(dao.GetDB(), time.Now().Add(-48*time.Hour))
dao.UpdateActStatusByTime(dao.GetDB(), time.Now())
}, updateActStatusTimeList)
ScheduleScoreStore()
ScheduleCheckStoreAlert()
@@ -138,10 +142,10 @@ func Init() {
}, ChangeStoreSkuSaleStatusList)
ScheduleTimerFunc("BeginSavePriceRefer", func() {
report.BeginSavePriceRefer(jxcontext.AdminCtx, nil, nil)
}, createStorePriceTimeList)
}, priceReferTimeList)
ScheduleTimerFunc("CreateStorePriceScore", func() {
cms.CreateStorePriceScore(jxcontext.AdminCtx, false)
}, openRemoteStoreTimeList)
cms.CreateStorePriceScore(jxcontext.AdminCtx)
}, createStorePriceTimeList)
}
ScheduleTimerFunc("AutoSaleStoreSku", func() {
cms.AutoSaleStoreSku(jxcontext.AdminCtx, nil, false)
@@ -156,20 +160,55 @@ func Init() {
}
}
func doDailyWork() {
globals.SugarLogger.Debug("doDailyWork")
cms.SyncStoresCourierInfo(jxcontext.AdminCtx, nil, false, true)
netprinter.RebindAllPrinters(jxcontext.AdminCtx, false, true)
func syncStoreSku() {
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)
cms.CurVendorSync.FullSyncStoresSkus(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDJD}, nil, false, []int{27379}, true, true)
task := tasksch.NewParallelTask("同步京西与平台数据", nil, jxcontext.AdminCtx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
step := batchItemList[0].(int)
errList := errlist.New()
db := dao.GetDB()
switch step {
case 0:
errList.AddErr(cms.DeleteSkuNameExPrefixOverdue(db))
errList.AddErr(cms.SetMultiStoreSkuSyncModifyStatus(db, partner.GetMultiStoreVendorIDs()))
SaveImportantTaskID(TaskNameSyncStoreSku, SpecialTaskID)
taskID, _ := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDEBAI, model.VendorIDMTWM}, nil, false, nil, nil, syncFlag, true, true)
SaveImportantTaskID(TaskNameSyncStoreSku, taskID)
_, err = cms.CurVendorSync.LoopMultiStoresVendors(jxcontext.AdminCtx, db, "同步多门店平台商品库", false, true,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
vendorInfo := batchItemList[0].(*cms.MultiStoreVendorInfo)
_, err = cms.FullSyncVendorStuff(jxcontext.AdminCtx, task, vendorInfo.VendorID, vendorInfo.OrgCode, false, true)
return retVal, err
})
errList.AddErr(err)
// cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, db, partner.GetMultiStoreVendorIDs(), nil, false, nil, []int{27379}, syncFlag, true, true)
_, err = cms.CurVendorSync.FullSyncStoresSkus(jxcontext.AdminCtx, db, partner.GetMultiStoreVendorIDs(), nil, false, []int{27379}, true, true)
errList.AddErr(err)
case 1:
errList.AddErr(cms.SetSingleStoreSkuSyncModifyStatus(db, partner.GetSingleStoreVendorIDs()))
_, err = cms.CurVendorSync.AmendAndPruneStoreStuff(jxcontext.AdminCtx, partner.GetSingleStoreVendorIDs(), nil, false, true, cms.AmendPruneAll, false)
errList.AddErr(err)
SaveImportantTaskID(TaskNameSyncStoreSku, SpecialTaskID)
taskID, err2 := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, db, partner.GetSingleStoreVendorIDs(), nil, false, nil, nil, syncFlag, true, true)
errList.AddErr(err2)
SaveImportantTaskID(TaskNameSyncStoreSku, taskID)
}
err = errList.GetErrListAsOne()
return retVal, err
}, []int{0, 1})
tasksch.HandleTask(task, nil, true).Run()
}
func doDailyWork() {
globals.SugarLogger.Debug("doDailyWork")
cms.SyncStoresCourierInfo(jxcontext.AdminCtx, nil, false, true)
netprinter.RebindAllPrinters(jxcontext.AdminCtx, false, true)
syncStoreSku()
InitEx()
@@ -180,6 +219,8 @@ func doDailyWork() {
//fromDate, toDate都不传默认刷新当前天5天以前的订单只传fromDate默认刷新fromDate到当天的订单
//只传toDate默认刷新toDate到5天以前的订单
orderman.RefreshOrdersWithoutJxStoreID(jxcontext.AdminCtx, "", "", true, true)
//刷新京东门店的等级
cms.RefreshJdLevel(jxcontext.AdminCtx)
}
func RefreshRealMobile(ctx *jxcontext.Context, vendorID int, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) {

View File

@@ -396,7 +396,7 @@ func ScorePromotionSku(storeInfo *cms.StoreExt) {
db := dao.GetDB()
beginTime := time.Now()
endTime := time.Now()
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, -1, nil, []int{storeID}, nil, beginTime, endTime)
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, -1, nil, model.ActTypeAll, []int{storeID}, nil, beginTime, endTime)
finalScore := 0
if err == nil && len(actStoreSkuList) > 0 {
actStoreSkuMap := make(map[int]int)

View File

@@ -149,7 +149,7 @@ func GetStoreSkuSalesInfo(ctx *jxcontext.Context, storeID int) (outStoreSkuSales
if storeSkuInfo != nil {
skuName := storeSkuInfo.SkuName
skuInfo := storeSkuInfo.Skus[0]
storeSkuSales.SkuName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, skuInfo.Comment, skuName.Unit, skuInfo.SkuSpecQuality, skuInfo.SkuSpecUnit, 0)
storeSkuSales.SkuName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, skuInfo.Comment, skuName.Unit, skuInfo.SkuSpecQuality, skuInfo.SkuSpecUnit, 0,skuName.ExPrefix,skuName.ExPrefixBegin,skuName.ExPrefixEnd)
storeSkuSales.SkuImage = storeSkuInfo.Img
storeSkuSales.SkuPrice = jxutils.IntPrice2StandardCurrencyString(int64(storeSkuInfo.Skus[0].BindPrice))
} else if skuAndNameInfo != nil {
@@ -159,7 +159,7 @@ func GetStoreSkuSalesInfo(ctx *jxcontext.Context, storeID int) (outStoreSkuSales
storeSkuSales.SkuImage = skuNameList[0].Img
prefix = skuNameList[0].Prefix
}
storeSkuSales.SkuName = jxutils.ComposeSkuName(prefix, skuAndNameInfo.Name, skuAndNameInfo.Comment, skuAndNameInfo.Unit, skuAndNameInfo.SpecQuality, skuAndNameInfo.SpecUnit, 0)
storeSkuSales.SkuName = jxutils.ComposeSkuName(prefix, skuAndNameInfo.Name, skuAndNameInfo.Comment, skuAndNameInfo.Unit, skuAndNameInfo.SpecQuality, skuAndNameInfo.SpecUnit, 0,skuAndNameInfo.ExPrefix,skuAndNameInfo.ExPrefixBegin,skuAndNameInfo.ExPrefixEnd)
storeSkuSales.SkuPrice = "N/A"
} else {
storeSkuSales.SkuName = "N/A"

View File

@@ -6,6 +6,8 @@ import (
"math"
"time"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
@@ -52,7 +54,7 @@ func StatisticsReportForStoreSkusPrice(ctx *jxcontext.Context, cityCodes, skuIDs
func BeginSavePriceRefer(ctx *jxcontext.Context, cityCodes, skuIDs []int) (err error) {
db := dao.GetDB()
snapshotAt := utils.Time2Date(time.Now())
snapshotAt := utils.Time2Date(time.Now().AddDate(0, 0, -1))
priceReferSnapshot, err := dao.GetStatisticsReportForStoreSkusPrice(db, cityCodes, skuIDs)
if len(priceReferSnapshot) > 0 {
dao.Begin(db)
@@ -71,12 +73,12 @@ func BeginSavePriceRefer(ctx *jxcontext.Context, cityCodes, skuIDs []int) (err e
for _, v := range priceReferSnapshot {
dao.WrapAddIDCULDEntity(v, ctx.GetUserName())
v.SnapshotAt = snapshotAt
fmt.Println(v)
if err = dao.CreateEntity(db, v); err != nil {
return err
}
}
dao.Commit(db)
globals.SugarLogger.Debugf("CreatePriceRefer")
}
return err
}

View File

@@ -1451,7 +1451,7 @@ func BuildSkuFromEbaiStore(ctx *jxcontext.Context, baiduShopID int64, isAsync, i
}
price := sku.LinkID
sku.LinkID = 0
skuName := jxutils.ComposeSkuName(skuNameExt.Prefix, skuNameExt.Name, sku.Comment, skuNameExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount)
skuName := jxutils.ComposeSkuNameOriginal(skuNameExt.Prefix, skuNameExt.Name, sku.Comment, skuNameExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount)
fixedStatus := 1
if sku.Status != model.SkuStatusNormal {
fixedStatus = 2

View File

@@ -327,7 +327,7 @@ func FloatWeight2Int(weight float32) int {
return int(math.Round(float64(weight * 1000)))
}
func ComposeSkuName(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int) (skuName string) {
func ComposeSkuNameOriginal(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int) (skuName string) {
if prefix != "" {
skuName = "[" + prefix + "]"
}
@@ -348,6 +348,29 @@ func ComposeSkuName(prefix, name, comment, unit string, spec_quality float32, sp
return skuName
}
func ComposeSkuName(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) {
if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil {
if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 {
skuName = exPrefix
}
}
skuName += ComposeSkuNameOriginal(prefix, name, comment, unit, spec_quality, spec_unit, maxLen)
return skuName
}
func ComposeSkuNameSync(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) {
if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil {
if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 {
skuName = exPrefix
}
if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 {
skuName = ""
}
}
skuName += ComposeSkuNameOriginal(prefix, name, comment, unit, spec_quality, spec_unit, maxLen)
return skuName
}
func ComposeSpuName(prefix, name string, maxLen int) (spuName string) {
if prefix != "" {
spuName = "[" + prefix + "]"
@@ -409,6 +432,31 @@ func SplitSkuName(skuName string) (prefix, name, comment, specUnit, unit string,
return prefix, name, comment, specUnit, unit, specQuality
}
// https://my.oschina.net/hyller/blog/700414
func CalUpcCheckSum(upc12 int64) (checkSum int) {
var sum [2]int
for i := 0; i < 12; i++ {
base := int64(math.Pow10(i))
sum[i%2] += int((upc12 / base) % 10)
}
sum[0] *= 3
return (10 - (sum[0]+sum[1])%10) % 10
}
func IsUpcValid(upc string) bool {
if len(upc) != 13 {
return false
}
upcInt := utils.Str2Int64WithDefault(upc, 0)
checkSum := CalUpcCheckSum(upcInt / 10)
return int(utils.Str2Int64(upc[12:])) == checkSum
}
func GenFakeUPC(skuID int) string {
id := int64(skuID) + 666600000000
return fmt.Sprintf("%012d%d", id, CalUpcCheckSum(id))
}
func MakeValidationMapFromSlice(validValues []string, flag int) map[string]int {
retVal := make(map[string]int)
for _, v := range validValues {

View File

@@ -8,6 +8,7 @@ type ActStoreSkuMap struct {
actStoreSkuMap map[int64]map[int]*model.ActStoreSku2
}
// isActPrice为true表示是活动false表示是结算
func NewActStoreSkuMap(actStoreSkuList []*model.ActStoreSku2, isActPrice bool) (actMap *ActStoreSkuMap) {
actMap = &ActStoreSkuMap{}
actStoreSkuMap := make(map[int64]map[int]*model.ActStoreSku2)

View File

@@ -2,18 +2,14 @@ package jxutils
import (
"testing"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
)
func TestGetActStoreSku(t *testing.T) {
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(dao.GetDB(), 0, []int{model.VendorIDMTWM}, []int{102046}, []int{25430, 30611},
utils.Str2Time("2019-07-27 13:29:57"), utils.Str2Time("2019-07-27 13:29:57"))
if err != nil {
t.Fatal(err)
}
storeSkuMap := jxutils.NewActStoreSkuMap(actStoreSkuList, false)
t.Log(storeSkuMap.GetActStoreSku(1, 2, 3))
// actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(dao.GetDB(), 0, []int{model.VendorIDMTWM}, []int{102046}, []int{25430, 30611},
// utils.Str2Time("2019-07-27 13:29:57"), utils.Str2Time("2019-07-27 13:29:57"))
// if err != nil {
// t.Fatal(err)
// }
// storeSkuMap := jxutils.NewActStoreSkuMap(actStoreSkuList, false)
// t.Log(storeSkuMap.GetActStoreSku(1, 2, 3))
}

View File

@@ -2,12 +2,10 @@ package jxutils
import (
"fmt"
"strings"
"testing"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
)
func TestSplitSlice(t *testing.T) {
@@ -109,22 +107,22 @@ func TestCalcPolygonAreaAutonavi(t *testing.T) {
// pointers := GetPolygonFromCircle(104.065702, 30.657488, 3000, 128)
// area := CalcPolygonAreaAutonavi(pointers)
// t.Logf("area:%f", area)
db := dao.GetDB()
storeList, err := dao.GetStoreList(db, nil, nil, "")
if err != nil {
t.Fatal(err)
}
// db := dao.GetDB()
// storeList, err := dao.GetStoreList(db, nil, nil, "")
// if err != nil {
// t.Fatal(err)
// }
strBuilder := &strings.Builder{}
strBuilder.WriteString("\n")
for _, v := range storeList {
if v.DeliveryRangeType == model.DeliveryRangeTypePolygon {
pointers := CoordinateStr2Points(v.DeliveryRange)
area1 := CalcPolygonAreaAutonavi(pointers)
strBuilder.WriteString(fmt.Sprintf("%d,%f\n", v.ID, area1))
}
}
t.Log(strBuilder.String())
// strBuilder := &strings.Builder{}
// strBuilder.WriteString("\n")
// for _, v := range storeList {
// if v.DeliveryRangeType == model.DeliveryRangeTypePolygon {
// pointers := CoordinateStr2Points(v.DeliveryRange)
// area1 := CalcPolygonAreaAutonavi(pointers)
// strBuilder.WriteString(fmt.Sprintf("%d,%f\n", v.ID, area1))
// }
// }
// t.Log(strBuilder.String())
}
func TestCaculateSkuPrice(t *testing.T) {

View File

@@ -284,3 +284,26 @@ func TestGetOneEmailFromStr(t *testing.T) {
}
}
}
func TestGenFakeUPC(t *testing.T) {
for _, v := range [][]string{
[]string{
"6666000298034",
"29803",
},
[]string{
"6666076543212",
"7654321",
},
} {
if str := GenFakeUPC(int(utils.Str2Int64(v[1]))); str != v[0] {
t.Errorf("%s failed, result:%s, expect:%s", v[1], str, v[0])
}
}
if !IsUpcValid("6666076543212") {
t.Fatal("wrong1")
}
if IsUpcValid("6666076543210") {
t.Fatal("wrong2")
}
}

View File

@@ -418,12 +418,6 @@ func (t *BaseTask) MarshalJSON() ([]byte, error) {
func (t *BaseTask) run(taskHandler func()) {
if t.GetStatus() == TaskStatusBegin {
utils.CallFuncAsync(func() {
defer func() {
if r := recover(); r != nil {
globals.SugarLogger.Errorf("panic in BaseTask.run task:%s, task detail:%s, r:%v", t.Name, utils.Format4Output(t, false), r)
}
}()
taskHandler()
task := t

View File

@@ -197,7 +197,7 @@ func getOrderDetailBrief(order *model.GoodsOrder) (brief string) {
sb.WriteString(utils.Int2Str(order.Skus[0].Count))
sb.WriteString("份(")
sb.WriteString(jxutils.IntPrice2StandardString(order.Skus[0].SalePrice))
sb.WriteString("元/份)等,共支付了")
sb.WriteString("元/份)等,预计收入")
sb.WriteString(jxutils.IntPrice2StandardString(order.ActualPayPrice))
sb.WriteString("元")
return sb.String()

View File

@@ -7,6 +7,7 @@ import (
)
const (
ActTypeAll = -1
ActSkuFake = 0 // 假活动,只用于存储活动结算信息
ActSkuDirectDown = 3 // 兼容之前的
ActSkuSecKill = 4 // 兼容之前的
@@ -198,10 +199,13 @@ type ActStoreSku2 struct {
SkuName string `json:"skuName"`
Prefix string `json:"-"`
SkuNameName string `orm:"column(sku_name_name)" json:"-"`
Unit string `orm:"size(8)" json:"-"`
SpecQuality float32 `json:"-"`
SpecUnit string `json:"-"`
Comment string `json:"-"`
Prefix string `json:"-"`
ExPrefix string
ExPrefixBegin *time.Time
ExPrefixEnd *time.Time
SkuNameName string `orm:"column(sku_name_name)" json:"-"`
Unit string `orm:"size(8)" json:"-"`
SpecQuality float32 `json:"-"`
SpecUnit string `json:"-"`
Comment string `json:"-"`
}

View File

@@ -45,10 +45,10 @@ type GoodsOrderExt struct {
type OrderSkuExt struct {
OrderSku
NameID int `orm:"column(name_id)" json:"nameID"`
FullSkuName string `json:"fullSkuName"`
Image string `json:"image"`
RealEarningPrice int64 `json:"realEarningPrice"` // 实际单品结算给门店老板钱
NameID int `orm:"column(name_id)" json:"nameID"`
FullSkuName string `json:"fullSkuName"`
Image string `json:"image"`
// RealEarningPrice int64 `json:"realEarningPrice"` // 实际单品结算给门店老板钱
}
type GoodsOrderCountInfo struct {
@@ -83,3 +83,20 @@ type OrderFinancialSkuExt struct {
OrderSkuFinancial
Image string `json:"image"`
}
type ProductInfo struct {
OriginalName string `json:"originalName"`
OriginalSpec string `json:"originalSpec"`
Name string `json:"name"`
Img string `json:"img"`
ImgList []string `json:"imgList"`
SpecQuality int `json:"specQuality"`
SpecUnit string `json:"specUnit"`
Unit string `json:"unit"`
Weight float32 `json:"weight"`
Price int `json:"price"`
Categories []string `json:"categories"`
ManName string `json:"manName"` // 生产商
BrandName string `json:"brandName"`
UpcCode string `json:"upcCode"`
}

View File

@@ -18,6 +18,8 @@ const (
VendorIDPurchaseEnd = 11
VendorIDJX = 9 // 这是一个假的京西VendorID
VendorIDWXPay = 51 // 微信支付
VendorIDDeliveryBegin = 101
VendorIDDada = 101
VendorIDMTPS = 102

View File

@@ -33,9 +33,9 @@ var (
OrderStatusName = map[int]string{
OrderStatusMsg: "通知消息",
OrderStatusWaybillTipChanged: "小费变动",
OrderStatusRefuseFailedGetGoods: "取货失败审核驳回",
OrderStatusAdjust: "订单调整完成",
OrderStatusWait4Pay: "待付款",
OrderStatusApplyUrgeOrder: "催单",
OrderStatusUnlocked: "解锁",
@@ -46,7 +46,7 @@ var (
OrderStatusUnknown: "一般事件",
OrderStatusCreated: "待付",
OrderStatusWait4Pay: "待付",
OrderStatusNew: "新订单",
OrderStatusAccepted: "待拣货",
OrderStatusFinishedPickup: "待配送",
@@ -86,6 +86,18 @@ var (
OrderTypeAfsOrder: "售后单",
}
ComplaintReasons = map[int]string{
ComplaintReasons1: "骑手态度恶劣",
ComplaintReasons2: "骑手接单后未取货",
ComplaintReasons3: "骑手取货太慢",
ComplaintReasons4: "骑手送货太慢",
ComplaintReasons5: "货品未送达",
ComplaintReasons6: "货品有损坏",
ComplaintReasons7: "骑手违规收取顾客其他费用",
ComplaintReasons69: "骑手恶意取消订单",
ComplaintReasons71: "骑手提前点击取货/送达",
}
MultiStoresVendorMap = map[int]int{
VendorIDJD: 1,
VendorIDMTWM: 0,
@@ -161,19 +173,21 @@ const (
const (
OrderStatusMsg = -100
OrderStatusWaybillTipChanged = -80 // 订单小费变化
OrderStatusRefuseFailedGetGoods = -70 // 取货失败审核驳回
OrderStatusAdjust = -65 // 原值-35 订单调整完成
OrderStatusWait4Pay = -60 // 原值-30 下单待支付,微盟在这个时间发新订单事件
OrderStatusApplyUrgeOrder = -55 // 原值-15
OrderStatusUnlocked = -25
OrderStatusLocked = -20
// OrderStatusApplyRefund = -10
OrderStatusUndoApplyCancel = -10
OrderStatusApplyCancel = -5
OrderStatusUnlocked = -25
OrderStatusLocked = -20
OrderStatusUndoApplyCancel = -10
OrderStatusVendorRejectCancel = -7
OrderStatusVendorAgreeCancel = -6
OrderStatusApplyCancel = -5
OrderStatusUnknown = 0
OrderStatusCreated = 2 // 支付
OrderStatusWait4Pay = 2 // 原值-60 下单待支付
OrderStatusNew = 5 // 新订单,实际是已经支付
OrderStatusAccepted = 10 // 已经接单,也即待出库,待拣货
OrderStatusFinishedPickup = 15 // 拣货完成
@@ -202,6 +216,19 @@ const (
LockStatusLocked = 1
)
//投诉原因
const (
ComplaintReasons1 = 1 //"骑手态度恶劣",
ComplaintReasons2 = 2 //"骑手接单后未取货"
ComplaintReasons3 = 3 //"骑手取货太慢",
ComplaintReasons4 = 4 //"骑手送货太慢",
ComplaintReasons5 = 5 //"货品未送达",
ComplaintReasons6 = 6 //"货品有损坏",
ComplaintReasons7 = 7 //"骑手违规收取顾客其他费用",
ComplaintReasons69 = 69 //"骑手恶意取消订单",
ComplaintReasons71 = 71 //"骑手提前点击取货/送达",
)
const (
WaybillStatusRefuseFailedGetGoods = -70
WaybillStatusUnknown = 0
@@ -222,6 +249,7 @@ const (
WaybillStatusDelivered = 105 // todo 这个应该改为110与订单对应
WaybillStatusCanceled = 115
WaybillStatusFailed = 120 // 这个状态存在的意义是区分于WaybillStatusCanceled比如达达平台在这种状态下再次创建运单的方式不一样
WaybillStatusEndEnd = 120
)
const (
@@ -336,7 +364,7 @@ func IsOrderLockStatus(status int) bool {
}
func IsOrderUnlockStatus(status int) bool {
return status == OrderStatusUnlocked || status == OrderStatusUndoApplyCancel
return status == OrderStatusUnlocked || status == OrderStatusUndoApplyCancel || status == OrderStatusVendorAgreeCancel || status == OrderStatusVendorRejectCancel
}
func IsOrderMainStatus(status int) bool {
@@ -367,3 +395,7 @@ func WaybillVendorID2Mask(vendorID int) (mask int8) {
func IsAfsOrderFinalStatus(status int) bool {
return status >= AfsOrderStatusFinished && status <= AfsOrderStatusFailed
}
func IsWaybillFinalStatus(status int) bool {
return status >= WaybillStatusEndBegin && status <= WaybillStatusEndEnd
}

View File

@@ -101,7 +101,7 @@ func GetActStoreSkuVendorList(db *DaoDB, actID int, vendorIDs, storeIDs, skuIDs
END vendor_sku_id,
t4.comment, t4.spec_quality, t4.spec_unit,
t6.name store_name,
t7.name sku_name_name, t7.unit, t7.prefix
t7.name sku_name_name, t7.unit, t7.prefix, t7.ex_prefix, t7.ex_prefix_begin, t7.ex_prefix_end
FROM act_store_sku t1
%s JOIN act_store_sku_map t2 ON t2.act_id = ? AND t2.bind_id = t1.id AND t2.deleted_at = ?`, jdVendorIDField, leftOrEmpty)
sqlParams := []interface{}{
@@ -204,25 +204,25 @@ func QueryActs(db *DaoDB, actID int, offset, pageSize int, syncStatus int, keywo
SELECT
t1.*,
t2.id map_id, t2.vendor_id, t2.vendor_act_id, t2.sync_status, t2.remark map_remark
FROM act t1
LEFT JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ?`
sqlParams = []interface{}{utils.DefaultTimeValue}
if syncStatus >= 0 {
sql += " AND (t2.sync_status = ? OR t2.sync_status & ? <> 0)"
sqlParams = append(sqlParams, syncStatus, syncStatus)
}
} else if syncStatus >= 0 {
sql += " JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ? AND (t2.sync_status = ? OR t2.sync_status & ? <> 0)"
sqlParams = append(sqlParams, utils.DefaultTimeValue, syncStatus, syncStatus)
FROM act t1`
}
sql += " LEFT JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ?"
sqlParams = append(sqlParams, utils.DefaultTimeValue)
if syncStatus >= 0 {
sql += " AND (t2.sync_status = ? OR t2.sync_status & ? <> 0)"
sqlParams = append(sqlParams, syncStatus, syncStatus)
}
sql += `
WHERE t1.deleted_at = ?`
if syncStatus >= 0 {
sql += " AND t2.id IS NOT NULL"
}
sqlParams = append(sqlParams, utils.DefaultTimeValue)
keywordInt := int64(0)
if keyword != "" {
keywordLike := "%" + keyword + "%"
sql += " AND ( t1.name LIKE ? OR t1.advertising LIKE ? OR t1.remark LIKE ?"
sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike)
sql += " AND ( t1.name LIKE ? OR t1.advertising LIKE ? OR t1.remark LIKE ? OR t2.vendor_act_id LIKE ?"
sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike)
keywordInt = utils.Str2Int64WithDefault(keyword, 0)
if keywordInt > 0 {
sql += `
@@ -321,9 +321,12 @@ func QueryActs(db *DaoDB, actID int, offset, pageSize int, syncStatus int, keywo
t2.id map_id, t2.vendor_id, t2.vendor_org_code, t2.vendor_act_id, t2.sync_status, t2.remark map_remark
FROM act t1
LEFT JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ?
WHERE t1.id IN (` + GenQuestionMarks(len(idList)) + `)
ORDER BY t1.id DESC, t2.vendor_id
`
WHERE t1.id IN (` + GenQuestionMarks(len(idList)) + `)`
if syncStatus >= 0 {
sql += " AND t2.id IS NOT NULL"
}
sql += `
ORDER BY t1.id DESC, t2.vendor_id`
sqlParams = []interface{}{
utils.DefaultTimeValue,
idList,
@@ -369,7 +372,7 @@ func GetExistVendorActIDs(db *DaoDB, vendorID int) (vendorActIDs []string, err e
return vendorActIDs, err
}
func GetEffectiveActStoreSkuInfo(db *DaoDB, actID int, vendorIDs []int, storeIDs, skuIDs []int, beginAt, endAt time.Time) (actStoreSkuList []*model.ActStoreSku2, err error) {
func GetEffectiveActStoreSkuInfo(db *DaoDB, actID int, vendorIDs []int, actType int, storeIDs, skuIDs []int, beginAt, endAt time.Time) (actStoreSkuList []*model.ActStoreSku2, err error) {
if utils.IsTimeZero(beginAt) {
return nil, fmt.Errorf("GeActStoreSkuInfo必须指定活动开始时间")
}
@@ -406,9 +409,13 @@ func GetEffectiveActStoreSkuInfo(db *DaoDB, actID int, vendorIDs []int, storeIDs
sqlParams = append(sqlParams, model.GetVendorMask(vendorIDs...), vendorIDs)
}
if actID > 0 {
sql = " AND t1.id = ?"
sql += " AND t1.id = ?"
sqlParams = append(sqlParams, actID)
}
if actType != model.ActTypeAll {
sql += " AND t1.type = ?"
sqlParams = append(sqlParams, actType)
}
if len(storeIDs) > 0 {
sql += " AND t2.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
sqlParams = append(sqlParams, storeIDs)
@@ -432,7 +439,7 @@ func UpdateActStatusByTime(db *DaoDB, refTime time.Time) (num int64, err error)
model.ActStatusEnded,
utils.DefaultTimeValue,
model.ActStatusCanceled,
refTime,
utils.Time2Date(refTime),
}
num, err = ExecuteSQL(db, sql, sqlParams...)
return num, err

View File

@@ -5,6 +5,7 @@ import (
"time"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
)
func TestGetEffectiveActStoreSkuInfo(t *testing.T) {
@@ -27,7 +28,7 @@ func TestGetEffectiveActStoreSkuInfo(t *testing.T) {
ToTime: utils.Str2Time("2019-08-06 12:34:56"),
},
} {
result, err := GetEffectiveActStoreSkuInfo(GetDB(), v.ActID, v.VendorIDs, v.StoreIDs, v.SkuIDs, v.FromTime, v.ToTime)
result, err := GetEffectiveActStoreSkuInfo(GetDB(), v.ActID, v.VendorIDs, model.ActTypeAll, v.StoreIDs, v.SkuIDs, v.FromTime, v.ToTime)
if err != nil {
t.Fatal(err)
}

View File

@@ -734,7 +734,7 @@ func GetOrders(db *DaoDB, ids []int64, isIncludeSku, isIncludeFake bool, fromDat
IF(t3.jx_sku_id > 0, t3.jx_sku_id, t3.sku_id) sku_id,
t3.count sku_count2,
t3.shop_price sku_shop_price,
t3.earning_price sku_earning_price,
IF(t3.store_sub_id = 0, 0, t3.earning_price) sku_earning_price,
t3.sale_price sku_sale_price,
t3.sku_name`
}
@@ -1015,3 +1015,88 @@ func GetPendingFakeOrders(db *DaoDB, vendorIDs []int, orderCreatedAfter, orderCr
err = GetRows(db, &orderList, sql, sqlParams...)
return orderList, err
}
// 不会有Skus信息
func LoadPendingOrders(db *DaoDB, orderCreatedAfter time.Time, beforStatus int) (orderList []*model.GoodsOrder, err error) {
sql := `
SELECT *
FROM goods_order
WHERE order_created_at >= ?
AND status < ?`
sqlParams := []interface{}{orderCreatedAfter, beforStatus}
err = GetRows(db, &orderList, sql, sqlParams...)
return orderList, err
}
func GetWayBillByOrderID(db *DaoDB, orderStatus, vendorID, waybillVendorID int, vendorOrderID string) (wayBillList []*model.Waybill, err error) {
sql := `
SELECT b.*
FROM goods_order a
JOIN waybill b ON IF(a.waybill_vendor_id = -1,a.vendor_order_id,a.vendor_waybill_id) = b.vendor_waybill_id AND b.order_vendor_id = a.vendor_id
WHERE a.vendor_order_id = ?
AND a.vendor_id = ?
`
sqlParams := []interface{}{
vendorOrderID,
vendorID,
}
if orderStatus > 0 {
sql += ` AND a.status = ?`
sqlParams = append(sqlParams, orderStatus)
}
if waybillVendorID > 0 {
sql += ` AND b.waybill_vendor_id = ?`
sqlParams = append(sqlParams, waybillVendorID)
}
err = GetRows(db, &wayBillList, sql, sqlParams...)
return wayBillList, err
}
func GetOrdersSupplement(db *DaoDB, storIDs, vendorIDs []int, vendorOrderID string, fromTime, toTime time.Time, status, stype, offset, pageSize int) (orderSupplementFee []*model.OrderSupplementFee, totalCount int, err error) {
sql := `
SELECT SQL_CALC_FOUND_ROWS *
FROM order_supplement_fee
WHERE 1=1
AND deleted_at = ?
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
}
if !utils.IsTimeZero(fromTime) {
sql += " AND supplement_time >= ?"
sqlParams = append(sqlParams, fromTime)
}
if !utils.IsTimeZero(toTime) {
sql += " AND supplement_time <= ?"
sqlParams = append(sqlParams, toTime)
}
if len(storIDs) > 0 {
sql += " AND store_id IN (" + GenQuestionMarks(len(storIDs)) + ")"
sqlParams = append(sqlParams, storIDs)
}
if len(vendorIDs) > 0 {
sql += " AND store_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")"
sqlParams = append(sqlParams, vendorIDs)
}
if vendorOrderID != "" {
sql += " AND vendor_order_id = ?"
sqlParams = append(sqlParams, vendorOrderID)
}
if status >= 0 {
sql += " AND status = ?"
sqlParams = append(sqlParams, status)
}
if stype >= 0 {
sql += " AND type = ?"
sqlParams = append(sqlParams, stype)
}
sql += `
LIMIT ? OFFSET ?`
sqlParams = append(sqlParams, pageSize, offset)
Begin(db)
defer Commit(db)
if err = GetRows(db, &orderSupplementFee, sql, sqlParams...); err == nil {
totalCount = GetLastTotalRowCount(db)
}
return orderSupplementFee, totalCount, err
}

View File

@@ -160,6 +160,10 @@ func GetCategoryIDDBField(prefix string) string {
return ConvertDBFieldPrefix(prefix) + "_category_id"
}
func GetVendorLockTimeStructField(prefix string) string {
return ConvertStructFieldPrefix(prefix) + "LockTime"
}
func value2Value(srcValue, dstValue reflect.Value, copyType int) {
srcType := srcValue.Type()
for i := 0; i < srcType.NumField(); i++ {

View File

@@ -188,10 +188,10 @@ func GetGetStatisticsReportForAfsOrders(db *DaoDB, storeIDs []int, fromDate time
func GetStatisticsReportForStoreSkusPrice(db *DaoDB, cityCodes, skuIDs []int) (priceReferSnapshot []*model.PriceReferSnapshot, err error) {
sql := `
SELECT b.city_code,a.sku_id,
MAX(a.price) max_price,
MIN(a.price) min_price,
ROUND(AVG(a.price)) avg_price,
ROUND(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT((a.price/IF(b.pay_percentage=0,100,b.pay_percentage))*100 ORDER BY (a.price/IF(b.pay_percentage=0,100,b.pay_percentage))*100),',',Count(1)/2),',',-1),2) mid_price,
ROUND(MAX(a.price/IF(b.pay_percentage=0,100,b.pay_percentage)*100)) max_price,
ROUND(MIN(a.price/IF(b.pay_percentage=0,100,b.pay_percentage)*100)) min_price,
ROUND(AVG(a.price/IF(b.pay_percentage=0,100,b.pay_percentage)*100)) avg_price,
ROUND(SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT((a.price/IF(b.pay_percentage=0,100,b.pay_percentage))*100 ORDER BY (a.price/IF(b.pay_percentage=0,100,b.pay_percentage))*100),',',Count(1)/2),',',-1)) mid_price,
MAX(a.jd_price) max_jd_price,
MIN(a.jd_price) min_jd_price,
ROUND(AVG(a.jd_price)) avg_jd_price,
@@ -211,8 +211,7 @@ func GetStatisticsReportForStoreSkusPrice(db *DaoDB, cityCodes, skuIDs []int) (p
t1.min_vendor_price,
t1.avg_vendor_price
FROM store_sku_bind a
JOIN store b ON a.store_id = b.id AND b.deleted_at = ?
JOIN sku d ON a.sku_id = d.id AND d.deleted_at = ?
JOIN store b ON a.store_id = b.id AND b.deleted_at = ? AND b.status != ?
LEFT JOIN (
SELECT SUM(t1.count),t1.sku_id,MAX(t1.sale_price) max_sale_price,MIN(t1.sale_price) min_sale_price,ROUND(AVG(t1.sale_price)) avg_sale_price,MAX(t1.vendor_price) max_vendor_price,MIN(t1.vendor_price) min_vendor_price,ROUND(AVG(t1.vendor_price)) avg_vendor_price
FROM order_sku t1
@@ -220,12 +219,14 @@ func GetStatisticsReportForStoreSkusPrice(db *DaoDB, cityCodes, skuIDs []int) (p
GROUP BY 2
)t1 ON t1.sku_id = a.sku_id
WHERE a.deleted_at = ?
AND a.status = ?
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
utils.DefaultTimeValue,
model.StoreStatusDisabled,
time.Now().AddDate(0, -1, 0),
utils.DefaultTimeValue,
model.SkuStatusNormal,
}
if len(skuIDs) > 0 {
sql += " AND a.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
@@ -277,7 +278,7 @@ func GetPriceReferSnapshot(db *DaoDB, cityCodes, skuIDs []int, snapDate time.Tim
err = err2
if len(skuList) > 0 {
skuAndName := skuList[0]
jxSkuDetailName := jxutils.ComposeSkuName(skuAndName.Prefix, skuAndName.Name, skuAndName.Comment, skuAndName.Unit, skuAndName.SpecQuality, skuAndName.SpecUnit, 0)
jxSkuDetailName := jxutils.ComposeSkuNameOriginal(skuAndName.Prefix, skuAndName.Name, skuAndName.Comment, skuAndName.Unit, skuAndName.SpecQuality, skuAndName.SpecUnit, 0)
v.SkuName = jxSkuDetailName
}
}

View File

@@ -8,16 +8,17 @@ import (
"git.rosy.net.cn/jx-callback/globals"
)
type tStoreSkuSyncInfo2 struct {
StoreSkuSyncInfo
VendorPlaceCode string
}
type SkuCategoryWithVendor struct {
*model.SkuCategory
MapList []*model.ThingMap `json:"mapList"`
}
type SkuNamePlace struct {
model.Place
NameID int `orm:"column(name_id)" json:"nameID"`
SkuID int `orm:"column(sku_id)" json:"skuID"`
}
func GetSellCities(db *DaoDB, nameID int, vendorID int) (cities []*model.Place, err error) {
cities = []*model.Place{}
sql := `
@@ -49,7 +50,7 @@ func DeleteSkuNamePlace(db *DaoDB, nameID int, placeCodes []int) (num int64, err
return ExecuteSQL(db, sql, sqlParams...)
}
func GetCategories(db *DaoDB, parentID int, catIDs []int) (cats []*model.SkuCategory, err error) {
func GetCategories(db *DaoDB, parentID, level int, catIDs []int) (cats []*model.SkuCategory, err error) {
sql := `
SELECT t1.*
FROM sku_category t1
@@ -62,16 +63,20 @@ func GetCategories(db *DaoDB, parentID int, catIDs []int) (cats []*model.SkuCate
params = append(params, parentID)
}
if len(catIDs) > 0 {
sql += " AND t1.id (" + GenQuestionMarks(len(catIDs)) + ")"
sql += " AND t1.id IN (" + GenQuestionMarks(len(catIDs)) + ")"
params = append(params, catIDs)
}
if level > 0 {
sql += " AND t1.level = ?"
params = append(params, level)
}
sql += " ORDER BY t1.level, t1.seq"
return cats, GetRows(db, &cats, sql, params)
}
func GetSkus(db *DaoDB, skuIDs, nameIDs, statuss, catIDs []int) (skuList []*model.SkuAndName, err error) {
sql := `
SELECT t1.*, t2.name, t2.unit, t2.prefix, t2.is_spu
SELECT t1.*, t2.name, t2.unit, t2.prefix, t2.is_spu, t2.ex_prefix, t2.ex_prefix_begin, t2.ex_prefix_end
FROM sku t1
JOIN sku_name t2 ON t2.id = t1.name_id AND t2.deleted_at = ?
`
@@ -174,6 +179,9 @@ func SetSkuSyncStatus(db *DaoDB, vendorID int, skuIDs []int, syncStatus int) (nu
return ExecuteSQL(db, sql, sqlParams...)
}
// todo, GetSkuCategoryWithVendor与GetSkusWithVendor
// 如果mustDirty为true应该是要thing_map为基表LEFT JOIN原始实体表否则当原始实体记录在未同步前被物理删除后无法真正同步
// 多门店平台使用,当前只有京东
func GetSkuCategoryWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, parentCatID int, catIDs []int, mustDirty bool) (catList []*SkuStoreCatInfo, err error) {
sql := `
@@ -211,7 +219,7 @@ func GetSkuCategoryWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string,
`
sqlParams = append(sqlParams, model.ThingTypeCategory, utils.DefaultTimeValue)
if mustDirty {
sql += " AND t1m.sync_status <> 0"
sql += " AND t1m.sync_status IS NOT NULL AND t1m.sync_status <> 0"
} else {
sql += " AND t1.deleted_at = ?"
sqlParams = append(sqlParams, utils.DefaultTimeValue)
@@ -252,9 +260,9 @@ func GetSkusWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, nameIDs
IF(t11.resource_type IS NULL OR t11.resource_type <> ?, t2.img, '') img,
IF(t12.resource_type IS NULL OR t12.resource_type <> ?, t2.img2, '') img2,
t2.desc_img,
t5.jd_code vendor_place_code,
t2.ex_prefix,
t2.ex_prefix_begin,
t2.ex_prefix_end,
t3.jd_category_id vendor_vendor_cat_id,
t3m.sync_status cat_sync_status,
@@ -281,15 +289,13 @@ func GetSkusWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, nameIDs
LEFT JOIN sku_category t3 ON t3.id = t2.category_id
LEFT JOIN thing_map t3m ON t3m.thing_id = t3.id AND t3m.thing_type = ? AND t3m.deleted_at = ?
AND t3m.vendor_id = t1m.vendor_id AND t3m.vendor_org_code = t1m.vendor_org_code
LEFT JOIN sku_name_place_bind t4 ON t2.is_global = 0 AND t4.name_id = t1.name_id
LEFT JOIN place t5 ON t5.code = t4.place_code
LEFT JOIN data_resource t11 ON t11.main_url = t2.img
LEFT JOIN data_resource t12 ON t12.main_url = t2.img2
WHERE 1 = 1
`
sqlParams = append(sqlParams, model.ThingTypeCategory, utils.DefaultTimeValue)
if mustDirty {
sql += " AND t1m.sync_status <> 0"
sql += " AND t1m.sync_status IS NOT NULL AND t1m.sync_status <> 0"
} else {
sql += " AND t1.deleted_at = ?"
sqlParams = append(sqlParams, utils.DefaultTimeValue)
@@ -303,19 +309,47 @@ func GetSkusWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, nameIDs
sqlParams = append(sqlParams, skuIDs)
}
sql += " ORDER BY t1.seq"
var list []*tStoreSkuSyncInfo2
if err = GetRows(db, &list, sql, sqlParams...); err == nil {
skuMap := make(map[int]*StoreSkuSyncInfo)
for _, v := range list {
if skuMap[v.SkuID] == nil {
skuMap[v.SkuID] = &v.StoreSkuSyncInfo
skuList = append(skuList, &v.StoreSkuSyncInfo)
if err = GetRows(db, &skuList, sql, sqlParams...); err == nil {
skuPlaceList, err2 := GetSkuNamePlaces(db, nameIDs, skuIDs)
if err = err2; err == nil {
skuPlaceMap := make(map[int][]*SkuNamePlace)
for _, v := range skuPlaceList {
skuPlaceMap[v.SkuID] = append(skuPlaceMap[v.SkuID], v)
}
if !IsVendorThingIDEmpty(v.VendorPlaceCode) {
skuMap[v.SkuID].SellCities = append(skuMap[v.SkuID].SellCities, v.VendorPlaceCode)
for _, v := range skuList {
if v.IsGlobal == 0 {
for _, v2 := range skuPlaceMap[v.SkuID] {
// 京东到家
if v2.JdCode > 0 {
v.SellCities = append(v.SellCities, utils.Int2Str(v2.JdCode))
}
}
}
}
}
}
return skuList, err
}
func GetSkuNamePlaces(db *DaoDB, nameIDs, skuIDs []int) (skuPlaceList []*SkuNamePlace, err error) {
sql := `
SELECT
t4.*,
t2.id sku_id, t2.name_id
FROM sku t2
JOIN sku_name_place_bind t3 ON t3.name_id = t2.name_id
JOIN place t4 ON t4.code = t3.place_code
WHERE t2.deleted_at = ?
`
sqlParams := []interface{}{utils.DefaultTimeValue}
if len(nameIDs) > 0 {
sql += " AND t2.name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")"
sqlParams = append(sqlParams, nameIDs)
}
if len(skuIDs) > 0 {
sql += " AND t2.id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
sqlParams = append(sqlParams, skuIDs)
}
err = GetRows(db, &skuPlaceList, sql, sqlParams...)
return skuPlaceList, err
}

View File

@@ -14,10 +14,11 @@ type StoreDetail struct {
VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空
VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"`
VendorStatus int `json:"vendor_status"` // 取值同Store.Status
DeliveryFee int `json:"deliveryFee"`
SyncStatus int8 `orm:"default(2)" json:"syncStatus"`
VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"`
VendorStoreName string `json:"vendorStoreName"`
VendorStatus int `json:"vendor_status"` // 取值同Store.Status
DeliveryFee int `json:"deliveryFee"`
SyncStatus int8 `orm:"default(2)" json:"syncStatus"`
PricePercentage int16 `orm:"default(100)" json:"pricePercentage"` // todo 厂商价格相对于本地价格的百分比,这个字段的修改会比较特殊,因为可能需要刷新厂商价格
PricePercentagePackStr string `orm:"size(4096)" json:"-"` //
@@ -38,6 +39,8 @@ type StoreDetail struct {
MarketManName string `json:"marketManName"` //市场负责人
OperatorName string `json:"operatorName"` //运营负责人
OperatorName2 string `json:"operatorName2"`
JdStoreLevel string `json:"jdStoreLevel"` //京东门店等级
}
// 带快递门店信息的
@@ -60,10 +63,12 @@ type CityBrankBranch struct {
}
type StorePriceScore struct {
StoreID int `orm:"column(store_id)" json:"storeID"`
StoreName string `json:"storeName"`
StoreScore float64 `json:"storeScore"`
CityName string `json:"cityName"`
StoreID int `orm:"column(store_id)" json:"storeID"`
StoreName string `json:"storeName"`
StoreScore float64 `json:"storeScore"`
CityName string `json:"cityName"`
DirectDownCount int `json:"directDownCount"`
SecKillCount int `json:"secKillCount"`
}
type StorePriceScoreEx struct {
@@ -78,8 +83,8 @@ func (s *StoreDetail) GetPricePerentage(price int) (pricePercentage int) {
func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (storeDetail *StoreDetail, err error) {
sql := `
SELECT t1.*,
t2.vendor_store_id, t2.status vendor_status, t2.delivery_fee, t2.sync_status,
t2.price_percentage, t2.auto_pickup, t2.delivery_type, t2.delivery_competition, t2.is_sync,
t2.vendor_store_id, t2.status vendor_status, t2.delivery_fee, t2.sync_status, t2.vendor_org_code,
t2.price_percentage, t2.auto_pickup, t2.delivery_type, t2.delivery_competition, t2.is_sync, t2.vendor_store_name,
t3.value price_percentage_pack_str,
t4.value freight_deduction_pack_str,
district.name district_name,
@@ -484,16 +489,39 @@ func GetStoreMapsListWithoutDisabled(db *DaoDB, vendorIDs []int, status int) (st
return storeMapList, err
}
func GetStorePriceScore(db *DaoDB, storeIDs []int, fromScore, toScore, sort int, snapDate time.Time, offset, pageSize int) (StorePriceScore []*StorePriceScore, totalCount int, err error) {
func GetStorePriceScore(db *DaoDB, storeIDs, vendorIDs []int, fromScore, toScore, sort int, snapDate time.Time, offset, pageSize int) (StorePriceScore []*StorePriceScore, totalCount int, err error) {
sql := `
SELECT SQL_CALC_FOUND_ROWS a.store_id,score store_score,e.name city_name,b.name store_name
SELECT SQL_CALC_FOUND_ROWS a.store_id, score store_score, e.name city_name, b.name store_name, t1.direct_down_count, t1.sec_kill_count
FROM store_price_score_snapshot a
JOIN store b ON b.id = a.store_id
JOIN place e ON e.code = b.city_code
JOIN (SELECT a.store_id, count(d.type = ? OR NULL) direct_down_count, count(d.type = ? OR NULL) sec_kill_count
FROM store_sku_bind a
LEFT JOIN act_store_sku b ON a.store_id = b.store_id AND b.sku_id = a.sku_id
LEFT JOIN act_map c ON c.act_id = b.act_id
LEFT JOIN act d ON d.id = c.act_id
WHERE 1=1
`
sqlParams := []interface{}{
model.ActSkuDirectDown, model.ActSkuSecKill,
}
if len(storeIDs) > 0 {
sql += " AND a.store_id IN(" + GenQuestionMarks(len(storeIDs)) + ")"
sqlParams = append(sqlParams, storeIDs)
}
if len(vendorIDs) > 0 {
sql += " AND c.vendor_id IN(" + GenQuestionMarks(len(vendorIDs)) + ")"
sqlParams = append(sqlParams, vendorIDs)
}
sql += `
AND NOW() BETWEEN d.begin_at AND d.end_at
AND a.status = ?
AND a.deleted_at = ?
GROUP BY a.store_id)t1 ON t1.store_id = a.store_id
WHERE 1=1
`
sqlParams := []interface{}{}
if fromScore != 0 && toScore != 0 {
sqlParams = append(sqlParams, model.StoreSkuBindStatusNormal, utils.DefaultTimeValue)
if fromScore != 0 || toScore != 0 {
sql += " AND a.score BETWEEN ? AND ?"
sqlParams = append(sqlParams, fromScore, toScore)
}
@@ -505,10 +533,18 @@ func GetStorePriceScore(db *DaoDB, storeIDs []int, fromScore, toScore, sort int,
sql += " AND a.snapshot_at = ?"
sqlParams = append(sqlParams, snapDate)
}
if sort == 0 {
if sort == 1 {
sql += " ORDER BY a.score"
} else {
} else if sort == -1 {
sql += " ORDER BY a.score DESC"
} else if sort == 2 {
sql += " ORDER BY t1.direct_down_count"
} else if sort == -2 {
sql += " ORDER BY t1.direct_down_count DESC"
} else if sort == 3 {
sql += " ORDER BY t1.sec_kill_count"
} else if sort == -3 {
sql += " ORDER BY t1.sec_kill_count DESC"
}
sql += " LIMIT ? OFFSET ?"
sqlParams = append(sqlParams, pageSize, offset)

View File

@@ -18,6 +18,7 @@ var (
model.VendorIDMTWM: "mtwm_url",
model.VendorIDEBAI: "ebai_url",
}
salePriceLimit = 100
)
type SkuStoreCatInfo struct {
@@ -56,7 +57,10 @@ type StoreSkuSyncInfo struct {
model.Sku
// sku_name
Prefix string
Prefix string
ExPrefix string
ExPrefixBegin *time.Time
ExPrefixEnd *time.Time
// NameID int `orm:"column(name_id)"`
VendorNameID string `orm:"column(vendor_name_id)"` // 暂时无用
Name string
@@ -69,7 +73,7 @@ type StoreSkuSyncInfo struct {
// 平台相关的图片信息
Img string
Img2 string
DescImg string // 饿百是SkuName中的DescImgEbai
DescImg string
VendorVendorCatID int64 `orm:"column(vendor_vendor_cat_id)"` // 平台商品分类(叶子结点)
@@ -81,7 +85,9 @@ type StoreSkuSyncInfo struct {
CatSyncStatus int8
VendorCatID string `orm:"column(vendor_cat_id)"`
VendorPrice int64
VendorPrice int64
LockTime *time.Time
MergedStatus int
SkuName string
StatusSaleBegin int16 `json:"statusSaleBegin"` //商品可售时间范围
@@ -167,6 +173,11 @@ type StoreSkuExt struct {
MtwmPrice int `json:"mtwmPrice"`
JxPrice int `json:"jxPrice"`
JdLockTime *time.Time `orm:"null" json:"jdLockTime,omitempty"`
EbaiLockTime *time.Time `orm:"null" json:"ebaiLockTime,omitempty"`
MtwmLockTime *time.Time `orm:"null" json:"mtwmLockTime,omitempty"`
JxLockTime *time.Time `orm:"null" json:"jxLockTime,omitempty"`
AutoSaleAt time.Time `orm:"type(datetime);null" json:"autoSaleAt"`
ActPrice int `json:"actPrice"`
@@ -176,7 +187,7 @@ type StoreSkuExt struct {
EarningPrice int `json:"earningPrice"`
EarningActID int `orm:"column(earning_act_id)" json:"earningActID"`
RealEarningPrice int `json:"realEarningPrice"`
// RealEarningPrice int `json:"realEarningPrice"`
StatusSaleBegin int16 `json:"statusSaleBegin"` //商品可售时间范围
StatusSaleEnd int16 `json:"statusSaleEnd"`
@@ -185,6 +196,15 @@ type StoreSkuExt struct {
Times int `json:"times"`
}
type SkuNameAndPlace struct {
model.SkuName
CityCode int `json:"cityCode"`
CityName string `json:"cityName"`
Sequence int `json:"sequence"`
Count int `json:"count"`
Type int `json:"type"`
}
// todo 应该通过需要同步的skuid来驱动同步分类而不是当前这种分开的逻辑
// 单门店模式厂商适用
// 从store_sku_bind中得到所有依赖的商家分类信息
@@ -302,16 +322,16 @@ func newGetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty
SELECT
t14.vendor_id, t14.vendor_org_code,
t1.id bind_id, t1.sku_id, t1.price, t1.unit_price, t1.status store_sku_status,
%s vendor_sku_id, t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price,
%s vendor_sku_id, t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price, t1.%s_lock_time lock_time,
t1.store_id, t1.deleted_at bind_deleted_at,t1.status_sale_begin,t1.status_sale_end,
t2.*,
t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc,
t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.ex_prefix, t3.ex_prefix_begin, t3.ex_prefix_end,
IF(t11.%s <> '', t11.%s, t3.img) img,
IF(t12.%s <> '', t12.%s, t3.img2) img2,
t13.%s desc_img,
t4.%s_category_id vendor_vendor_cat_id`
fmtParams := []interface{}{
skuVendorIDField, fieldPrefix, fieldPrefix,
skuVendorIDField, fieldPrefix, fieldPrefix, fieldPrefix,
GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
GetDataResFieldName(vendorID),
@@ -329,7 +349,7 @@ func newGetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty
}
sql += `
FROM store_sku_bind t1
LEFT JOIN store_map t14 ON t14.store_id = t1.store_id AND t14.vendor_id = ? AND t14.deleted_at = ?
JOIN store_map t14 ON t14.store_id = t1.store_id AND t14.vendor_id = ? AND t14.deleted_at = ?
LEFT JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? AND t2.status = ?
LEFT JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ?
LEFT JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ?
@@ -351,7 +371,7 @@ func newGetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty
} else {
sql += `
LEFT JOIN sku_category t5sku ON t5sku.id = t2.category_id
LEFT JOIN thing_map t2m ON t2m.thing_id = t1.sku_id AND t2m.vendor_org_code = t14.vendor_org_code AND t2m.thing_type = ? AND t2m.vendor_id = ? AND t2m.deleted_at = ?
JOIN thing_map t2m ON t2m.thing_id = t1.sku_id AND t2m.vendor_org_code = t14.vendor_org_code AND t2m.thing_type = ? AND t2m.vendor_id = ? AND t2m.deleted_at = ?
LEFT JOIN thing_map t4m ON t4m.thing_id = t3.category_id AND t4m.vendor_org_code = t14.vendor_org_code AND t4m.thing_type = ? AND t4m.vendor_id = ? AND t4m.deleted_at = ?
LEFT JOIN thing_map t5skum ON t5skum.thing_id = t5sku.id AND t5skum.vendor_org_code = t14.vendor_org_code AND t5skum.thing_type = ? AND t5skum.vendor_id = ? AND t5skum.deleted_at = ?
`
@@ -410,7 +430,7 @@ func oldGetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty
%s.%s_id vendor_sku_id, t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price,
t1.store_id, t1.deleted_at bind_deleted_at,t1.status_sale_begin,t1.status_sale_end,
t2.*,
t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc,
t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc,t3.ex_prefix, t3.ex_prefix_begin, t3.ex_prefix_end,
IF(t11.%s <> '', t11.%s, t3.img) img,
IF(t12.%s <> '', t12.%s, t3.img2) img2,
t13.%s desc_img,
@@ -504,11 +524,15 @@ func GetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSyncInf
func newGetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSyncInfo, err error) {
globals.SugarLogger.Debugf("GetFullStoreSkus, storeID:%d, vendorID:%d", storeID, vendorID)
// 对于多门店平台商品库删除后不需要操作门店商品所以sku_name用JOIN, sku与sku_name也可以直接排除下架的
sql := `
SELECT t1.id bind_id, t1.price, t1.unit_price, t1.status store_sku_status,
t1.%s_sync_status sku_sync_status, t1.store_id, t1.deleted_at bind_deleted_at,
SELECT
sm.vendor_id, sm.vendor_org_code,
t1.id bind_id, t1.price, t1.unit_price, t1.status store_sku_status,
t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price, t1.%s_lock_time lock_time,
t1.store_id, t1.deleted_at bind_deleted_at,
t2.*, t2.id sku_id, t2m.vendor_thing_id vendor_sku_id,
t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc,
t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.ex_prefix, t3.ex_prefix_begin, t3.ex_prefix_end,
IF(t11.%s <> '', t11.%s, t3.img) img,
IF(t12.%s <> '', t12.%s, t3.img2) img2,
t13.%s desc_img,
@@ -516,12 +540,12 @@ func newGetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSync
t4m.sync_status cat_sync_status, t4m.vendor_thing_id vendor_cat_id,
t5skum.sync_status sku_cat_sync_status, t5skum.vendor_thing_id sku_vendor_cat_id
FROM sku t2
LEFT JOIN store_sku_bind t1 ON t1.sku_id = t2.id AND t1.store_id = ? AND t1.deleted_at = ?
LEFT JOIN store_map sm ON sm.store_id = t1.store_id AND sm.vendor_id = ? AND sm.deleted_at = ?
LEFT JOIN thing_map t2m ON t2m.thing_id = t2.id AND t2m.vendor_org_code = sm.vendor_org_code AND t2m.thing_type = ? AND t2m.vendor_id = ? AND t2m.deleted_at = ?
JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ?
JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ?
LEFT JOIN thing_map t4m ON t4m.thing_id = t3.category_id AND t4m.vendor_org_code = sm.vendor_org_code AND t4m.thing_type = ? AND t4m.vendor_id = ? AND t4m.deleted_at = ?
JOIN store_map sm ON sm.vendor_id = ? AND sm.store_id = ? AND sm.deleted_at = ?
JOIN thing_map t2m ON t2m.thing_id = t2.id AND t2m.vendor_org_code = sm.vendor_org_code AND t2m.thing_type = ? AND t2m.vendor_id = ? AND t2m.deleted_at = ?
JOIN thing_map t4m ON t4m.thing_id = t3.category_id AND t4m.vendor_org_code = sm.vendor_org_code AND t4m.thing_type = ? AND t4m.vendor_id = ? AND t4m.deleted_at = ?
LEFT JOIN store_sku_bind t1 ON sm.store_id = t1.store_id AND t1.sku_id = t2.id AND t1.deleted_at = ?
LEFT JOIN sku_category t5sku ON t2.category_id = t5sku.id
LEFT JOIN thing_map t5skum ON t5skum.thing_id = t2.category_id AND t5skum.vendor_org_code = sm.vendor_org_code AND t5skum.thing_type = ? AND t5skum.vendor_id = ? AND t5skum.deleted_at = ?
LEFT JOIN data_resource t11 ON t11.main_url = t3.img
@@ -530,21 +554,18 @@ func newGetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSync
WHERE t2.deleted_at = ? AND t2.status = ? AND t2m.vendor_thing_id <> ''
ORDER BY t1.price DESC`
sqlParams := []interface{}{
storeID,
utils.DefaultTimeValue, model.SkuStatusNormal,
utils.DefaultTimeValue,
vendorID, utils.DefaultTimeValue,
vendorID, storeID, utils.DefaultTimeValue,
model.ThingTypeSku, vendorID, utils.DefaultTimeValue,
utils.DefaultTimeValue,
model.SkuStatusNormal,
utils.DefaultTimeValue,
model.ThingTypeCategory, vendorID, utils.DefaultTimeValue,
model.ThingTypeCategory, vendorID, utils.DefaultTimeValue,
utils.DefaultTimeValue,
model.SkuStatusNormal,
model.ThingTypeCategory, vendorID, utils.DefaultTimeValue,
utils.DefaultTimeValue, model.SkuStatusNormal,
}
fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID])
sql = fmt.Sprintf(sql,
fieldPrefix,
fieldPrefix, fieldPrefix, fieldPrefix,
GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
GetDataResFieldName(vendorID), GetDataResFieldName(vendorID),
GetDataResFieldName(vendorID),
@@ -860,7 +881,7 @@ func GetStoresSkusInfoBySaleTime(db *DaoDB, storeID int) (storeSkuBindList []*mo
return storeSkuBindList, err
}
func UpdateStoreSkuBindSyncStatus(db *DaoDB, vendorIDs []int, storeID int) (num int64, err error) {
func UpdateStoreSkuBindSyncStatusForSaleStatus(db *DaoDB, vendorIDs []int, storeID int) (num int64, err error) {
sql := `
UPDATE store_sku_bind
SET
@@ -892,6 +913,74 @@ func UpdateStoreSkuBindSyncStatus(db *DaoDB, vendorIDs []int, storeID int) (num
return ExecuteSQL(db, sql, sqlParams...)
}
func UpdateStoreSkuBindSyncStatusForExPrefix(db *DaoDB, vendorIDs []int) (num int64, err error) {
sql := `
UPDATE store_sku_bind a
JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ?
JOIN sku_name c ON c.id = b.name_id AND c.deleted_at = ?
SET
`
fmtParams := []interface{}{}
sqlParams := []interface{}{
utils.DefaultTimeValue,
utils.DefaultTimeValue,
}
if len(vendorIDs) > 0 {
for _, v := range vendorIDs {
fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[v])
sql += ` %s_sync_status = %s_sync_status | ?,`
fmtParams = append(fmtParams, fieldPrefix, fieldPrefix)
sqlParams = append(sqlParams, model.SyncFlagModifiedMask)
}
} else {
return 0, errors.New("取平台ID名有错误partner.GetPurchasePlatformVendorIDs()")
}
sql = sql[0:strings.LastIndex(sql, ",")]
sql = fmt.Sprintf(sql, fmtParams...)
sql += ` WHERE a.deleted_at = ?
AND c.ex_prefix != ""
AND (c.ex_prefix_begin = DATE_FORMAT(DATE_ADD(NOW(),INTERVAL '6' HOUR),'%Y-%m-%d 00:00:00')
OR c.ex_prefix_end = DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00'))
`
sqlParams = append(sqlParams, utils.DefaultTimeValue)
return ExecuteSQL(db, sql, sqlParams...)
}
func UpdateSkuSyncStatusForExPrefix(db *DaoDB, vendorIDs []int) (num int64, err error) {
sql := `
UPDATE thing_map t1
JOIN sku t2 ON t2.id = t1.thing_id AND t2.deleted_at = ?
JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ?
AND t3.ex_prefix <> '' AND (t3.ex_prefix_begin = DATE_FORMAT(DATE_ADD(NOW(),INTERVAL '6' HOUR),'%Y-%m-%d 00:00:00')
OR t3.ex_prefix_end = DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00'))
SET
t1.sync_status = t1.sync_status | ?
WHERE t1.deleted_at = ? AND t1.thing_type = ? AND t1.sync_status & ? <> 0
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
utils.DefaultTimeValue,
model.SyncFlagModifiedMask,
utils.DefaultTimeValue, model.ThingTypeSku, model.SyncFlagDeletedMask,
}
if len(vendorIDs) > 0 {
sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")"
sqlParams = append(sqlParams, vendorIDs)
}
return ExecuteSQL(db, sql, sqlParams...)
}
func DeleteSkuNameExPrefixOverdue(db *DaoDB) (num int64, err error) {
sql := `
UPDATE sku_name
SET ex_prefix_begin = null,ex_prefix_end = null
WHERE deleted_at = ?
AND DATE_FORMAT(DATE_ADD(NOW(),INTERVAL '6' HOUR),'%Y-%m-%d 00:00:00') >= ex_prefix_end
`
sqlParams := []interface{}{utils.DefaultTimeValue}
return ExecuteSQL(db, sql, sqlParams...)
}
func GetStoreSkusByNameIDs(db *DaoDB, storeIDs []int, nameID int) (skuList []*StoreSkuSyncInfo, err error) {
sql := `
SELECT a.*,c.unit,c.name
@@ -924,7 +1013,7 @@ func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSk
JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id
JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ?
JOIN sku_name t1 ON t1.id = c.name_id AND t1.deleted_at = ?
STRAIGHT_JOIN store_sku_bind t4 ON t4.store_id = IF(a.store_id = 0,a.jx_store_id,a.store_id) AND t4.sku_id = b.sku_id AND t4.status = ? AND t4.deleted_at = ?
STRAIGHT_JOIN store_sku_bind t4 ON t4.store_id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND t4.sku_id = b.sku_id AND t4.status = ? AND t4.deleted_at = ?
JOIN store d ON d.id = a.store_id
WHERE 1=1
AND a.order_created_at BETWEEN ? and NOW()
@@ -948,7 +1037,7 @@ func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSk
ORDER BY t1.count DESC
LIMIT ?
`
sqlParams = append(sqlParams, 100, 30)
sqlParams = append(sqlParams, salePriceLimit, 30)
err = GetRows(db, &storeSkuNameExt, sql, sqlParams...)
var skuNamesInfo = &StoreSkuNamesInfo{
SkuNames: storeSkuNameExt,
@@ -984,7 +1073,33 @@ func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSk
return storeSkuNameExt, err
}
func GetTopCategorysByStoreIDs(db *DaoDB, storeIDs []int) (skuCategory []*model.SkuCategory, err error) {
func GetTopSkusByCityCode(db *DaoDB, cityCode int, orderCreate time.Time) (skuNameAndPlace []*SkuNameAndPlace, err error) {
sql := `
SELECT SUM(b.count) count, e.name city_name, d.city_code, f.*
FROM goods_order a
JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id
JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ?
JOIN sku_name f ON f.id = c.name_id
JOIN store d ON d.id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND d.deleted_at = ? AND d.city_code = ?
JOIN place e ON e.code = d.city_code
WHERE 1=1
AND b.sale_price > ?
AND a.order_created_at BETWEEN ? and NOW()
GROUP BY 2,3,4
ORDER BY count DESC
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
utils.DefaultTimeValue,
cityCode,
salePriceLimit,
orderCreate,
}
err = GetRows(db, &skuNameAndPlace, sql, sqlParams...)
return skuNameAndPlace, err
}
func GetTopCategoriesByStoreIDs(db *DaoDB, storeIDs []int, limit int) (skuCategory []*model.SkuCategory, err error) {
sql := `
SELECT DISTINCT t5.* FROM(
SELECT d.*
@@ -993,10 +1108,10 @@ func GetTopCategorysByStoreIDs(db *DaoDB, storeIDs []int) (skuCategory []*model.
FROM(
SELECT SUM(b.count) count,d.category_id
FROM goods_order a
JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id
JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id
JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ?
JOIN sku_name d ON d.id = c.name_id AND d.deleted_at = ?
JOIN store e ON e.id = a.store_id
JOIN store e ON e.id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND e.status != -2
JOIN (SELECT city_code FROM store WHERE 1=1
`
sqlParams := []interface{}{
@@ -1023,11 +1138,51 @@ func GetTopCategorysByStoreIDs(db *DaoDB, storeIDs []int) (skuCategory []*model.
Order by t4.count DESC)t5
LIMIT ?
`
sqlParams = append(sqlParams, time.Now().AddDate(0, -1, 0), 100, 2, utils.DefaultTimeValue, 1, 10)
sqlParams = append(sqlParams, time.Now().AddDate(0, -1, 0), salePriceLimit, 2, utils.DefaultTimeValue, 1, limit)
err = GetRows(db, &skuCategory, sql, sqlParams...)
return skuCategory, err
}
func GetStoreSkuCategories(db *DaoDB, storeID, parentID int) (catList []*model.SkuCategory, err error) {
sql := `
SELECT
t1.*
FROM sku_category t1
JOIN
(
SELECT DISTINCT t3.category_id
FROM store_sku_bind t1
JOIN sku t2 ON t2.id = t1.sku_id AND t2.deleted_at = ? AND t2.status = ?
JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ? AND t3.status = ?
WHERE t1.deleted_at = ? AND t1.status = ? AND t1.store_id = ?
) t2 ON t2.category_id = t1.id
WHERE t1.deleted_at = ?`
sqlParams := []interface{}{
utils.DefaultTimeValue, model.SkuStatusNormal,
utils.DefaultTimeValue, model.SkuStatusNormal,
utils.DefaultTimeValue, model.SkuStatusNormal, storeID,
utils.DefaultTimeValue,
}
if parentID >= 0 {
sql += " AND t1.parent_id = ?"
sqlParams = append(sqlParams, parentID)
}
sql += " ORDER BY t1.level, t1.seq"
if err = GetRows(db, &catList, sql, sqlParams...); err == nil && len(catList) > 0 {
parentIDMap := make(map[int]int)
for _, v := range catList {
parentIDMap[v.ParentID] = 1
}
paretnCats, err2 := GetCategories(db, -1, 0, jxutils.IntMap2List(parentIDMap))
if err = err2; err == nil {
catList = append(catList, paretnCats...)
} else {
catList = nil
}
}
return catList, err
}
func RefershStoreSkusMidPrice(db *DaoDB, storeIDs []int) (count int64, err error) {
sql := `
UPDATE store_sku_bind a
@@ -1068,16 +1223,21 @@ func GetStoreSkuNamePrice(db *DaoDB) (storeSkuNamePriceList []*model.StoreSkuNam
return storeSkuNamePriceList, err
}
func SetStoreSkuBindVendorPrice(storeSkuBind *model.StoreSkuBind, vendorID int, vendorPrice int) {
func SetStoreSkuBindVendorPrice(storeSkuBind *model.StoreSkuBind, vendorID int, vendorPrice int, lockTime time.Time) {
pLockTime := utils.Time2Pointer(lockTime)
switch vendorID {
case model.VendorIDJD:
storeSkuBind.JdPrice = vendorPrice
storeSkuBind.JdLockTime = pLockTime
case model.VendorIDMTWM:
storeSkuBind.MtwmPrice = vendorPrice
storeSkuBind.MtwmLockTime = pLockTime
case model.VendorIDEBAI:
storeSkuBind.EbaiPrice = vendorPrice
storeSkuBind.EbaiLockTime = pLockTime
case model.VendorIDJX:
storeSkuBind.JxPrice = vendorPrice
storeSkuBind.JxLockTime = pLockTime
}
}
@@ -1136,7 +1296,7 @@ func UpdateActPrice4StoreSkuNameNew(db *DaoDB, storeIDs, skuIDs []int, skuNamesI
if actVendorID >= 0 {
vendorIDs = []int{actVendorID}
}
actStoreSkuList, err := GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, storeIDs, skuIDs, time.Now(), time.Now())
actStoreSkuList, err := GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, model.ActTypeAll, storeIDs, skuIDs, time.Now(), time.Now())
if err != nil {
globals.SugarLogger.Errorf("updateActPrice4StoreSkuNameNew can not get sku promotion info for error:%v", err)
return err
@@ -1151,15 +1311,16 @@ func UpdateActPrice4StoreSkuNameNew(db *DaoDB, storeIDs, skuIDs []int, skuNamesI
v.ActPrice = int(actStoreSku.ActualActPrice)
v.ActID = actStoreSku.ActID
v.ActType = actStoreSku.Type
v.EarningPrice = int(jxutils.CaculateSkuEarningPrice(int64(v.ActPrice), int64(v.ActPrice), skuName.PayPercentage))
}
if actStoreSku := actStoreSkuMap4EarningPrice.GetActStoreSku(skuName.StoreID, v.SkuID, -1); actStoreSku != nil {
v.EarningPrice = int(actStoreSku.EarningPrice)
v.EarningActID = actStoreSku.ActID
}
v.RealEarningPrice = v.EarningPrice
if v.RealEarningPrice == 0 {
v.RealEarningPrice = int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.BindPrice), skuName.PayPercentage))
} else {
earningPrice := int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.BindPrice), skuName.PayPercentage))
if earningPrice < v.EarningPrice {
v.EarningPrice = earningPrice
}
}
}
} else {
@@ -1168,3 +1329,65 @@ func UpdateActPrice4StoreSkuNameNew(db *DaoDB, storeIDs, skuIDs []int, skuNamesI
}
return err
}
func GetDeletedStoreSkuBind(db *DaoDB, storeID, skuID int) (storeSkuBind *model.StoreSkuBind) {
sql := `
SELECT a.*
FROM store_sku_bind a
WHERE a.store_id = ? AND a.sku_id = ?
ORDER BY a.deleted_at DESC`
sqlParams := []interface{}{
storeID, skuID,
}
if err := GetRow(db, &storeSkuBind, sql, sqlParams...); err != nil {
storeSkuBind = nil
}
return storeSkuBind
}
func GetMidPriceByNameID(db *DaoDB, cityCode, skuNameID int, snapDate time.Time) (midPrice int, err error) {
var (
sku []*model.SkuAndName
skuMap = make(map[int]int)
)
sql := `
SELECT a.mid_price price, a.sku_id id, b.spec_quality, c.unit, b.spec_unit
FROM price_refer_snapshot a
JOIN sku b ON a.sku_id = b.id
JOIN sku_name c ON c.id = b.name_id
WHERE c.id = ?
AND a.snapshot_at = ?
AND a.city_code = ?
`
sqlParams := []interface{}{
skuNameID,
snapDate,
cityCode,
}
err = GetRows(db, &sku, sql, sqlParams...)
if err != nil {
return 0, err
}
if len(sku) > 0 {
for _, v := range sku {
var (
price int
specQuality float64
)
if v.Unit == model.SpecialUnit {
if v.SpecUnit == model.SpecUnitNames[1] || v.SpecUnit == model.SpecUnitNames[2] {
specQuality = float64(v.SpecQuality) * 1000
} else {
specQuality = float64(v.SpecQuality)
}
price = int(utils.Float64TwoInt64(utils.Int2Float64(model.SpecialSpecQuality) / specQuality * utils.Int2Float64(v.Price)))
} else {
price = v.Price
}
if skuMap[skuNameID] < price {
skuMap[skuNameID] = price
}
}
}
return skuMap[skuNameID], err
}

View File

@@ -0,0 +1,30 @@
package dao
import (
"testing"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/globals"
)
func TestGetFullStoreSkus(t *testing.T) {
skuList, err := GetFullStoreSkus(GetDB(), model.VendorIDJD, 100118)
if err != nil {
t.Fatal(err)
}
globals.SugarLogger.Debug(utils.Format4Output(skuList, false))
}
func TestGetStoreSkus(t *testing.T) {
skuList, err := GetStoreSkus(GetDB(), model.VendorIDMTWM, 100134, nil)
if err != nil {
t.Fatal(err)
}
globals.SugarLogger.Debug(utils.Format4Output(skuList, false))
}
func TestGetDeletedStoreSkuBind(t *testing.T) {
storeSkuBind := GetDeletedStoreSkuBind(GetDB(), 100123, 30648)
globals.SugarLogger.Debug(utils.Format4Output(storeSkuBind, false))
}

View File

@@ -59,6 +59,7 @@ type GoodsOrder struct {
TotalShopMoney int64 `json:"totalShopMoney"` // 应结金额-第三方平台结算给京西的金额(包括了所有的补贴,扣除)
DiscountMoney int64 `json:"discountMoney"` // 订单总优惠金额
PmSubsidyMoney int64 `json:"pmSubsidyMoney"` // 平台活动补贴(订单主体活动补贴+订单单条sku补贴1+
BaseFreightMoney int64 `json:"baseFreightMoney"` // 商户承担的配送费不包括DistanceFreightMoney
DistanceFreightMoney int64 `json:"distanceFreightMoney"` // 商户承担的远距离配送费(当前只有京东到家有值)
WaybillTipMoney int64 `json:"waybillTipMoney"` // 京西加的平台配送小费
EarningPrice int64 `json:"earningPrice"` // 结算给门店老板的钱(未扣除可能的三方配送费)
@@ -76,7 +77,7 @@ type GoodsOrder struct {
GoodsCount int `json:"goodsCount"` // 商品个数
Status int `json:"status"` // 参见OrderStatus*相关的常量定义
VendorStatus string `orm:"size(255)" json:"vendorStatus"`
LockStatus int `json:"lockStatus"`
LockStatus int `json:"lockStatus"` // 当前只支持单一锁定
LockStatusTime time.Time `orm:"type(datetime);null" json:"lockStatusTime"` // last lock status time
OrderSeq int `json:"orderSeq"` // 门店订单序号
BuyerComment string `orm:"size(255)" json:"buyerComment"`
@@ -133,7 +134,7 @@ type OrderSku struct {
ID int64 `orm:"column(id)" json:"-"`
VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"`
VendorID int `orm:"column(vendor_id)" json:"vendorID"`
StoreSubID int `orm:"column(store_sub_id)" json:"storeSubID"` // 当前这个字段被当成结算活动ID用
StoreSubID int `orm:"column(store_sub_id)" json:"storeSubID"` // EarningActID当前这个字段被当成结算活动ID用
StoreSubName string `orm:"size(64)" json:"storeSubName"` // 当前这个字段被用作vendorActType
Count int `json:"count"`
VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"`
@@ -172,6 +173,7 @@ type Waybill struct {
VendorStatus string `orm:"size(255)" json:"-"`
ActualFee int64 `json:"actualFee"` // 实际要支付给快递公司的费用
DesiredFee int64 `json:"desiredFee"` // 运单总费用
TipFee int64 `json:"tipFee"` // 运单小费,不含在上两项中
DuplicatedCount int `json:"-"` // 重复新订单消息数这个一般不是由于消息重发造成的消息重发由OrderStatus过滤一般是业务逻辑造成的
DeliveryFlag int8 `json:"deliveryFlag"`
WaybillCreatedAt time.Time `orm:"type(datetime);index" json:"waybillCreatedAt"`
@@ -196,6 +198,12 @@ func (w *Waybill) TableIndex() [][]string {
}
}
type WaybillExt struct {
Waybill
Lng float64 `json:"lng"`
Lat float64 `json:"lat"`
}
// 包含订单与运单的状态及事件vendor status
type OrderStatus struct {
ID int64 `orm:"column(id)" json:"id"`
@@ -296,25 +304,26 @@ type OrderComment struct {
type OrderPay struct {
ModelIDCULD
VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"`
VendorID int `orm:"column(vendor_id)" json:"vendorID"`
PayType int `json:"payType"`
PayOrderID string `orm:"column(pay_order_id);size(48)" json:"payOrderID"` // 京西支付定单号
PayType int `json:"payType"`
VendorPayType string `orm:"size(48)" json:"vendorPayType"`
VendorOrderID string `orm:"column(vendor_order_id);size(48);index" json:"vendorOrderID"` // 支付对应的购物订单号
VendorID int `orm:"column(vendor_id)" json:"vendorID"` // 购物订单所属厂商代码(当前只有京西)
Status int `json:"status"`
PayCreatedAt time.Time `orm:"type(datetime);index" json:"payCreatedAt"`
PayFinishedAt *time.Time `orm:"type(datetime);null" json:"payFinishedAt"`
TotalFee int `json:"totalFee"`
TransactionID string `orm:"column(transaction_id);index;size(48)" json:"transactionID"`
PrepayID string `orm:"column(prepay_id);unique;size(48)" json:"prepayID"`
PrepayID string `orm:"column(prepay_id);index;size(48)" json:"prepayID"` // 下单后支付前支付方生成的事务ID
TransactionID string `orm:"column(transaction_id);index;size(48)" json:"transactionID"` // 支付成功后支付方生成的事务ID
CodeURL string `orm:"column(code_url);size(256)" json:"codeURL"`
PayOrderID string `orm:"column(pay_order_id);size(48)" json:"payOrderID"`
OriginalData string `orm:"type(text)" json:"-"`
}
func (v *OrderPay) TableIndex() [][]string {
return [][]string{
[]string{"VendorOrderID", "VendorID", "PayType", "DeletedAt"},
[]string{"PayOrderID", "PayType", "DeletedAt"},
}
}
@@ -322,12 +331,11 @@ type OrderPayRefund struct {
ModelIDCULD
RefundID string `orm:"column(refund_id);unique;size(48)" json:"refundID"`
VendorRefundID string `orm:"column(vendor_refund_id);unique;size(48)" json:"vendorRefundID"`
VendorRefundID string `orm:"column(vendor_refund_id);unique;size(48)" json:"vendorRefundID"` // 支付方退款成功后生成的退款单号
AfsOrderID string `orm:"column(afs_order_id);index;size(48)" json:"afsOrderID"` // AfsOrderID与RefundID的区别
VendorOrderID string `orm:"column(vendor_order_id);index;size(48)" json:"vendorOrderID"`
VendorID int `orm:"column(vendor_id)" json:"vendorID"`
TransactionID string `orm:"column(transaction_id);index;size(48)" json:"transactionID"`
TransactionID string `orm:"column(transaction_id);index;size(48)" json:"transactionID"` // 支付成功后支付方生成的事务ID
Status int `json:"status"`
RefundCreatedAt time.Time `orm:"type(datetime);index" json:"payCreatedAt"`
RefundFinishedAt *time.Time `orm:"type(datetime);null" json:"payFinishedAt"`
@@ -336,6 +344,11 @@ type OrderPayRefund struct {
OriginalData string `orm:"type(text)" json:"-"`
}
type OrderSupplementFee struct {
ModelIDCULD
VendorOrderID string `orm:"column(vendor_order_id);index;size(48)" json:"vendorOrderID"`
}
// 判断是否是购买平台自有物流
// 对于京东,饿百来说,就是其自有的物流,对于微商城来说,是达达
func IsWaybillPlatformOwn(bill *Waybill) bool {

View File

@@ -1,5 +1,7 @@
package model
import "time"
const (
SkuCategoryNormal = 0
SkuCategorySpecial = 1
@@ -166,8 +168,12 @@ func (*SkuCategory) TableIndex() [][]string {
type SkuName struct {
ModelIDCULD
Prefix string `orm:"size(255)" json:"prefix"`
Name string `orm:"size(255);index" json:"name"`
Prefix string `orm:"size(255)" json:"prefix"`
Name string `orm:"size(255)" json:"name"`
ExPrefix string `orm:"size(255)" json:"exPrefix"`
ExPrefixBegin *time.Time `orm:"null" json:"exPrefixBegin"`
ExPrefixEnd *time.Time `orm:"null" json:"exPrefixEnd"`
BrandID int `orm:"column(brand_id);default(0)" json:"brandID"` // todo此属性暂时没有使用且有问题应该是不同平台都有一个brandid
CategoryID int `orm:"column(category_id);index" json:"categoryID"` // 标准类别
@@ -187,9 +193,9 @@ type SkuName struct {
DescImg string `orm:"size(255)" json:"descImg"` // 商品详情图片描述
// DescImgEbai string `orm:"size(255)" json:"descImgEbai"` // 饿百的商品详情图片描述RTF
Upc string `orm:"size(20);index"`
Status int `orm:"default(1)" json:"status"` // skuname状态取值同sku.Status
IsSpu int8 `orm:"column(is_spu)" json:"isSpu"` // 用于指明是否SKUNAME当成SPU
Upc *string `orm:"size(20)"`
Status int `orm:"default(1)" json:"status"` // skuname状态取值同sku.Status
IsSpu int8 `orm:"column(is_spu)" json:"isSpu"` // 用于指明是否SKUNAME当成SPU
JdID int64 `orm:"column(jd_id);null;index" json:"jdID"`
JdSyncStatus int8 `orm:"default(2)" json:"jdSyncStatus"`
@@ -200,6 +206,13 @@ type SkuName struct {
func (*SkuName) TableUnique() [][]string {
return [][]string{
[]string{"Name", "Prefix", "SpecQuality", "SpecUnit", "Unit", "IsSpu", "DeletedAt"},
[]string{"Upc", "DeletedAt"},
}
}
func (*SkuName) TableIndex() [][]string {
return [][]string{
[]string{"ExPrefix", "ExPrefixBegin", "ExPrefixEnd", "DeletedAt"},
}
}
@@ -223,10 +236,14 @@ type Sku struct {
type SkuAndName struct {
Sku
Name string
Unit string
Prefix string
IsSpu int
Name string
Unit string
Prefix string
IsSpu int
ExPrefix string
ExPrefixBegin *time.Time
ExPrefixEnd *time.Time
Price int
}
func (*Sku) TableUnique() [][]string {
@@ -255,9 +272,9 @@ type SkuWithVendor struct {
type SkuNameExt struct {
SkuName
Skus []*SkuWithVendor `orm:"-" json:"skus"`
SkusStr string `json:"-"`
Places []int `orm:"-" json:"places"`
PlacesStr string `json:"-"`
Skus []*SkuWithVendor `orm:"-" json:"skus"`
SkusStr string `json:"-"`
FullName string `json:"fullName"`
Places []int `orm:"-" json:"places"`
PlacesStr string `json:"-"`
}

View File

@@ -49,6 +49,12 @@ const (
StoreChangePriceTypeManagedStore = 3 // 直营门店,禁止改价
)
const (
AutoReplyAll = 0 // 全部自动回复
AutoReplyGoodComment = 1 // 禁止差评自动回复
AutoReplyDisabled = 2 // 禁止自动回复
)
var (
StoreStatusName = map[int]string{
StoreStatusDisabled: "禁用",
@@ -240,6 +246,11 @@ var (
StoreChangePriceTypeBossDisabled: "普通门店禁止改价",
StoreChangePriceTypeManagedStore: "直营门店禁止改价",
}
AutoReplyTypeName = map[int]string{
AutoReplyAll: "全部自动回复",
AutoReplyGoodComment: "禁止差评自动回复",
AutoReplyDisabled: "禁止自动回复",
}
)
type Store struct {
@@ -264,6 +275,7 @@ type Store struct {
AutoEnableAt *time.Time `orm:"type(datetime);null" json:"autoEnableAt"` // 自动营业时间(临时休息用)
ChangePriceType int8 `json:"changePriceType"` // 修改价格类型,即是否需要审核
SMSNotify int8 `orm:"column(sms_notify);" json:"smsNotify"` // 是否通过短信接收订单消息
AutoReplyType int8 `json:"autoReplyType"` // 订单评价自动回复类型
PrinterDisabled int8 `orm:"default(0)" json:"printerDisabled"` // 是否禁用网络打印机
PrinterFontSize int8 `orm:"default(0)" json:"printerFontSize"` // 打印字体-10正常1
@@ -314,6 +326,7 @@ type Store struct {
OperatorPhone2 string `orm:"size(16)" json:"operatorPhone2"` // 非京东运营人电话
OperatorRole2 string `orm:"size(32)" json:"operatorRole2"` // 非京东运营人组(角色)
PromoteInfo string `orm:"size(255)" json:"promoteInfo"` //门店公告(所有平台统一的公告)
}
func (*Store) TableUnique() [][]string {
@@ -375,9 +388,10 @@ type StoreMap struct {
VendorID int `orm:"column(vendor_id)" json:"vendorID"`
VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空
VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"`
Status int `json:"status"` // 取值同Store.Status
StoreName string `orm:"size(255)" json:"storeName"` // 平台门店的名字
VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"`
Status int `json:"status"` // 取值同Store.Status
StoreName string `orm:"size(255)" json:"storeName"` // 平台门店的名字,由平台到京西
VendorStoreName string `orm:"size(255)" json:"vendorStoreName"` //平台门店名,由京西到平台
PricePercentage int16 `orm:"default(100)" json:"pricePercentage"` // todo 厂商价格相对于本地价格的百分比,这个字段的修改会比较特殊,因为可能需要刷新厂商价格
PricePercentagePack string `orm:"size(32)" json:"pricePercentagePack"` //
@@ -389,10 +403,11 @@ type StoreMap struct {
DeliveryFee int `json:"deliveryFee"`
DeliveryCompetition int8 `orm:"default(1)" json:"deliveryCompetition"` // 是否支持配送竞争
SyncStatus int8 `orm:"default(2)" json:"syncStatus"`
IsSync int8 `orm:"default(1)" json:"isSync"` // 是否同步
FakeOpenStart int16 `orm:"default(0)" json:"fakeOpenStart"` // 假开店开始
FakeOpenStop int16 `orm:"default(0)" json:"fakeOpenStop"` // 假开店结束
SyncStatus int8 `orm:"default(2)" json:"syncStatus"`
IsSync int8 `orm:"default(1)" json:"isSync"` // 是否同步
FakeOpenStart int16 `orm:"default(0)" json:"fakeOpenStart"` // 假开店开始
FakeOpenStop int16 `orm:"default(0)" json:"fakeOpenStop"` // 假开店结束
JdStoreLevel string `orm:"size(32)" json:"jdStoreLevel"` //京东门店等级
}
func (*StoreMap) TableUnique() [][]string {
@@ -522,6 +537,7 @@ type VendorStoreSnapshot struct {
DeliveryType int8 `orm:"default(0)" json:"deliveryType"` // 配送类型
StoreName string `orm:"size(255)" json:"storeName"` // 平台门店的名字
IsAutoOrder int8 `json:"isAutoOrder"` // 平台是否自动接单,-10未知1
JdStoreLevel string `orm:"size(32)" json:"jdStoreLevel"` //京东门店等级
}
func (*VendorStoreSnapshot) TableUnique() [][]string {

View File

@@ -94,22 +94,26 @@ type StoreSkuBind struct {
Status int
// ElmID int64 `orm:"column(elm_id);index"`
MtwmID int64 `orm:"column(mtwm_id);index"`
EbaiID int64 `orm:"column(ebai_id);index"`
MtwmID int64 `orm:"column(mtwm_id)"`
// WscID int64 `orm:"column(wsc_id);index"` // 表示微盟skuId
// WscID2 int64 `orm:"column(wsc_id2);index"` // 表示微盟goodsId
// ElmSyncStatus int8 `orm:"default(2)"`
JdSyncStatus int8 `orm:"default(2)"`
EbaiSyncStatus int8 `orm:"default(2)"`
MtwmSyncStatus int8 `orm:"default(2)"`
EbaiSyncStatus int8 `orm:"default(2)"`
// WscSyncStatus int8 `orm:"default(2)"`
JdPrice int `json:"jdPrice"`
EbaiPrice int `json:"ebaiPrice"`
MtwmPrice int `json:"mtwmPrice"`
EbaiPrice int `json:"ebaiPrice"`
JxPrice int `json:"jxPrice"`
// WscPrice int `json:"wscPrice"`
JdLockTime *time.Time `orm:"null" json:"jdLockTime"`
MtwmLockTime *time.Time `orm:"null" json:"mtwmLockTime"`
EbaiLockTime *time.Time `orm:"null" json:"ebaiLockTime"`
JxLockTime *time.Time `orm:"null" json:"jxLockTime"`
AutoSaleAt time.Time `orm:"type(datetime);null" json:"autoSaleAt"`

View File

@@ -69,16 +69,12 @@ func (c *DeliveryHandler) onWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaap
order := c.callbackMsg2Waybill(msg)
switch msg.OrderStatus {
case dadaapi.OrderStatusWaitingForAccept:
if result, err := api.DadaAPI.QueryOrderInfo(msg.OrderID); err == nil {
order.ActualFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["actualFee"], 0.0))
order.DesiredFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["deliveryFee"], 0.0))
if dadaOrder, err := api.DadaAPI.QueryOrderInfo2(msg.OrderID); err == nil {
order.ActualFee = jxutils.StandardPrice2Int(dadaOrder.ActualFee)
order.DesiredFee = jxutils.StandardPrice2Int(dadaOrder.DeliveryFee)
}
order.Status = model.WaybillStatusNew
case dadaapi.OrderStatusAccepted:
// if result, err := api.DadaAPI.QueryOrderInfo(msg.OrderID); err == nil {
// order.ActualFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["actualFee"], 0.0))
// order.DesiredFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["deliveryFee"], 0.0))
// }
order.Status = model.WaybillStatusAccepted
case dadaapi.OrderStatusDelivering:
order.Status = model.WaybillStatusDelivering
@@ -204,10 +200,12 @@ func (c *DeliveryHandler) IsErrStoreExist(err error) bool {
func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) {
db := dao.GetDB()
deliveryFeeInfo = &partner.WaybillFeeInfo{}
billParams, addParams, err := c.getBillParams(db, order)
// billParams, addParams, err := c.getBillParams(db, order)
billParams, err := c.getBillParams2(db, order)
if err == nil {
var result *dadaapi.CreateOrderResponse
if result, err = api.DadaAPI.QueryDeliverFee(billParams, addParams); err != nil {
// if result, err = api.DadaAPI.QueryDeliverFee(billParams, addParams); err != nil {
if result, err = api.DadaAPI.QueryDeliverFee2(billParams); err != nil {
return nil, err
}
deliveryFeeInfo.DeliveryFee = jxutils.StandardPrice2Int(result.Fee)
@@ -216,9 +214,34 @@ func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInf
return deliveryFeeInfo, err
}
func (c *DeliveryHandler) getBillParams(db *dao.DaoDB, order *model.GoodsOrder) (billParams *dadaapi.OperateOrderRequiredParams, addParams map[string]interface{}, err error) {
billParams = &dadaapi.OperateOrderRequiredParams{
// ShopNo: utils.Int2Str(order.StoreID), // 当前达达的门店号与京西是一样的
// func (c *DeliveryHandler) getBillParams(db *dao.DaoDB, order *model.GoodsOrder) (billParams *dadaapi.OperateOrderRequiredParams, addParams map[string]interface{}, err error) {
// billParams = &dadaapi.OperateOrderRequiredParams{
// // ShopNo: utils.Int2Str(order.StoreID), // 当前达达的门店号与京西是一样的
// OriginID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID),
// CargoPrice: jxutils.IntPrice2Standard(limitOrderPrice(order.ActualPayPrice)),
// IsPrepay: 0,
// ReceiverName: utils.FilterMb4(order.ConsigneeName),
// ReceiverAddress: utils.FilterMb4(order.ConsigneeAddress),
// ReceiverPhone: order.ConsigneeMobile,
// }
// if billParams.ShopNo, err = c.getDadaShopID(order, db); err == nil {
// if billParams.CityCode, err = c.getDataCityCodeFromOrder(order, db); err == nil {
// billParams.ReceiverLng, billParams.ReceiverLat, _ = jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
// addParams = map[string]interface{}{
// "info": fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, utils.FilterMb4(order.BuyerComment)),
// // "origin_mark": model.VendorNames[order.VendorID], // 订单来源标示该字段可以显示在达达app订单详情页面只支持字母最大长度为10
// // "origin_mark_no": fmt.Sprintf("%d", order.OrderSeq), // 订单来源编号该字段可以显示在达达app订单详情页面支持字母和数字最大长度为30
// "cargo_type": 13,
// "cargo_weight": jxutils.IntWeight2Float(limitOrderWeight(order.Weight)),
// "cargo_num": order.GoodsCount,
// }
// }
// }
// return billParams, addParams, err
// }
func (c *DeliveryHandler) getBillParams2(db *dao.DaoDB, order *model.GoodsOrder) (billParams *dadaapi.OperateOrderParams, err error) {
billParams = &dadaapi.OperateOrderParams{
OriginID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID),
CargoPrice: jxutils.IntPrice2Standard(limitOrderPrice(order.ActualPayPrice)),
IsPrepay: 0,
@@ -229,23 +252,20 @@ func (c *DeliveryHandler) getBillParams(db *dao.DaoDB, order *model.GoodsOrder)
if billParams.ShopNo, err = c.getDadaShopID(order, db); err == nil {
if billParams.CityCode, err = c.getDataCityCodeFromOrder(order, db); err == nil {
billParams.ReceiverLng, billParams.ReceiverLat, _ = jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
addParams = map[string]interface{}{
"info": fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, utils.FilterMb4(order.BuyerComment)),
// "origin_mark": model.VendorNames[order.VendorID], // 订单来源标示该字段可以显示在达达app订单详情页面只支持字母最大长度为10
// "origin_mark_no": fmt.Sprintf("%d", order.OrderSeq), // 订单来源编号该字段可以显示在达达app订单详情页面支持字母和数字最大长度为30
"cargo_type": 13,
"cargo_weight": jxutils.IntWeight2Float(limitOrderWeight(order.Weight)),
"cargo_num": order.GoodsCount,
}
billParams.Info = fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, utils.FilterMb4(order.BuyerComment))
billParams.CargoType = dadaapi.CargoTypeFresh
billParams.CargoWeight = float64(jxutils.IntWeight2Float(limitOrderWeight(order.Weight)))
billParams.CargoNum = order.GoodsCount
}
}
return billParams, addParams, err
return billParams, err
}
// IDeliveryPlatformHandler
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
db := dao.GetDB()
billParams, addParams, err := c.getBillParams(db, order)
// billParams, addParams, err := c.getBillParams(db, order)
billParams, err := c.getBillParams2(db, order)
if err == nil {
if globals.EnableStoreWrite {
// 达达要求第二次创建运单,调用函数不同。所以查找两天内有无相同订单号的运单
@@ -265,16 +285,19 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee
if err = delivery.CallCreateWaybillPolicy(waybillList[0].ActualFee, maxDeliveryFee, order, model.VendorIDDada); err != nil {
return nil, err
}
result, err = api.DadaAPI.ReaddOrder(billParams, addParams)
// result, err = api.DadaAPI.ReaddOrder(billParams, addParams)
result, err = api.DadaAPI.ReaddOrder2(billParams)
} else {
// 第一次创建
if err != nil {
globals.SugarLogger.Warnf("CreateWaybill orderID:%s error:%v", order.VendorOrderID, err)
}
if false {
result, err = api.DadaAPI.AddOrder(billParams, addParams)
// result, err = api.DadaAPI.AddOrder(billParams, addParams)
result, err = api.DadaAPI.AddOrder2(billParams)
} else {
if result, err = api.DadaAPI.QueryDeliverFee(billParams, addParams); err != nil {
// if result, err = api.DadaAPI.QueryDeliverFee(billParams, addParams); err != nil {
if result, err = api.DadaAPI.QueryDeliverFee2(billParams); err != nil {
return nil, err
}
if err = delivery.CallCreateWaybillPolicy(jxutils.StandardPrice2Int(result.Fee), maxDeliveryFee, order, model.VendorIDDada); err != nil {
@@ -363,3 +386,34 @@ func limitOrderWeight(weight int) int {
}
return weight
}
func (c *DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) {
if globals.EnableStoreWrite {
err = api.DadaAPI.ComplaintRider(bill.VendorOrderID, resonID)
}
return err
}
func (c *DeliveryHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
order, err := api.DadaAPI.QueryOrderInfo2(vendorOrderID)
if err == nil {
tipFee = jxutils.StandardPrice2Int(order.Tips)
}
return tipFee, err
}
func (c *DeliveryHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
if globals.EnableStoreWrite {
err = api.DadaAPI.AddTip(vendorOrderID, jxutils.IntPrice2Standard(tipFee), cityCode, "")
}
return err
}
func (c *DeliveryHandler) GetRidderPosition(ctx *jxcontext.Context, vendorOrgCode, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (lng, lat float64, err error) {
order, err := api.DadaAPI.QueryOrderInfo2(vendorOrderID)
if err == nil {
lng = utils.Str2Float64WithDefault(order.TransporterLng, 0)
lat = utils.Str2Float64WithDefault(order.TransporterLat, 0)
}
return lng, lat, err
}

View File

@@ -5,6 +5,7 @@ import (
"time"
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals/testinit"
@@ -18,15 +19,14 @@ func TestCreateWaybill(t *testing.T) {
orderID := "817540316000041"
if order, err := partner.CurOrderManager.LoadOrder(orderID, model.VendorIDJD); err == nil {
// globals.SugarLogger.Debug(order)
c := new(DeliveryHandler)
_, err = c.CreateWaybill(order, nil)
_, err = CurDeliveryHandler.CreateWaybill(order, 0)
if err == nil {
time.Sleep(1 * time.Second)
bill := &model.Waybill{
VendorOrderID: orderID,
WaybillVendorID: model.VendorIDDada,
}
err = c.CancelWaybill(bill, partner.CancelWaybillReasonOther, "")
err = CurDeliveryHandler.CancelWaybill(bill, partner.CancelWaybillReasonOther, "")
if err != nil {
t.Fatal(err.Error())
}
@@ -37,3 +37,11 @@ func TestCreateWaybill(t *testing.T) {
t.Fatal(err.Error())
}
}
func TestGetRidderPosition(t *testing.T) {
lng, lat, err := CurDeliveryHandler.GetRidderPosition(jxcontext.AdminCtx, "", "80704840263399812", "", "")
if err != nil {
t.Fatal(err)
}
t.Logf("lng:%f, lat:%f", lng, lat)
}

View File

@@ -8,6 +8,7 @@ import (
"git.rosy.net.cn/baseapi/platformapi/mtpsapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
@@ -173,14 +174,18 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee
item.GoodCount += goodItem.GoodCount
}
}
addParams := map[string]interface{}{
"note": utils.FilterMb4(order.BuyerComment),
"goods_detail": string(utils.MustMarshal(goods)),
"goods_pickup_info": fmt.Sprintf("%s第%d号单", model.VendorChineseNames[order.VendorID], order.OrderSeq),
"poi_seq": fmt.Sprintf("#%d", order.OrderSeq),
}
// addParams := map[string]interface{}{
// "note": utils.FilterMb4(order.BuyerComment),
// "goods_detail": string(utils.MustMarshal(goods)),
// "goods_pickup_info": fmt.Sprintf("%s第%d号单", model.VendorChineseNames[order.VendorID], order.OrderSeq),
// "poi_seq": fmt.Sprintf("#%d", order.OrderSeq),
// }
billParams.Note = utils.FilterMb4(order.BuyerComment)
billParams.GoodsDetail = string(utils.MustMarshal(goods))
billParams.GoodsPickupInfo = fmt.Sprintf("%s第%d号单", model.VendorChineseNames[order.VendorID], order.OrderSeq)
billParams.PoiSeq = fmt.Sprintf("#%d", order.OrderSeq)
if globals.EnableStoreWrite {
result, err2 := api.MtpsAPI.CreateOrderByShop(billParams, addParams)
result, err2 := api.MtpsAPI.CreateOrderByShop2(billParams)
if err = err2; err == nil {
bill = &model.Waybill{
VendorOrderID: order.VendorOrderID,
@@ -192,7 +197,7 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee
}
delivery.OnWaybillCreated(bill)
} else {
globals.SugarLogger.Debugf("CreateWaybill failed, orderID:%s, billParams:%v, addParams:%v, error:%v", order.VendorOrderID, billParams, addParams, err)
globals.SugarLogger.Debugf("CreateWaybill failed, orderID:%s, billParams:%v, error:%v", order.VendorOrderID, billParams, err)
}
} else {
err = fmt.Errorf("测试环境不能真正创建运单")
@@ -246,3 +251,19 @@ func limitOrderWeight(weight int) int {
}
return weight
}
func (c *DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) {
if globals.EnableStoreWrite {
err = api.MtpsAPI.EvaluateRider(utils.Str2Int64(bill.VendorWaybillID2), bill.VendorWaybillID, 1, resonContent)
}
return err
}
func (c *DeliveryHandler) GetRidderPosition(ctx *jxcontext.Context, vendorOrgCode, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (lng, lat float64, err error) {
intLng, intLat, err := api.MtpsAPI.RiderLocation(utils.Str2Int64(vendorWaybillID2), vendorWaybillID)
if err == nil {
lng = jxutils.IntCoordinate2Standard(intLng)
lat = jxutils.IntCoordinate2Standard(intLat)
}
return lng, lat, err
}

View File

@@ -109,7 +109,7 @@ type IOrderManager interface {
SaveOrderFinancialInfo(order *model.OrderFinancial, operation string) (err error)
SaveAfsOrderFinancialInfo(afsOrder *model.AfsOrder) (err error)
GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded bool) (bills []*model.Waybill, err error)
GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded, isGetPos bool) (bills []*model.WaybillExt, err error)
// afs order
OnAfsOrderAdjust(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error)
@@ -156,10 +156,10 @@ type IMultipleStoresHandler interface {
IPurchasePlatformHandler
GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*BareCategoryInfo, err error)
CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error)
UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error)
// CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error)
// UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
// DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
// ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error)
CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error)
UpdateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error)
@@ -167,9 +167,9 @@ type IMultipleStoresHandler interface {
ReorderCategories2(ctx *jxcontext.Context, vendorOrgCode, vendorParentCatID string, vendorCatIDList []string) (err error)
// sku
CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
// CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
// UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
// DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
// ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error)
CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error)
@@ -277,3 +277,23 @@ func IsMultiStore(vendorID int) bool {
}
return false
}
func GetRidderPositionGetter(vendorID int) (handler IRidderPositionGetter) {
if handlerInfo := GetDeliveryPlatformFromVendorID(vendorID); handlerInfo != nil {
if handler, _ = handlerInfo.Handler.(IRidderPositionGetter); handler != nil {
return handler
}
}
handler, _ = GetPurchasePlatformFromVendorID(vendorID).(IRidderPositionGetter)
return handler
}
func GetWaybillTipUpdater(vendorID int) (handler IAddWaybillTip) {
if handlerInfo := GetDeliveryPlatformFromVendorID(vendorID); handlerInfo != nil {
if handler, _ = handlerInfo.Handler.(IAddWaybillTip); handler != nil {
return handler
}
}
handler, _ = GetPurchasePlatformFromVendorID(vendorID).(IAddWaybillTip)
return handler
}

View File

@@ -38,6 +38,8 @@ type IDeliveryPlatformHandler interface {
CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error)
CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error)
GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *WaybillFeeInfo, err error)
//投诉骑手
ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error)
}
type IDeliveryUpdateStoreHandler interface {

View File

@@ -13,6 +13,7 @@ type OrderPhoneNumberInfo struct {
type IPurchasePlatformOrderHandler interface {
Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder)
GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error)
GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error)
GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams)
AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error)
@@ -57,6 +58,10 @@ type IPurchasePlatformOrderHandler interface {
}
type IAddWaybillTip interface {
GetWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder) (tipFee int64, err error)
AddWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee2Add int64) (err error)
GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error)
UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error)
}
type IRidderPositionGetter interface {
GetRidderPosition(ctx *jxcontext.Context, vendorOrgCode, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (lng, lat float64, err error)
}

View File

@@ -0,0 +1,51 @@
package pay
import (
"time"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
)
type PayOpStatus int
const (
OpStatusFailed PayOpStatus = 0
OpStatusSuccessed PayOpStatus = 1
)
type CreatePayParam struct {
PayOrderID string
VendorPayType string
VendorOrderID string
ProductDesc string
ProductDetail string
FeeType string
TotalFee int
TimeStart time.Time
TimeExpire time.Time
UserData string
}
type PayOpResult struct {
Status PayOpStatus
VendorStatus string
ErrMsg string
ID string
VendorID string
OriginalData string
}
type ResponseHandler interface {
OnCreatePay(vendorID int, result *PayOpResult) (err error)
OnRefundPay(vendorID int, result *PayOpResult) (err error)
}
type IPayPlatformHandler interface {
CreatePay(ctx *jxcontext.Context, param *CreatePayParam, isOffline bool) (prepayID, qrCodeURL string, err error)
ClosePay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID string) (err error)
RefundPay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID, refundID, reason string, totalFee, refundFee int) (vendorRefundID string, err error)
}

View File

@@ -0,0 +1,60 @@
package wxpay
import (
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/partner/pay"
"git.rosy.net.cn/jx-callback/globals"
)
func OnCallback(msg *wxpayapi.CallbackMsg) (err error) {
globals.SugarLogger.Debugf("wxpay OnCallback msg:%s", utils.Format4Output(msg, true))
switch msg.MsgType {
case wxpayapi.MsgTypePay:
err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg))
case wxpayapi.MsgTypeRefund:
err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg))
}
return err
}
func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) {
opResult := &pay.PayOpResult{
OriginalData: string(utils.MustMarshal(msg)),
}
if msg.ReturnCode == wxpayapi.ResponseCodeSuccess {
opResult.Status = pay.OpStatusSuccessed
opResult.ID = msg.OutTradeNo
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
opResult.VendorID = msg.TransactionID
} else {
opResult.VendorStatus = msg.ErrCode
opResult.ErrMsg = msg.ErrCodeDes
}
} else {
opResult.Status = pay.OpStatusFailed
}
err = payHandler.responseHandler.OnCreatePay(model.VendorIDWXPay, opResult)
return err
}
func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) {
opResult := &pay.PayOpResult{
OriginalData: string(utils.MustMarshal(msg)),
}
if msg.ReturnCode == wxpayapi.ResponseCodeSuccess {
opResult.Status = pay.OpStatusSuccessed
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
opResult.ID = msg.ReqInfoObj.OutRefundNo
opResult.VendorID = msg.ReqInfoObj.RefundID
} else {
opResult.VendorStatus = msg.ErrCode
opResult.ErrMsg = msg.ErrCodeDes
}
} else {
opResult.Status = pay.OpStatusFailed
}
err = payHandler.responseHandler.OnRefundPay(model.VendorIDWXPay, opResult)
return err
}

View File

@@ -0,0 +1,73 @@
package wxpay
import (
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/partner/pay"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
)
type PayHandler struct {
responseHandler pay.ResponseHandler
}
var (
payHandler *PayHandler
)
func New(responseHandler pay.ResponseHandler) (handler *PayHandler) {
return &PayHandler{
responseHandler: responseHandler,
}
}
func vendorPayType2WxpayType(vendorPayType string) string {
return vendorPayType
}
func (p *PayHandler) CreatePay(ctx *jxcontext.Context, createParam *pay.CreatePayParam, isOffline bool) (prepayID, qrCodeURL string, err error) {
param := &wxpayapi.CreateOrderParam{
OutTradeNo: createParam.PayOrderID,
Body: createParam.ProductDesc,
NotifyURL: globals.WxpayNotifyURL,
SpbillCreateIP: ctx.GetRealRemoteIP(),
TradeType: vendorPayType2WxpayType(createParam.VendorPayType),
TotalFee: createParam.TotalFee,
TimeStart: wxpayapi.Time2PayTime(createParam.TimeStart),
TimeExpire: wxpayapi.Time2PayTime(createParam.TimeExpire),
}
if isOffline {
param.TradeType = wxpayapi.TradeTypeNative
}
if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini {
param.OpenID = authInfo.GetAuthID()
}
if result, err := api.WxpayAPI.CreateUnifiedOrder(param); err == nil {
prepayID = result.PrepayID
qrCodeURL = result.CodeURL
}
return prepayID, qrCodeURL, err
}
func (p *PayHandler) ClosePay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID string) (err error) {
return api.WxpayAPI.CloseOrder(payOrderID)
}
func (p *PayHandler) RefundPay(ctx *jxcontext.Context, payOrderID, vendorPayOrderID, refundID, reason string, totalFee, refundFee int) (vendorRefundID string, err error) {
param := &wxpayapi.PayRefundParam{
OutTradeNo: payOrderID,
NotifyURL: globals.WxpayNotifyURL,
OutRefundNo: refundID,
TotalFee: totalFee,
RefundFee: refundFee,
RefundDesc: wxpayapi.CData(reason),
}
retVal, err := api.WxpayAPI.PayRefund(param)
if err == nil {
vendorRefundID = retVal.RefundID
}
return vendorRefundID, err
}

View File

@@ -57,11 +57,11 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
<B>%s</B><BR>
<BR>
<BOLD>实际支付:</BOLD>%s<BR>
<BR>
商品明细: <BR>
品名 数量 单价 小计<BR>
--------------------------------<BR>`
// <BOLD>实际支付:</BOLD>%s<BR>
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -74,7 +74,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
order.ConsigneeMobile,
order.ConsigneeAddress,
order.BuyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {
@@ -131,11 +131,11 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
<B>%s</B><BR>
<BR>
<B><BOLD>实际支付:</BOLD></B><B>%s<BR></B>
<BR>
<B>商品明细: <BR></B>
<B>品名数量单价小计<BR></B>
--------------------------------<BR>`
// <B><BOLD>实际支付:</BOLD></B><B>%s<BR></B>
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -148,7 +148,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
order.ConsigneeMobile,
order.ConsigneeAddress,
order.BuyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {

View File

@@ -59,11 +59,11 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
*
客户备注: *
<big>%s*
<S011>实际支付: %s*
商品明细: *
品名 数量 单价 小计
--------------------------------*
`
// <S011>实际支付: %s*
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -76,7 +76,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
order.ConsigneeMobile,
order.ConsigneeAddress,
buyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {
orderFmt += `%s*`
@@ -128,17 +128,17 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
<big>%s\#%d*
<qrcA4>%s*
` + getCode +
`<big>客户: %s*
`<big>客户: %s*
<big>电话: %s*
<big>地址: %s*
*
<big>客户备注: *
<big>%s*
<big>实际支付: %s*
<big>商品明细: *
<big>品名数量单价小计*
--------------------------------*
`
// <big>实际支付: %s*
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -151,7 +151,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
order.ConsigneeMobile,
order.ConsigneeAddress,
buyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {
orderFmt += `<big>%s*`
@@ -209,12 +209,12 @@ func (c *PrinterHandler) getOrderContent2(order *model.GoodsOrder, storeTel stri
|5客户备注:
|7%s
|5
|6实际支付: %s
|5
|5商品明细:
|5品名 数量 单价 小计
|5--------------------------------
`
// |6实际支付: %s
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -227,7 +227,7 @@ func (c *PrinterHandler) getOrderContent2(order *model.GoodsOrder, storeTel stri
order.ConsigneeMobile,
order.ConsigneeAddress,
buyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {
orderFmt += `|5%s`

View File

@@ -55,11 +55,11 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
客户备注: \n
<FS2>%s</FS2>\n
\n
<FB>实际支付:</FB>%s\n
\n
商品明细: \n
品名 数量 单价 小计\n
--------------------------------\n`
// <FB>实际支付:</FB>%s\n
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -72,7 +72,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
order.ConsigneeMobile,
order.ConsigneeAddress,
order.BuyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {
@@ -123,11 +123,11 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
<FS2>客户备注: \n</FS2>
<FS2>%s</FS2>\n
\n
<FS2><FB>实际支付:</FB>%s\n</FS2>
\n
<FS2>商品明细: \n</FS2>
<FS2>品名数量单价小计\n</FS2>
--------------------------------\n`
// <FS2><FB>实际支付:</FB>%s\n</FS2>
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -140,7 +140,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
order.ConsigneeMobile,
order.ConsigneeAddress,
order.BuyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {

View File

@@ -56,11 +56,11 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
客户备注: <RN>
<S2>%s</S2><RN>
<RN>
<B1>实际支付:</B1>%s<RN>
<RN>
商品明细: <RN>
品名 数量 单价 小计<RN>
********************************<RN>`
// <B1>实际支付:</B1>%s<RN>
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -73,7 +73,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin
order.ConsigneeMobile,
order.ConsigneeAddress,
order.BuyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {
@@ -124,11 +124,11 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
<S2>客户备注: <RN></S2>
<S2>%s</S2><RN>
<RN>
<S2><B1>实际支付:</B1>%s<RN></S2>
<RN>
<S2>商品明细: <RN></S2>
<S2>品名数量单价小计<RN></S2>
********************************<RN>`
// <S2><B1>实际支付:</B1>%s<RN></S2>
orderParams := []interface{}{
globals.StoreName,
utils.Time2Str(order.OrderCreatedAt),
@@ -141,7 +141,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st
order.ConsigneeMobile,
order.ConsigneeAddress,
order.BuyerComment,
jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
// jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice),
}
for _, sku := range order.Skus {

View File

@@ -5,9 +5,11 @@ import (
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/globals"
)
func OnCallbackMsg(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) {
globals.SugarLogger.Debugf("ebai OnCallbackMsg msg:%s", utils.Format4Output(msg, true))
if CurPurchaseHandler != nil {
if orderID := GetOrderIDFromMsg(msg); orderID != "" {
jxutils.CallMsgHandler(func() {

View File

@@ -28,8 +28,6 @@ const (
callDeliveryDelay = 10 * time.Minute
callDeliveryDelayGap = 30
fakeUserApplyCancel = "fake_user_apply_cancel"
fakeUserUndoApplyCancel = "fake_user_undo_apply_cancel"
fakeAcceptOrder = "fake_accept_order"
fakeOrderAdjustFinished = "fake_order_adjust_finished"
fakeOrderCanceled = "fake_order_canceled"
@@ -49,8 +47,6 @@ var (
ebaiapi.OrderStatusCanceled: model.OrderStatusCanceled,
fakeOrderAdjustFinished: model.OrderStatusAdjust,
fakeUserApplyCancel: model.OrderStatusApplyCancel,
fakeUserUndoApplyCancel: model.OrderStatusUndoApplyCancel,
fakeOrderCanceled: model.OrderStatusCanceled,
}
@@ -83,6 +79,14 @@ func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *
return order, err
}
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
status, err = api.EbaiAPI.OrderStatusGet(vendorOrderID)
if err == nil {
status = p.getStatusFromVendorStatus(utils.Int2Str(status))
}
return status, err
}
func (p *PurchaseHandler) getOrder(vendorOrderID string) (order *model.GoodsOrder, orderMap map[string]interface{}, err error) {
result, err := api.EbaiAPI.OrderGet(vendorOrderID)
if err == nil {
@@ -202,6 +206,7 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
OrderCreatedAt: getTimeFromInterface(orderMap["create_time"]),
OriginalData: string(utils.MustMarshal(result)),
ActualPayPrice: utils.ForceInterface2Int64(orderMap["user_fee"]),
BaseFreightMoney: utils.ForceInterface2Int64(orderMap["send_fee"]),
TotalShopMoney: utils.ForceInterface2Int64(orderMap["shop_fee"]),
DeliveryType: mapDeliveryType(int(utils.ForceInterface2Int64(orderMap["delivery_party"]))),
@@ -404,7 +409,7 @@ func (p *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName
//
func (c *PurchaseHandler) onOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
if c.isAfsMsg(msg) {
retVal = c.OnAfsOrderMsg(msg)
retVal = c.onAfsOrderMsg(msg)
} else {
status := c.callbackMsg2Status(msg)
if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 {
@@ -424,7 +429,7 @@ func (c *PurchaseHandler) onOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.
// 处理饿百降级订单的情况
// 是否降级;1:是,0:否;极少数订单因网络或信息交互异常,导致订单部分字段(如订单金额)生成延迟,此时订单会被标记为“已降级”状态,需开发者重新调用查看订单详情接口获取完整订单数据。
// toto sku是否也需要处理
if status.Status == model.OrderStatusFinished {
if status.Status == model.OrderStatusDelivering || status.Status == model.OrderStatusFinished {
if order, err2 := partner.CurOrderManager.LoadOrder(status.VendorOrderID, status.VendorID); err2 == nil {
if order.TotalShopMoney == 0 {
if order2, err2 := c.GetOrder(msg.Source, status.VendorOrderID); err2 == nil {
@@ -478,11 +483,15 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *ebaiapi.CallbackMsg) (orderSta
if cancelType == ebaiapi.OrderUserCancelTypeBeforeSale {
if msgType == ebaiapi.OrderUserCancelApply ||
msgType == ebaiapi.OrderUserCancelCSIntervene {
orderStatus.VendorStatus = fakeUserApplyCancel
} else if msgType == ebaiapi.OrderUserCancelInvalid ||
msgType == ebaiapi.OrderUserCancelMerchantRefused ||
msgType == ebaiapi.OrderUserCancelCSRefused {
orderStatus.VendorStatus = fakeUserUndoApplyCancel
orderStatus.Status = model.OrderStatusApplyCancel
} else if msgType == ebaiapi.OrderUserCancelCSRefused ||
msgType == ebaiapi.OrderUserCancelMerchantRefused {
orderStatus.Status = model.OrderStatusVendorRejectCancel
} else if msgType == ebaiapi.OrderUserCancelInvalid {
orderStatus.Status = model.OrderStatusUndoApplyCancel
} else if msgType == ebaiapi.OrderUserCancelCSAgreed ||
msgType == ebaiapi.OrderUserCancelMerchantAgreed {
orderStatus.Status = model.OrderStatusVendorAgreeCancel
}
}
} else if msg.Cmd == ebaiapi.CmdOrderPartRefund {
@@ -500,7 +509,9 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *ebaiapi.CallbackMsg) (orderSta
}
orderStatus.Remark = utils.Interface2String(msg.Body["reason"])
}
orderStatus.Status = c.getStatusFromVendorStatus(orderStatus.VendorStatus)
if orderStatus.Status == 0 {
orderStatus.Status = c.getStatusFromVendorStatus(orderStatus.VendorStatus)
}
return orderStatus
}
@@ -649,3 +660,20 @@ func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode strin
}
return vendorOrderIDs, err
}
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
orderInfo, err := api.EbaiAPI.GetStoreOrderInfo(vendorOrderID)
if err == nil {
if orderBasic, _ := orderInfo["order_basic"].(map[string]interface{}); orderBasic != nil {
tipFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(orderBasic["delivery_tip_amount"], 0))
}
}
return tipFee, err
}
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
if globals.EnableEbaiStoreWrite {
err = api.EbaiAPI.ModifyTip4OrderWaybill(vendorOrderID, "", jxutils.IntPrice2Standard(tipFee), 0)
}
return err
}

View File

@@ -102,7 +102,7 @@ func (c *PurchaseHandler) onAfsOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaia
afsOrder.Skus = append(afsOrder.Skus, orderSku)
}
} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
if afsOrder := c.createAfsOrder(msg); afsOrder != nil {
if afsOrder = c.createAfsOrder(msg); afsOrder != nil {
// if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDEBAI); err2 == nil {
// afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg)
cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)

View File

@@ -30,9 +30,10 @@ type tEbaiStoreInfo struct {
EbaiStoreStatus int
SyncStatus int
ProvinceID int `orm:"column(province_id)"`
CityID int `orm:"column(city_id)"`
DistrictID int `orm:"column(district_id)"`
ProvinceID int `orm:"column(province_id)"`
CityID int `orm:"column(city_id)"`
DistrictID int `orm:"column(district_id)"`
VendorStoreName string
}
func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) {
@@ -156,7 +157,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
SELECT
t1.*,
t2.status ebai_store_status, t2.vendor_store_id, t2.vendor_org_code,
IF(t1.updated_at > t2.updated_at, t1.last_operator, t2.last_operator) real_last_operator, t2.sync_status
IF(t1.updated_at > t2.updated_at, t1.last_operator, t2.last_operator) real_last_operator, t2.sync_status, t2.vendor_store_name
FROM store t1
JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND (t2.deleted_at = ?)
WHERE t1.id = ?
@@ -193,6 +194,9 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
}
params := genStoreMapFromStore(store)
if err = api.EbaiAPI.ShopUpdate(params); err == nil {
if store.PromoteInfo != "" {
err = api.EbaiAPI.ShopAnnouncementSet("", utils.Str2Int64(store.VendorStoreID), store.PromoteInfo)
}
}
}
}
@@ -389,8 +393,12 @@ func genStoreMapFromStore(store *tEbaiStoreInfo) map[string]interface{} {
if store.VendorStoreID != "" {
params["baidu_shop_id"] = store.VendorStoreID
}
if store.SyncStatus&(model.SyncFlagNewMask /*|model.SyncFlagStoreName*/) != 0 {
params["name"] = jxutils.ComposeStoreName(store.Name, model.VendorIDEBAI)
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
if store.VendorStoreName != "" {
params["name"] = store.VendorStoreName
} else {
params["name"] = jxutils.ComposeStoreName(store.Name, model.VendorIDEBAI)
}
}
params["address"] = store.Address
// todo 饿百 开店审核通过后不允许修改商户信息

View File

@@ -113,7 +113,7 @@ func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) {
return ebaiapi.IsErrSkuNotExist(err)
}
func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
func (p *PurchaseHandler) updateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isNeedMapCat bool) (failedList []*partner.StoreSkuInfoWithErr, err error) {
storeSku := storeSkuList[0]
strStoreID := utils.Int2Str(storeID)
params := genSkuParamsFromStoreSkuInfo2(storeSku, false)
@@ -122,13 +122,19 @@ func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, v
if err != nil {
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "更新商品基础信息")
}
utils.CallFuncAsync(func() {
api.EbaiAPI.SkuShopCategoryMap(strStoreID, utils.Str2Int64(storeSku.VendorSkuID), "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku))
})
if isNeedMapCat {
utils.CallFuncAsync(func() {
api.EbaiAPI.SkuShopCategoryMap(strStoreID, utils.Str2Int64(storeSku.VendorSkuID), "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku))
})
}
}
return failedList, err
}
func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
return p.updateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true)
}
// 对于多门店平台来说storeSkuList中只有SkuID与VendorSkuID有意义
func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
storeSku := storeSkuList[0]
@@ -139,6 +145,9 @@ func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, v
if vendorSkuID, err = api.EbaiAPI.SkuCreate(ctx.GetTrackInfo(), strStoreID, storeSku.SkuID, params); err == nil {
utils.AfterFuncWithRecover(5*time.Second, func() {
api.EbaiAPI.SkuShopCategoryMap(strStoreID, vendorSkuID, "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku))
// 饿百平台有BUG会导致新建一个之前删除的商品时信息不会及时更新强制刷新一下
// 比如门店100887, skuID33805订单1577176719141226065
p.updateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false)
})
} else {
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "创建商品")
@@ -321,7 +330,7 @@ func jxCatSeq2Ebai(seq int) int {
}
func formatCatName(name string) string {
return name
return utils.LimitUTF8StringLen(name, ebaiapi.MaxCategoryNameLen)
}
func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) {

View File

@@ -120,7 +120,7 @@ func (c *PurchaseHandler) onOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancel
default:
status.Status = model.OrderStatusUnknown
}
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnOrderStatusChanged(status), status.VendorStatus)
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnOrderStatusChanged("", status), status.VendorStatus)
}
func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) {
@@ -223,7 +223,7 @@ func (c *PurchaseHandler) onOrderUserUrgeOrder(msg *elmapi.CallbackOrderUrgeMsg)
StatusTime: utils.Timestamp2Time(msg.UpdateTime),
}
c.ClientUrgeOrder(msg.OrderID)
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnOrderStatusChanged(status), status.VendorStatus)
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnOrderStatusChanged("", status), status.VendorStatus)
}
func (c *PurchaseHandler) stateAndType2Str(state string, msgType int) string {

View File

@@ -325,7 +325,7 @@ func (c *PurchaseHandler) onActMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.C
if _, ok := actMap.Load(intPromotionID); !ok {
utils.CallFuncAsync(func() {
if !partner.CurActManager.IsVendorActExist(jxcontext.AdminCtx, promotionID, model.VendorIDJD) {
act, actStoreSkuList, err := getActFromJD(appKey2OrgCode(msg.AppKey), promotionID)
act, actStoreSkuList, err := getActFromJD(AppKey2OrgCode(msg.AppKey), promotionID)
if err == nil && len(actStoreSkuList) > 0 {
_, err = partner.CurActManager.CreateActFromVendor(jxcontext.AdminCtx, act, actStoreSkuList)
}

View File

@@ -6,21 +6,21 @@ import (
func OnOrderMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
if CurPurchaseHandler != nil {
retVal = CurPurchaseHandler.OnOrderMsg(appKey2OrgCode(msg.AppKey), msg)
retVal = CurPurchaseHandler.OnOrderMsg(AppKey2OrgCode(msg.AppKey), msg)
}
return retVal
}
func OnWaybillMsg(msg *jdapi.CallbackDeliveryStatusMsg) (retVal *jdapi.CallbackResponse) {
if CurPurchaseHandler != nil {
retVal = CurPurchaseHandler.OnWaybillMsg(appKey2OrgCode(msg.AppKey), msg)
retVal = CurPurchaseHandler.OnWaybillMsg(AppKey2OrgCode(msg.AppKey), msg)
}
return retVal
}
func OnStoreMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
if CurPurchaseHandler != nil {
retVal = CurPurchaseHandler.OnStoreMsg(appKey2OrgCode(msg.AppKey), msg)
retVal = CurPurchaseHandler.OnStoreMsg(AppKey2OrgCode(msg.AppKey), msg)
}
return retVal
}

View File

@@ -18,7 +18,7 @@ func (p *PurchaseHandler) OnFinancialMsg(msg *jdapi.CallbackOrderMsg) (retVal *j
// 京东正向/退款订单类型处理--存储
func (p *PurchaseHandler) onFinancialMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
var err error
a := GetAPIByAppKey(msg.AppKey)
a := getAPI(AppKey2OrgCode(msg.AppKey))
// if msg.StatusID == jdapi.OrderStatusPayFinishedSettle || msg.StatusID == jdapi.OrderStatusTipChanged || msg.StatusID == jdapi.OrderStatusSwitch2SelfSettle { // 如果是正向单
if msg.StatusID == jdapi.OrderStatusPayFinishedSettle || msg.StatusID == jdapi.OrderStatusTipChanged || msg.StatusID == jdapi.OrderStatusAdjustSettle || msg.StatusID == jdapi.OrderStatusSwitch2SelfSettle { // 如果是正向单
order, err2 := partner.CurOrderManager.LoadOrder(msg.BillID, model.VendorIDJD)

View File

@@ -23,6 +23,9 @@ func init() {
}
func getAPI(appOrgCode string) (apiObj *jdapi.API) {
if appOrgCode == "" {
globals.SugarLogger.Warnf("getAPI appOrgCode is empty")
}
return partner.CurAPIManager.GetAPI(model.VendorIDJD, appOrgCode).(*jdapi.API)
}
@@ -30,7 +33,7 @@ func GetAPI(appOrgCode string) (apiObj *jdapi.API) {
return getAPI(appOrgCode)
}
func appKey2OrgCode(appKey string) (vendorOrgCode string) {
func AppKey2OrgCode(appKey string) (vendorOrgCode string) {
apiList := partner.CurAPIManager.GetAppOrgCodeList(model.VendorIDJD)
for _, v := range apiList {
jdAPI := partner.CurAPIManager.GetAPI(model.VendorIDJD, v).(*jdapi.API)
@@ -39,23 +42,10 @@ func appKey2OrgCode(appKey string) (vendorOrgCode string) {
break
}
}
return vendorOrgCode
}
func GetAPIByAppKey(appKey string) (apiObj *jdapi.API) {
if appKey == "" {
apiObj = getAPI("")
} else {
apiList := partner.CurAPIManager.GetAppOrgCodeList(model.VendorIDJD)
for _, v := range apiList {
jdAPI := partner.CurAPIManager.GetAPI(model.VendorIDJD, v).(*jdapi.API)
if jdAPI.GetAppKey() == appKey {
apiObj = jdAPI
break
}
}
if vendorOrgCode == "" {
globals.SugarLogger.Warnf("AppKey2OrgCode appKey:%s get empty vendorOrgCode", appKey)
}
return apiObj
return vendorOrgCode
}
func (c *PurchaseHandler) GetVendorID() int {

View File

@@ -27,13 +27,17 @@ var (
jdapi.OrderStatusFinishedPickup: model.OrderStatusFinishedPickup,
jdapi.OrderStatusDelivering: model.OrderStatusDelivering,
jdapi.OrderStatusDelivered: model.OrderStatusFinished,
// jdapi.OrderStatusFinished: model.OrderStatusFinished, // todo 这个状态不是真正都完成的意思
jdapi.OrderStatusCanceled: model.OrderStatusCanceled,
jdapi.OrderStatusFinished: model.OrderStatusFinished, // todo 这个状态不是真正都完成的意思?
jdapi.OrderStatusCanceled: model.OrderStatusCanceled,
jdapi.OrderStatusAdjust: model.OrderStatusAdjust,
jdapi.OrderStatusUserApplyCancel: model.OrderStatusApplyCancel,
jdapi.OrderStatusLocked: model.OrderStatusLocked,
jdapi.OrderStatusUnlocked: model.OrderStatusUnlocked,
jdapi.OrderStatusVenderAgreeCancel: model.OrderStatusVendorAgreeCancel,
jdapi.OrderStatusVenderRejectCancel: model.OrderStatusVendorRejectCancel,
jdapi.CallbackMsgOrderAddTips: model.OrderStatusWaybillTipChanged,
}
deliveryTypeMap = map[int]string{
jdapi.CarrierNoCrowdSourcing: model.OrderDeliveryTypePlatform,
@@ -93,9 +97,6 @@ func (c *PurchaseHandler) onOrderMsg(vendorOrgCode string, msg *jdapi.CallbackOr
})
}
err := partner.CurOrderManager.OnOrderStatusChanged(vendorOrgCode, status)
// if globals.HandleLegacyJxOrder && err == nil {
// c.legacyJdOrderStatusChanged(status)
// }
retVal = jdapi.Err2CallbackResponse(err, status.VendorStatus)
}
}
@@ -147,6 +148,14 @@ func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.
return order, err
}
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
order, err := getAPI(vendorOrgCode).QuerySingleOrder2(vendorOrderID)
if err == nil {
status = p.getStatusFromVendorStatus(utils.Int2Str(order.OrderStatus))
}
return status, err
}
func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
result := orderData
orderID := utils.Int64ToStr(utils.MustInterface2Int64(result["orderId"]))
@@ -177,6 +186,7 @@ func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
OrderCreatedAt: utils.Str2Time(result[statusTimeField].(string)),
OriginalData: string(utils.MustMarshal(result)),
ActualPayPrice: utils.MustInterface2Int64(result["orderBuyerPayableMoney"]),
BaseFreightMoney: utils.Interface2Int64WithDefault(result["orderBaseFreightMoney"], 0),
DistanceFreightMoney: utils.Interface2Int64WithDefault(result["merchantPaymentDistanceFreightMoney"], 0),
DeliveryType: deliveryTypeMap[int(utils.Str2Int64WithDefault(utils.Interface2String(result["deliveryCarrierNo"]), 0))],
VendorOrgCode: utils.Interface2String(result["orgCode"]),
@@ -277,19 +287,24 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *jdapi.CallbackOrderMsg) *model
RefVendorOrderID: msg.BillID,
RefVendorID: model.VendorIDJD,
VendorStatus: msg.StatusID,
Status: c.getStatusFromVendorStatus(msg.StatusID),
StatusTime: utils.Str2Time(msg.Timestamp),
Remark: msg.Remark,
}
if msg.MsgURL == jdapi.CallbackMsgOrderAddTips {
orderStatus.VendorStatus = jdapi.CallbackMsgOrderAddTips
}
orderStatus.Status = c.getStatusFromVendorStatus(orderStatus.VendorStatus)
return orderStatus
}
func (c *PurchaseHandler) postFakeMsg(vendorOrderID, vendorStatus string) {
func (c *PurchaseHandler) postFakeMsg(vendorOrgCode, vendorOrderID, vendorStatus string) {
msg := &jdapi.CallbackOrderMsg{
CallbackMsg: &jdapi.CallbackMsg{},
BillID: vendorOrderID,
StatusID: vendorStatus,
Timestamp: utils.Time2Str(time.Now()),
CallbackMsg: &jdapi.CallbackMsg{
AppKey: getAPI(vendorOrgCode).GetAppKey(),
},
BillID: vendorOrderID,
StatusID: vendorStatus,
Timestamp: utils.Time2Str(time.Now()),
}
utils.CallFuncAsync(func() {
OnOrderMsg(msg)
@@ -309,14 +324,14 @@ func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI
if globals.EnableJdStoreWrite {
err = getAPI(order.VendorOrgCode).OrderAcceptOperate(order.VendorOrderID, isAcceptIt, userName)
if isAcceptIt && err == nil {
c.postFakeMsg(order.VendorOrderID, jdapi.StatusIDWaitOutStore)
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.StatusIDWaitOutStore)
}
} else {
if isAcceptIt {
c.postFakeMsg(order.VendorOrderID, jdapi.StatusIDWaitOutStore)
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.StatusIDWaitOutStore)
} else {
c.postFakeMsg(order.VendorOrderID, jdapi.OrderStatusCanceled)
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.OrderStatusCanceled)
}
}
return err
@@ -327,7 +342,7 @@ func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bo
if !isSelfDelivery && globals.EnableJdStoreWrite {
_, err = getAPI(order.VendorOrgCode).OrderJDZBDelivery(order.VendorOrderID, userName)
} else {
c.postFakeMsg(order.VendorOrderID, jdapi.OrderStatusFinishedPickup)
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.OrderStatusFinishedPickup)
}
return err
}
@@ -426,11 +441,18 @@ func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.Goods
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
order = jxutils.RemoveSkuFromOrder(order, removedSkuList)
var oaosAdjustDTOList []*jdapi.OAOSAdjustDTO
dtoMap := make(map[int]*jdapi.OAOSAdjustDTO)
for _, sku := range order.Skus {
oaosAdjustDTOList = append(oaosAdjustDTOList, &jdapi.OAOSAdjustDTO{
OutSkuID: utils.Int2Str(jxutils.GetSkuIDFromOrderSku(sku)),
SkuCount: sku.Count,
})
skuID := jxutils.GetSkuIDFromOrderSku(sku)
if dtoMap[skuID] == nil {
dtoMap[skuID] = &jdapi.OAOSAdjustDTO{
OutSkuID: utils.Int2Str(skuID),
SkuCount: sku.Count,
}
oaosAdjustDTOList = append(oaosAdjustDTOList, dtoMap[skuID])
} else {
dtoMap[skuID].SkuCount += sku.Count
}
}
if globals.EnableJdStoreWrite {
err = getAPI(order.VendorOrgCode).AdjustOrder(order.VendorOrderID, ctx.GetUserName(), reason, oaosAdjustDTOList)
@@ -462,31 +484,22 @@ func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode strin
return vendorOrderIDs, err
}
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee int64) (err error) {
a := getAPI(order.VendorOrgCode)
orderInfo, err := a.QuerySingleOrder2(order.VendorOrderID)
if err == nil {
tip2Add := int(tipFee) - orderInfo.Tips
if tip2Add != 0 {
if globals.EnableJdStoreWrite {
err = a.OrderAddTips(order.VendorOrderID, tip2Add, ctx.GetUserName())
}
}
}
return err
}
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder) (tipFee int64, err error) {
orderInfo, err := getAPI(order.VendorOrgCode).QuerySingleOrder2(order.VendorOrderID)
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
orderInfo, err := getAPI(vendorOrgCode).QuerySingleOrder2(vendorOrderID)
if err == nil {
tipFee = int64(orderInfo.Tips)
}
return tipFee, err
}
func (c *PurchaseHandler) AddWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee2Add int64) (err error) {
if globals.EnableJdStoreWrite {
err = getAPI(order.VendorOrgCode).OrderAddTips(order.VendorOrderID, int(tipFee2Add), ctx.GetUserName())
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
curTipFee, err := c.GetWaybillTip(ctx, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2)
if err == nil {
if tipFee2Add := tipFee - curTipFee; tipFee2Add > 0 {
if globals.EnableJdStoreWrite {
err = getAPI(vendorOrgCode).OrderAddTips(vendorOrderID, int(tipFee2Add), ctx.GetUserName())
}
}
}
return err
}

View File

@@ -32,6 +32,14 @@ func TestGetOrder(t *testing.T) {
}
}
func TestGetOrderStatus(t *testing.T) {
status, err := CurPurchaseHandler.GetOrderStatus("", "929203144000041")
if err != nil {
t.Fatal(err.Error())
}
t.Log(status)
}
func TestListOrders(t *testing.T) {
result, err := CurPurchaseHandler.ListOrders(jxcontext.AdminCtx, "", nil, time.Now(), "")
if err != nil {

View File

@@ -2,491 +2,479 @@ package jd
// 这里函数取得的信息除了与自身实体相关的ID比如PARENT ID都已经转换成了本地ID了
import (
"fmt"
"unicode/utf8"
// type tSkuInfoExt struct {
// model.SkuName
// JdCatID int64 `orm:"column(jd_cat_id)"` // 商家类别
// JdCategoryID int `orm:"column(jd_category_id)"` // 到家类别
// SkuCatID int64 `orm:"column(sku_cat_id)"` // 商家特殊类别
// Comment string `orm:"size(255)" json:"comment"`
// }
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals"
)
// var (
// skuAddParamsKeyMap = map[string]int{
// jdapi.KeyUpcCode: 1,
// }
// )
type tSkuInfoExt struct {
model.SkuName
JdCatID int64 `orm:"column(jd_cat_id)"` // 商家类别
JdCategoryID int `orm:"column(jd_category_id)"` // 到家类别
SkuCatID int64 `orm:"column(sku_cat_id)"` // 商家特殊类别
Comment string `orm:"size(255)" json:"comment"`
}
// func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
// var jdPid int64
// if cat.ParentID != 0 {
// pCat := &model.SkuCategory{}
// pCat.ID = cat.ParentID
// if err = dao.GetEntity(db, pCat); err == nil {
// jdPid = pCat.JdID
// } else {
// return err
// }
// }
// if globals.EnableJdStoreWrite {
// result, err2 := getAPI("").AddShopCategory(jdPid, cat.Name, int(cat.Level), cat.Seq, userName)
// if err = err2; err == nil {
// if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
// cat.JdID = jdID
// }
// }
// } else {
// cat.JdID = jxutils.GenFakeID()
// }
// return err
// }
var (
skuAddParamsKeyMap = map[string]int{
jdapi.KeyUpcCode: 1,
}
)
// func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
// if globals.EnableJdStoreWrite {
// return getAPI("").UpdateShopCategory(cat.JdID, cat.Name)
// }
// return nil
// }
func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
var jdPid int64
if cat.ParentID != 0 {
pCat := &model.SkuCategory{}
pCat.ID = cat.ParentID
if err = dao.GetEntity(db, pCat); err == nil {
jdPid = pCat.JdID
} else {
return err
}
}
if globals.EnableJdStoreWrite {
result, err2 := getAPI("").AddShopCategory(jdPid, cat.Name, int(cat.Level), cat.Seq, userName)
if err = err2; err == nil {
if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
cat.JdID = jdID
}
}
} else {
cat.JdID = jxutils.GenFakeID()
}
return err
}
// func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
// if globals.EnableJdStoreWrite {
// return getAPI("").DelShopCategory(cat.JdID)
// }
// return nil
// }
func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
if globals.EnableJdStoreWrite {
return getAPI("").UpdateShopCategory(cat.JdID, cat.Name)
}
return nil
}
// func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) {
// var parentJDID int64
// if parentCatID != 0 {
// cat := &model.SkuCategory{}
// cat.ID = parentCatID
// if err = dao.GetEntity(db, cat); err != nil {
// return err
// }
// parentJDID = cat.JdID
// }
// var cats []*model.SkuCategory
// if err = dao.GetRows(db, &cats, `
// SELECT *
// FROM sku_category
// WHERE parent_id = ? AND deleted_at = ?
// ORDER BY seq`, parentCatID, utils.DefaultTimeValue); err == nil {
// jdCatIDs := make([]int64, len(cats))
// for k, v := range cats {
// jdCatIDs[k] = v.JdID
// }
// if globals.EnableJdStoreWrite {
// err = getAPI("").ChangeShopCategoryOrder(parentJDID, jdCatIDs)
// }
// }
// return err
// }
func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
if globals.EnableJdStoreWrite {
return getAPI("").DelShopCategory(cat.JdID)
}
return nil
}
func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) {
var parentJDID int64
if parentCatID != 0 {
cat := &model.SkuCategory{}
cat.ID = parentCatID
if err = dao.GetEntity(db, cat); err != nil {
return err
}
parentJDID = cat.JdID
}
var cats []*model.SkuCategory
if err = dao.GetRows(db, &cats, `
SELECT *
FROM sku_category
WHERE parent_id = ? AND deleted_at = ?
ORDER BY seq`, parentCatID, utils.DefaultTimeValue); err == nil {
jdCatIDs := make([]int64, len(cats))
for k, v := range cats {
jdCatIDs[k] = v.JdID
}
if globals.EnableJdStoreWrite {
err = getAPI("").ChangeShopCategoryOrder(parentJDID, jdCatIDs)
}
}
return err
}
func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (string, error)) (err error) {
var skuInfoExt tSkuInfoExt
err = dao.GetRow(nil, &skuInfoExt, `
SELECT
t2.*, IF(t2.jd_category_id > 0, t2.jd_category_id, t3.jd_category_id) jd_category_id,
t3.jd_id jd_cat_id,
t4.jd_id sku_cat_id
FROM sku t1
JOIN sku_name t2 ON t1.name_id = t2.id
JOIN sku_category t3 ON t2.category_id = t3.id
LEFT JOIN sku_category t4 ON t1.category_id = t4.id
WHERE t1.id = ?
`, sku.ID)
if err == nil {
shopCategories := []int64{skuInfoExt.JdCatID}
// SPU只支持SPU的商家分类不支持单独SKU的去除SKU的分类
// if skuInfoExt.SkuCatID != 0 {
// shopCategories = append(shopCategories, skuInfoExt.SkuCatID)
// }
if skuInfoExt.JdCategoryID == 0 {
skuInfoExt.JdCategoryID = getDefJdCategoryID()
}
if skuInfoExt.BrandID == 0 {
skuInfoExt.BrandID = DefBrandID
}
addParams := map[string]interface{}{}
if skuInfoExt.IsGlobal == 0 { //如果不是全国可售,要查可售区域
sellPlaces, err2 := dao.GetSellCities(db, skuInfoExt.ID, model.VendorIDJD)
if err = err2; err == nil && len(sellPlaces) > 0 {
sellCites := make([]int, len(sellPlaces))
for k, v := range sellPlaces {
sellCites[k] = v.JdCode
}
addParams["sellCities"] = sellCites
}
}
if addParams["sellCities"] == nil {
addParams["sellCities"] = []int{0}
}
if skuInfoExt.DescImg != "" {
addParams[jdapi.KeyProductDesc] = fmt.Sprintf(`<img src="%s" alt="一张图片" />`, skuInfoExt.DescImg)
addParams[jdapi.KeyIfViewDesc] = 0
} else {
addParams[jdapi.KeyIfViewDesc] = 1
}
if err == nil {
skuName := jxutils.ComposeSkuName(skuInfoExt.Prefix, skuInfoExt.Name, sku.Comment, skuInfoExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount)
skuPrice := jxutils.CaculateSkuPrice(skuInfoExt.Price, sku.SpecQuality, sku.SpecUnit, skuInfoExt.Unit)
if skuInfoExt.Upc != "" {
addParams[jdapi.KeyUpcCode] = skuInfoExt.Upc
}
result, err2 := handler(&skuInfoExt, skuPrice, skuName, shopCategories, addParams)
if err = err2; err == nil {
if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
sku.JdID = jdID
}
}
}
}
return err
}
func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
if skuExt.IsSpu == 0 {
if globals.EnableJdStoreWrite {
vendorSkuID, err = getAPI("").AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), jxutils.BatchString2Slice(skuExt.Img, skuExt.Img2), jxStatus2jdStatus(sku.Status), true, addParams)
if err != nil {
if jdSkuID := jdapi.GetJdSkuIDFromError(err); jdSkuID > 0 {
vendorSkuID = utils.Int64ToStr(jdSkuID)
err = nil
}
}
} else {
vendorSkuID = utils.Int64ToStr(jxutils.GenFakeID())
}
} else {
vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
}
return vendorSkuID, err
})
}
// func (p *PurchaseHandler) ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) {
// jdSkuID := utils.Str2Int64(vendorSkuID)
// a := getAPI(vendorOrgCode)
// skuList, _, err := a.QuerySkuInfos(&jdapi.QuerySkuParam{
// SkuID: jdSkuID,
// })
// func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (string, error)) (err error) {
// var skuInfoExt tSkuInfoExt
// err = dao.GetRow(nil, &skuInfoExt, `
// SELECT
// t2.*, IF(t2.jd_category_id > 0, t2.jd_category_id, t3.jd_category_id) jd_category_id,
// t3.jd_id jd_cat_id,
// t4.jd_id sku_cat_id
// FROM sku t1
// JOIN sku_name t2 ON t1.name_id = t2.id
// JOIN sku_category t3 ON t2.category_id = t3.id
// LEFT JOIN sku_category t4 ON t1.category_id = t4.id
// WHERE t1.id = ?
// `, sku.ID)
// if err == nil {
// if len(skuList) >= 1 {
// skuNameExt = &model.SkuNameExt{}
// if imgList, err2 := a.QueryListBySkuIds(&jdapi.QueryListBySkuIdsParam{
// SkuIDs: []int64{jdSkuID},
// }); err2 == nil && len(imgList) > 0 {
// skuNameExt.Img = imgList[0].SourceImgURL
// }
// sku := skuList[0]
// prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(sku.SkuName)
// if name == "" {
// name = sku.SkuName
// unit = "份"
// specUnit = "g"
// }
// skuNameExt.Prefix = prefix
// skuNameExt.Name = name
// skuNameExt.Unit = unit
// skuNameExt.Price = sku.SkuPrice
// skuNameExt.Skus = []*model.SkuWithVendor{
// &model.SkuWithVendor{
// Sku: &model.Sku{
// SpecQuality: specQuality,
// SpecUnit: specUnit,
// Weight: jxutils.FloatWeight2Int(float32(sku.Weight)),
// JdID: sku.SkuID,
// Status: jdStatus2jxStatus(sku.FixedStatus),
// Comment: comment,
// },
// },
// }
// skuNameExt.Skus[0].ID = int(utils.Str2Int64(sku.OutSkuID))
// shopCategories := []int64{skuInfoExt.JdCatID}
// // SPU只支持SPU的商家分类不支持单独SKU的去除SKU的分类
// // if skuInfoExt.SkuCatID != 0 {
// // shopCategories = append(shopCategories, skuInfoExt.SkuCatID)
// // }
// if skuInfoExt.JdCategoryID == 0 {
// skuInfoExt.JdCategoryID = getDefJdCategoryID()
// }
// if skuInfoExt.BrandID == 0 {
// skuInfoExt.BrandID = DefBrandID
// }
// addParams := map[string]interface{}{}
// db := dao.GetDB()
// shopCategories := sku.ShopCategories
// if len(shopCategories) > 0 {
// skuCat := &model.SkuCategory{}
// skuCat.JdID = shopCategories[0]
// if dao.GetEntity(db, skuCat, "JdID") == nil {
// skuNameExt.CategoryID = skuCat.ID
// if skuInfoExt.IsGlobal == 0 { //如果不是全国可售,要查可售区域
// sellPlaces, err2 := dao.GetSellCities(db, skuInfoExt.ID, model.VendorIDJD)
// if err = err2; err == nil && len(sellPlaces) > 0 {
// sellCites := make([]int, len(sellPlaces))
// for k, v := range sellPlaces {
// sellCites[k] = v.JdCode
// }
// addParams["sellCities"] = sellCites
// }
// }
// if addParams["sellCities"] == nil {
// addParams["sellCities"] = []int{0}
// }
// if skuInfoExt.DescImg != "" {
// addParams[jdapi.KeyProductDesc] = fmt.Sprintf(`<img src="%s" alt="一张图片" />`, skuInfoExt.DescImg)
// addParams[jdapi.KeyIfViewDesc] = 0
// } else {
// addParams[jdapi.KeyIfViewDesc] = 1
// }
// if err == nil {
// skuName := jxutils.ComposeSkuName(skuInfoExt.Prefix, skuInfoExt.Name, sku.Comment, skuInfoExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount)
// skuPrice := jxutils.CaculateSkuPrice(skuInfoExt.Price, sku.SpecQuality, sku.SpecUnit, skuInfoExt.Unit)
// if skuInfoExt.Upc != "" {
// addParams[jdapi.KeyUpcCode] = skuInfoExt.Upc
// }
// result, err2 := handler(&skuInfoExt, skuPrice, skuName, shopCategories, addParams)
// if err = err2; err == nil {
// if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
// sku.JdID = jdID
// }
// }
// sellCities := sku.SellCities
// for _, v := range sellCities {
// if v == 0 {
// skuNameExt.IsGlobal = 1
// }
// }
// return err
// }
// func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
// if skuExt.IsSpu == 0 {
// if globals.EnableJdStoreWrite {
// vendorSkuID, err = getAPI("").AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), jxutils.BatchString2Slice(skuExt.Img, skuExt.Img2), jxStatus2jdStatus(sku.Status), true, addParams)
// if err != nil {
// if jdSkuID := jdapi.GetJdSkuIDFromError(err); jdSkuID > 0 {
// vendorSkuID = utils.Int64ToStr(jdSkuID)
// err = nil
// }
// }
// }
// if len(sellCities) == 0 || skuNameExt.IsGlobal == 1 {
// skuNameExt.IsGlobal = 1
// } else {
// var places []*model.Place
// if err = dao.GetRows(db, &places, "SELECT * FROM place WHERE jd_code IN ("+dao.GenQuestionMarks(len(sellCities))+") AND level = 2", sellCities); err == nil {
// skuNameExt.Places = make([]int, len(places))
// for k, v := range places {
// skuNameExt.Places[k] = v.Code
// vendorSkuID = utils.Int64ToStr(jxutils.GenFakeID())
// }
// } else {
// vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
// }
// return vendorSkuID, err
// })
// }
// // func (p *PurchaseHandler) ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) {
// // jdSkuID := utils.Str2Int64(vendorSkuID)
// // a := getAPI(vendorOrgCode)
// // skuList, _, err := a.QuerySkuInfos(&jdapi.QuerySkuParam{
// // SkuID: jdSkuID,
// // })
// // if err == nil {
// // if len(skuList) >= 1 {
// // skuNameExt = &model.SkuNameExt{}
// // if imgList, err2 := a.QueryListBySkuIds(&jdapi.QueryListBySkuIdsParam{
// // SkuIDs: []int64{jdSkuID},
// // }); err2 == nil && len(imgList) > 0 {
// // skuNameExt.Img = imgList[0].SourceImgURL
// // }
// // sku := skuList[0]
// // prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(sku.SkuName)
// // if name == "" {
// // name = sku.SkuName
// // unit = "份"
// // specUnit = "g"
// // }
// // skuNameExt.Prefix = prefix
// // skuNameExt.Name = name
// // skuNameExt.Unit = unit
// // skuNameExt.Price = sku.SkuPrice
// // skuNameExt.Skus = []*model.SkuWithVendor{
// // &model.SkuWithVendor{
// // Sku: &model.Sku{
// // SpecQuality: specQuality,
// // SpecUnit: specUnit,
// // Weight: jxutils.FloatWeight2Int(float32(sku.Weight)),
// // JdID: sku.SkuID,
// // Status: jdStatus2jxStatus(sku.FixedStatus),
// // Comment: comment,
// // },
// // },
// // }
// // skuNameExt.Skus[0].ID = int(utils.Str2Int64(sku.OutSkuID))
// // db := dao.GetDB()
// // shopCategories := sku.ShopCategories
// // if len(shopCategories) > 0 {
// // skuCat := &model.SkuCategory{}
// // skuCat.JdID = shopCategories[0]
// // if dao.GetEntity(db, skuCat, "JdID") == nil {
// // skuNameExt.CategoryID = skuCat.ID
// // }
// // }
// // sellCities := sku.SellCities
// // for _, v := range sellCities {
// // if v == 0 {
// // skuNameExt.IsGlobal = 1
// // }
// // }
// // if len(sellCities) == 0 || skuNameExt.IsGlobal == 1 {
// // skuNameExt.IsGlobal = 1
// // } else {
// // var places []*model.Place
// // if err = dao.GetRows(db, &places, "SELECT * FROM place WHERE jd_code IN ("+dao.GenQuestionMarks(len(sellCities))+") AND level = 2", sellCities); err == nil {
// // skuNameExt.Places = make([]int, len(places))
// // for k, v := range places {
// // skuNameExt.Places[k] = v.Code
// // }
// // }
// // }
// // } else {
// // err = partner.ErrCanNotFindItem
// // }
// // }
// // return skuNameExt, err
// // }
// func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
// params := utils.MergeMaps(addParams)
// params[jdapi.KeyCategoryId] = skuExt.JdCategoryID
// params[jdapi.KeyShopCategories] = shopCategories
// params[jdapi.KeyBrandId] = skuExt.BrandID
// params[jdapi.KeySkuName] = skuName
// params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight)
// params[jdapi.KeyImages] = jxutils.BatchString2Slice(skuExt.Img, skuExt.Img2)
// params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status)
// if skuExt.IsSpu == 0 {
// if globals.EnableJdStoreWrite {
// vendorSkuID, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params)
// }
// } else {
// vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
// }
// return vendorSkuID, err
// })
// }
// func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// params := map[string]interface{}{
// jdapi.KeyFixedStatus: jdapi.SkuFixedStatusDeleted,
// }
// sql := `
// SELECT t2.*
// FROM sku t1
// JOIN sku_name t2 ON t1.name_id = t2.id
// WHERE t1.id = ?
// `
// var skuExt tSkuInfoExt
// err = dao.GetRow(db, &skuExt, sql, sku.ID)
// if err == nil {
// if skuExt.IsSpu == 0 {
// if globals.EnableJdStoreWrite {
// _, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params)
// }
// } else {
// _, err = p.syncSkuNameAsSpu(db, sku, &skuExt, 0, "", nil, nil)
// }
// }
// return err
// }
// // func (p *PurchaseHandler) RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
// // globals.SugarLogger.Debugf("jd RefreshAllSkusID")
// // db := dao.GetDB()
// // var skuPairs []*jdapi.SkuIDPair
// // const stepCount = 2
// // rootTask := tasksch.NewSeqTask("jd RefreshAllSkusID", ctx,
// // func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
// // switch step {
// // case 0:
// // err = dao.GetRows(db, &skuPairs, `
// // SELECT t1.id out_sku_id, t1.jd_id sku_id
// // FROM sku t1
// // WHERE t1.deleted_at = ?
// // `, utils.DefaultTimeValue)
// // default:
// // taskName := "RefreshAllSkusID update id"
// // if step != stepCount-1 {
// // taskName = "RefreshAllSkusID update uuid"
// // }
// // task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetBatchSize(jdapi.MaxBatchSize4BatchUpdateOutSkuId), ctx,
// // func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
// // skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList))
// // for k, v := range batchItemList {
// // pair := v.(*jdapi.SkuIDPair)
// // skuPairs[k] = &jdapi.SkuIDPair{
// // SkuId: pair.SkuId,
// // OutSkuId: pair.OutSkuId,
// // }
// // if step != stepCount-1 {
// // skuPairs[k].OutSkuId = utils.GetUUID()
// // }
// // }
// // globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
// // if globals.EnableJdStoreWrite {
// // _, err = getAPI("").BatchUpdateOutSkuId(skuPairs)
// // }
// // return nil, err
// // }, skuPairs)
// // rootTask.AddChild(task1).Run()
// // _, err = task1.GetResult(0)
// // }
// // return nil, err
// // }, stepCount)
// // tasksch.HandleTask(rootTask, parentTask, false).Run()
// // if !isAsync {
// // _, err = rootTask.GetResult(0)
// // }
// // return rootTask.ID, err
// // }
// func splitAddParams(addParams map[string]interface{}) (spuAddParams, skuAddParams map[string]interface{}) {
// if addParams != nil {
// spuAddParams = make(map[string]interface{})
// skuAddParams = make(map[string]interface{})
// for key := range addParams {
// if skuAddParamsKeyMap[key] == 1 {
// skuAddParams[key] = addParams[key]
// } else {
// spuAddParams[key] = addParams[key]
// }
// }
// }
// return spuAddParams, skuAddParams
// }
// // 这个处理JD SPU补丁形式
// func (p *PurchaseHandler) syncSkuNameAsSpu(db *dao.DaoDB, sku *model.Sku, skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
// // SPU的SKU NAME不需要规格信息
// skuName = jxutils.ComposeSkuName(skuExt.Prefix, skuExt.Name, sku.Comment, "", 0, "", 0)
// skuNameJdID := skuExt.JdID
// globals.SugarLogger.Debugf("syncSkuNameAsSpu1 sku.id=%d, bareSkuName:%s, skuName:%s, skuNameJdID:%d", sku.ID, skuExt.Name, skuName, skuNameJdID)
// spuAddParams, skuAddParams := splitAddParams(addParams)
// if !jxutils.IsEmptyID(skuNameJdID) && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除SKU
// if globals.EnableJdStoreWrite {
// err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
// }
// }
// if err == nil {
// updateFields := []string{}
// if skuExt.JdSyncStatus&model.SyncFlagDeletedMask != 0 {
// sql := `
// SELECT COUNT(*) ct
// FROM sku t1
// WHERE t1.name_id = ? AND (t1.status <> ? OR t1.jd_sync_status <> 0)
// `
// var count struct {
// Ct int
// }
// if err = dao.GetRow(db, &count, sql, sku.NameID, model.SkuStatusDeleted); err != nil {
// return "", err
// }
// if count.Ct <= 1 && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 1就是最后删的那个
// updateFields = append(updateFields, model.FieldJdSyncStatus)
// if globals.EnableJdStoreWrite {
// if err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil {
// err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
// }
// }
// }
// } else {
// err = partner.ErrCanNotFindItem
// } else if skuExt.JdSyncStatus&model.SyncFlagNewMask != 0 && jxutils.IsEmptyID(skuNameJdID) {
// if globals.EnableJdStoreWrite {
// spuName := jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0)
// skus := []map[string]interface{}{
// map[string]interface{}{
// jdapi.KeyOutSkuId: utils.Int2Str(sku.ID),
// jdapi.KeySkuName: skuName,
// jdapi.KeyFixedStatus: jxStatus2jdStatus(sku.Status),
// jdapi.KeySkuPrice: price,
// jdapi.KeyWeight: jxutils.IntWeight2Float(sku.Weight),
// jdapi.KeyIsSale: true,
// jdapi.FakeKeySpecAttr: composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit),
// },
// }
// skus[0] = utils.MergeMaps(skus[0], skuAddParams)
// updateFields = append(updateFields, model.FieldJdSyncStatus)
// if globals.EnableJdStoreWrite {
// vendorSpuID, skuPairs, err2 := getAPI("").AddSpu(utils.Int2Str(skuExt.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, spuName, []string{skuExt.Img}, jxStatus2jdStatus(skuExt.Status), spuAddParams, skus)
// if err = err2; err == nil {
// skuExt.JdID = vendorSpuID
// // skuNameJdID = skuExt.JdID // 这个是故意去掉的这样之后的首次SKU修改操作就会被忽略下一条语句也就可以不用了
// // sku.JdSyncStatus &= ^model.SyncFlagNewMask
// vendorSkuID = utils.Int64ToStr(skuPairs[0].SkuId)
// updateFields = append(updateFields, model.FieldJdID)
// }
// }
// }
// } else if skuExt.JdSyncStatus&model.SyncFlagModifiedMask != 0 {
// params := utils.MergeMaps(map[string]interface{}{
// jdapi.KeySpuName: jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0),
// jdapi.KeyShopCategories: shopCategories,
// jdapi.KeyCategoryId: skuExt.JdCategoryID,
// jdapi.KeyBrandId: skuExt.BrandID,
// jdapi.KeyImages: []string{skuExt.Img},
// jdapi.KeyFixedStatus: jxStatus2jdStatus(skuExt.Status),
// }, spuAddParams)
// updateFields = append(updateFields, model.FieldJdSyncStatus)
// if globals.EnableJdStoreWrite {
// err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), params)
// }
// }
// if err == nil {
// if skuExt.JdSyncStatus != 0 && len(updateFields) > 0 {
// skuExt.JdSyncStatus = 0
// _, err = dao.UpdateEntity(db, &skuExt.SkuName, updateFields...)
// globals.SugarLogger.Debugf("syncSkuNameAsSpu4 sku.id=%d, skuName:%s, skuName:%s", sku.ID, skuExt.Name, utils.Format4Output(&skuExt.SkuName, false))
// }
// }
// }
// return skuNameExt, err
// }
func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
params := utils.MergeMaps(addParams)
params[jdapi.KeyCategoryId] = skuExt.JdCategoryID
params[jdapi.KeyShopCategories] = shopCategories
params[jdapi.KeyBrandId] = skuExt.BrandID
params[jdapi.KeySkuName] = skuName
params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight)
params[jdapi.KeyImages] = jxutils.BatchString2Slice(skuExt.Img, skuExt.Img2)
params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status)
if skuExt.IsSpu == 0 {
if globals.EnableJdStoreWrite {
vendorSkuID, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params)
}
} else {
vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
}
return vendorSkuID, err
})
}
func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
params := map[string]interface{}{
jdapi.KeyFixedStatus: jdapi.SkuFixedStatusDeleted,
}
sql := `
SELECT t2.*
FROM sku t1
JOIN sku_name t2 ON t1.name_id = t2.id
WHERE t1.id = ?
`
var skuExt tSkuInfoExt
err = dao.GetRow(db, &skuExt, sql, sku.ID)
if err == nil {
if skuExt.IsSpu == 0 {
if globals.EnableJdStoreWrite {
_, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params)
}
} else {
_, err = p.syncSkuNameAsSpu(db, sku, &skuExt, 0, "", nil, nil)
}
}
return err
}
// func (p *PurchaseHandler) RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
// globals.SugarLogger.Debugf("jd RefreshAllSkusID")
// db := dao.GetDB()
// var skuPairs []*jdapi.SkuIDPair
// const stepCount = 2
// rootTask := tasksch.NewSeqTask("jd RefreshAllSkusID", ctx,
// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
// switch step {
// case 0:
// err = dao.GetRows(db, &skuPairs, `
// SELECT t1.id out_sku_id, t1.jd_id sku_id
// FROM sku t1
// WHERE t1.deleted_at = ?
// `, utils.DefaultTimeValue)
// default:
// taskName := "RefreshAllSkusID update id"
// if step != stepCount-1 {
// taskName = "RefreshAllSkusID update uuid"
// if err == nil && !jxutils.IsEmptyID(skuNameJdID) {
// if sku.JdSyncStatus&model.SyncFlagNewMask != 0 { // 非首次新增SKU
// if globals.EnableJdStoreWrite {
// vendorSkuID2, err2 := getAPI("").AppendSku(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit), skuAddParams)
// if err = err2; err == nil {
// vendorSkuID = utils.Int64ToStr(vendorSkuID2)
// }
// task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetBatchSize(jdapi.MaxBatchSize4BatchUpdateOutSkuId), ctx,
// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
// skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList))
// for k, v := range batchItemList {
// pair := v.(*jdapi.SkuIDPair)
// skuPairs[k] = &jdapi.SkuIDPair{
// SkuId: pair.SkuId,
// OutSkuId: pair.OutSkuId,
// }
// if step != stepCount-1 {
// skuPairs[k].OutSkuId = utils.GetUUID()
// }
// }
// globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
// if globals.EnableJdStoreWrite {
// _, err = getAPI("").BatchUpdateOutSkuId(skuPairs)
// }
// return nil, err
// }, skuPairs)
// rootTask.AddChild(task1).Run()
// _, err = task1.GetResult(0)
// }
// return nil, err
// }, stepCount)
// tasksch.HandleTask(rootTask, parentTask, false).Run()
// if !isAsync {
// _, err = rootTask.GetResult(0)
// } else if sku.JdSyncStatus&model.SyncFlagModifiedMask != 0 {
// params := make(map[string]interface{})
// params[jdapi.KeySkuName] = skuName
// params[jdapi.KeyImages] = []string{skuExt.Img}
// params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status)
// params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight)
// params[jdapi.KeySkuPrice] = price
// if globals.EnableJdStoreWrite {
// err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.MergeMaps(params, skuAddParams))
// if sku.JdSyncStatus&model.SyncFlagSpecMask != 0 {
// skuIndex := sku.SkuIndex
// if skuIndex > 0 {
// saleAttrValue := composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit)
// globals.SugarLogger.Debugf("syncSkuNameAsSpu outSuperId:%d, saleAttrId:%d, saleAttrValueId:%d, saleAttrValueName:%s", skuExt.ID, jdapi.SaleAttrIDBase, jdapi.SaleAttrValueIDBase+skuIndex-1, saleAttrValue)
// err = getAPI("").UpdateSpuSaleAttr(utils.Int2Str(skuExt.ID), utils.Int2Str(jdapi.SaleAttrIDBase), "", utils.Int2Str(jdapi.SaleAttrValueIDBase+skuIndex-1), saleAttrValue)
// }
// }
// }
// }
// if err == nil {
// sku.JdSyncStatus = 0
// }
// }
// return rootTask.ID, err
// return vendorSkuID, err
// }
func splitAddParams(addParams map[string]interface{}) (spuAddParams, skuAddParams map[string]interface{}) {
if addParams != nil {
spuAddParams = make(map[string]interface{})
skuAddParams = make(map[string]interface{})
for key := range addParams {
if skuAddParamsKeyMap[key] == 1 {
skuAddParams[key] = addParams[key]
} else {
spuAddParams[key] = addParams[key]
}
}
}
return spuAddParams, skuAddParams
}
// 这个处理JD SPU补丁形式
func (p *PurchaseHandler) syncSkuNameAsSpu(db *dao.DaoDB, sku *model.Sku, skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
// SPU的SKU NAME不需要规格信息
skuName = jxutils.ComposeSkuName(skuExt.Prefix, skuExt.Name, sku.Comment, "", 0, "", 0)
skuNameJdID := skuExt.JdID
globals.SugarLogger.Debugf("syncSkuNameAsSpu1 sku.id=%d, bareSkuName:%s, skuName:%s, skuNameJdID:%d", sku.ID, skuExt.Name, skuName, skuNameJdID)
spuAddParams, skuAddParams := splitAddParams(addParams)
if !jxutils.IsEmptyID(skuNameJdID) && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除SKU
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
}
}
if err == nil {
updateFields := []string{}
if skuExt.JdSyncStatus&model.SyncFlagDeletedMask != 0 {
sql := `
SELECT COUNT(*) ct
FROM sku t1
WHERE t1.name_id = ? AND (t1.status <> ? OR t1.jd_sync_status <> 0)
`
var count struct {
Ct int
}
if err = dao.GetRow(db, &count, sql, sku.NameID, model.SkuStatusDeleted); err != nil {
return "", err
}
if count.Ct <= 1 && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 1就是最后删的那个
updateFields = append(updateFields, model.FieldJdSyncStatus)
if globals.EnableJdStoreWrite {
if err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil {
err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
}
}
}
} else if skuExt.JdSyncStatus&model.SyncFlagNewMask != 0 && jxutils.IsEmptyID(skuNameJdID) {
if globals.EnableJdStoreWrite {
spuName := jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0)
skus := []map[string]interface{}{
map[string]interface{}{
jdapi.KeyOutSkuId: utils.Int2Str(sku.ID),
jdapi.KeySkuName: skuName,
jdapi.KeyFixedStatus: jxStatus2jdStatus(sku.Status),
jdapi.KeySkuPrice: price,
jdapi.KeyWeight: jxutils.IntWeight2Float(sku.Weight),
jdapi.KeyIsSale: true,
jdapi.FakeKeySpecAttr: composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit),
},
}
skus[0] = utils.MergeMaps(skus[0], skuAddParams)
updateFields = append(updateFields, model.FieldJdSyncStatus)
if globals.EnableJdStoreWrite {
vendorSpuID, skuPairs, err2 := getAPI("").AddSpu(utils.Int2Str(skuExt.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, spuName, []string{skuExt.Img}, jxStatus2jdStatus(skuExt.Status), spuAddParams, skus)
if err = err2; err == nil {
skuExt.JdID = vendorSpuID
// skuNameJdID = skuExt.JdID // 这个是故意去掉的这样之后的首次SKU修改操作就会被忽略下一条语句也就可以不用了
// sku.JdSyncStatus &= ^model.SyncFlagNewMask
vendorSkuID = utils.Int64ToStr(skuPairs[0].SkuId)
updateFields = append(updateFields, model.FieldJdID)
}
}
}
} else if skuExt.JdSyncStatus&model.SyncFlagModifiedMask != 0 {
params := utils.MergeMaps(map[string]interface{}{
jdapi.KeySpuName: jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0),
jdapi.KeyShopCategories: shopCategories,
jdapi.KeyCategoryId: skuExt.JdCategoryID,
jdapi.KeyBrandId: skuExt.BrandID,
jdapi.KeyImages: []string{skuExt.Img},
jdapi.KeyFixedStatus: jxStatus2jdStatus(skuExt.Status),
}, spuAddParams)
updateFields = append(updateFields, model.FieldJdSyncStatus)
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), params)
}
}
if err == nil {
if skuExt.JdSyncStatus != 0 && len(updateFields) > 0 {
skuExt.JdSyncStatus = 0
_, err = dao.UpdateEntity(db, &skuExt.SkuName, updateFields...)
globals.SugarLogger.Debugf("syncSkuNameAsSpu4 sku.id=%d, skuName:%s, skuName:%s", sku.ID, skuExt.Name, utils.Format4Output(&skuExt.SkuName, false))
}
}
}
if err == nil && !jxutils.IsEmptyID(skuNameJdID) {
if sku.JdSyncStatus&model.SyncFlagNewMask != 0 { // 非首次新增SKU
if globals.EnableJdStoreWrite {
vendorSkuID2, err2 := getAPI("").AppendSku(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit), skuAddParams)
if err = err2; err == nil {
vendorSkuID = utils.Int64ToStr(vendorSkuID2)
}
}
} else if sku.JdSyncStatus&model.SyncFlagModifiedMask != 0 {
params := make(map[string]interface{})
params[jdapi.KeySkuName] = skuName
params[jdapi.KeyImages] = []string{skuExt.Img}
params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status)
params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight)
params[jdapi.KeySkuPrice] = price
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.MergeMaps(params, skuAddParams))
if sku.JdSyncStatus&model.SyncFlagSpecMask != 0 {
skuIndex := sku.SkuIndex
if skuIndex > 0 {
saleAttrValue := composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit)
globals.SugarLogger.Debugf("syncSkuNameAsSpu outSuperId:%d, saleAttrId:%d, saleAttrValueId:%d, saleAttrValueName:%s", skuExt.ID, jdapi.SaleAttrIDBase, jdapi.SaleAttrValueIDBase+skuIndex-1, saleAttrValue)
err = getAPI("").UpdateSpuSaleAttr(utils.Int2Str(skuExt.ID), utils.Int2Str(jdapi.SaleAttrIDBase), "", utils.Int2Str(jdapi.SaleAttrValueIDBase+skuIndex-1), saleAttrValue)
}
}
}
}
if err == nil {
sku.JdSyncStatus = 0
}
}
return vendorSkuID, err
}
func composeSkuSpec(specQuality float32, specUnit, unit string) string {
prefix := ""
if unit == model.SpecialUnit {
prefix = "约"
}
value := prefix + jxutils.ComposeSkuSpec(specQuality, specUnit)
suffix := "/" + unit
if utf8.RuneCountInString(value) <= 8-utf8.RuneCountInString(suffix) {
value += suffix
}
return value
}
// func composeSkuSpec(specQuality float32, specUnit, unit string) string {
// prefix := ""
// if unit == model.SpecialUnit {
// prefix = "约"
// }
// value := prefix + jxutils.ComposeSkuSpec(specQuality, specUnit)
// suffix := "/" + unit
// if utf8.RuneCountInString(value) <= 8-utf8.RuneCountInString(suffix) {
// value += suffix
// }
// return value
// }

View File

@@ -12,6 +12,7 @@ import (
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego"
)
@@ -113,7 +114,7 @@ func (p *PurchaseHandler) ReorderCategories2(ctx *jxcontext.Context, vendorOrgCo
func (p *PurchaseHandler) getVendorCategories(level int, pid int64) (vendorCats []*model.SkuVendorCategory, err error) {
// 得到平台的分类,不需要指定分账号
cats, err := getAPI("").QueryChildCategoriesForOP(pid)
cats, err := api.Jd2API.QueryChildCategoriesForOP(pid)
if err != nil {
return nil, err
}
@@ -169,6 +170,10 @@ func skuInfo2Param(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (param *jd
if param.CategoryID == 0 {
param.CategoryID = int64(getDefJdCategoryID())
}
// 京东强制要求upc的商品如果没有设置upc自动生成一个假的
if param.Upc == "" && isSkuMustHaveUpc(sku.Unit, param.CategoryID) {
param.Upc = jxutils.GenFakeUPC(sku.SkuID)
}
if sku.IsGlobal == 0 && len(sku.SellCities) > 0 {
param.SellCities = utils.StringSlice2Int64(sku.SellCities)
}
@@ -200,6 +205,23 @@ func (p *PurchaseHandler) UpdateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSy
func (p *PurchaseHandler) DeleteSku2(ctx *jxcontext.Context, vendorOrgCode string, sku *partner.StoreSkuInfo) (err error) {
globals.SugarLogger.Debugf("DeleteSku2 vendorOrgCode:%s, sku:%s", vendorOrgCode, utils.Format4Output(sku, true))
// 京东到家只能通过商家ID删除SKU如果没有的话先绑定再删除
if sku.SkuID == 0 {
skuPairList := []*jdapi.SkuIDPair{
&jdapi.SkuIDPair{
SkuId: utils.Str2Int64(sku.VendorSkuID),
OutSkuId: sku.VendorSkuID,
},
}
if globals.EnableJdStoreWrite {
_, err = getAPI(vendorOrgCode).BatchUpdateOutSkuId(skuPairList)
if err != nil {
return err
}
sku.SkuID = int(utils.Str2Int64(sku.VendorSkuID))
}
}
param := &jdapi.OpSkuParam{
TraceID: ctx.GetTrackInfo(),
OutSkuID: utils.Int2Str(sku.SkuID),
@@ -357,3 +379,101 @@ func jxStatus2jdStatus(jxStatus int) (jdStatus int) {
}
return jdStatus
}
func isSkuMustHaveUpc(unit string, vendorVendorCatID int64) bool {
return unit != model.SpecialUnit || !upcLessMap[vendorVendorCatID]
}
var (
upcLessMap = map[int64]bool{
20250: true,
20252: true,
20258: true,
20259: true,
20261: true,
20262: true,
20263: true,
20264: true,
20265: true,
20266: true,
20267: true,
22822: true,
20269: true,
20270: true,
20271: true,
20272: true,
20273: true,
20275: true,
20276: true,
20277: true,
20278: true,
20279: true,
20281: true,
20282: true,
20283: true,
20285: true,
20286: true,
20287: true,
22821: true,
20289: true,
20290: true,
23018: true,
20354: true,
20355: true,
20357: true,
20359: true,
23019: true,
20294: true,
20295: true,
20296: true,
20297: true,
20298: true,
20299: true,
20300: true,
20302: true,
20303: true,
20304: true,
22840: true,
22841: true,
20317: true,
20320: true,
20321: true,
20323: true,
20325: true,
20326: true,
20328: true,
20329: true,
20331: true,
20335: true,
20337: true,
20338: true,
20339: true,
22842: true,
22843: true,
23020: true,
20309: true,
20310: true,
20311: true,
20312: true,
20313: true,
20314: true,
20315: true,
22410: true,
23050: true,
20319: true,
20322: true,
20330: true,
20332: true,
20334: true,
20336: true,
20340: true,
20342: true,
23049: true,
20356: true,
20358: true,
20360: true,
20361: true,
20362: true,
20364: true,
}
)

View File

@@ -23,20 +23,6 @@ func TestCreateSku(t *testing.T) {
// }
}
func TestUpdateSku(t *testing.T) {
// t.Log(beego.BConfig.RunMode)
db := dao.GetDB()
skuID := 21741
sku := &model.Sku{}
sku.ID = skuID
dao.GetEntity(db, sku)
err := CurPurchaseHandler.UpdateSku(db, sku, "autotest")
if err != nil {
t.Fatal(err.Error())
}
}
func TestGetAllCategories(t *testing.T) {
result, err := CurPurchaseHandler.GetAllCategories(jxcontext.AdminCtx, "")
if err != nil || len(result) == 0 {

View File

@@ -36,6 +36,7 @@ type tJdStoreInfo struct {
VendorStoreID string `orm:"column(vendor_store_id)"`
RealLastOperator string
SyncStatus int
VendorStoreName string
}
var (
@@ -123,7 +124,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
t1.*, city.jd_code jd_city_code, district.jd_code jd_district_code,
t2.status jd_store_status, t2.vendor_store_id, IF(t1.updated_at > t2.updated_at, t1.last_operator,
t2.last_operator) real_last_operator,
t2.sync_status, t2.freight_deduction_pack, t2.vendor_org_code
t2.sync_status, t2.freight_deduction_pack, t2.vendor_org_code, t2.vendor_store_name
FROM store t1
JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND (t2.deleted_at = ?)
LEFT JOIN place city ON t1.city_code = city.code
@@ -146,7 +147,11 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
storeParams.OutSystemID = store.VendorStoreID
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD)
if store.VendorStoreName != "" {
storeParams.StationName = store.VendorStoreName
} else {
storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD)
}
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreAddress) != 0 {
storeParams.StationAddress = store.Address
@@ -170,7 +175,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
storeParams.City = storeParams.County
storeParams.County = specialDistrictMap[storeParams.County]
}
storeParams.StoreNotice = store.PromoteInfo
modifyCloseStatus := false
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagDeletedMask|model.SyncFlagStoreStatus) != 0 {
modifyCloseStatus = true

View File

@@ -64,7 +64,7 @@ func (c *PurchaseHandler) callbackMsg2Waybill(msg *jdapi.CallbackDeliveryStatusM
StatusTime: utils.Str2Time(msg.DeliveryStatusTime),
Remark: msg.Remark,
VendorOrgCode: appKey2OrgCode(msg.AppKey),
VendorOrgCode: AppKey2OrgCode(msg.AppKey),
}
return retVal
}

View File

@@ -152,13 +152,30 @@ func CreateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64,
outJxOrder.OrderID = GenOrderNo(ctx)
order, err2 := jxOrder2GoodsOrder(ctx, outJxOrder, deliveryAddress)
if err = err2; err == nil {
order.Status = model.OrderStatusCreated
order.Status = model.OrderStatusWait4Pay
callNewOrder(order)
}
}
return outJxOrder, err
}
// 买家取消(或申请取消)订单
func BuyerCancelOrder(ctx *jxcontext.Context, orderID int64) (canceled bool, err error) {
order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX)
if err == nil {
if order.Status < model.OrderStatusNew {
order.Status = model.OrderStatusCanceled
order.VendorStatus = utils.Int2Str(model.OrderStatusCanceled)
if err = partner.CurOrderManager.UpdateOrderFields(order, []string{model.FieldStatus, "VendorStatus"}); err == nil {
canceled = true
}
} else {
err = changeOrderStatus(utils.Int64ToStr(orderID), model.OrderStatusApplyCancel, fmt.Sprintf("用户%s主动取消", ctx.GetUserName()))
}
}
return canceled, err
}
func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) {
order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX)
if err == nil {
@@ -255,6 +272,10 @@ func GenOrderNo(ctx *jxcontext.Context) (orderNo int64) {
return orderNo
}
func GenPayOrderID(order *model.GoodsOrder) (payOrderID int64) {
return utils.Str2Int64(order.VendorOrderID)
}
func GenRefundID(order *model.GoodsOrder) (refundID int64) {
const suffix = 100000
refundID = utils.Str2Int64(order.VendorOrderID) * suffix
@@ -385,7 +406,7 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64
Count: v.Count,
SalePrice: int64(storeSkuBind.JxPrice), // todo 考虑活动价
Weight: sku.Weight,
Name: jxutils.ComposeSkuName(sku.Prefix, sku.Name, sku.Comment, sku.Unit, sku.SpecQuality, sku.SpecUnit, 0),
Name: jxutils.ComposeSkuName(sku.Prefix, sku.Name, sku.Comment, sku.Unit, sku.SpecQuality, sku.SpecUnit, 0, sku.ExPrefix, sku.ExPrefixBegin, sku.ExPrefixEnd),
}
if storeSkuBind.ActPrice != 0 && storeSkuBind.ActPrice < storeSkuBind.JxPrice {
jxSku.SalePrice = int64(storeSkuBind.ActPrice)
@@ -490,6 +511,10 @@ func AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName stri
return changeOrderStatus(order.VendorOrderID, status, "")
}
func AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
return err
}
func PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
return changeOrderStatus(order.VendorOrderID, model.OrderStatusFinishedPickup, "")
}
@@ -510,8 +535,9 @@ func CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string)
errList := errlist.New()
for _, orderPay := range payList {
if orderPay.Status == model.PayStatusYes {
refundID := utils.Int64ToStr(GenRefundID(order))
orderPayRefund, err2 := refundOrderByWX(ctx, orderPay, refundID)
// refundID := utils.Int64ToStr(GenRefundID(order))
refundID := order.VendorOrderID
orderPayRefund, err2 := refundOrderByWX(ctx, orderPay, refundID, orderPay.TotalFee, reason)
if err2 == nil {
dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName())
errList.AddErr(dao.CreateEntity(dao.GetDB(), orderPayRefund))
@@ -535,6 +561,15 @@ func CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string)
return err
}
func AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
if isAgree {
err = CancelOrder(ctx, order, reason)
} else {
err = changeOrderStatus(order.VendorOrderID, model.OrderStatusVendorRejectCancel, reason)
}
return err
}
// todo 消息用异步可能导致丢失,单同步又有重入相关的问题
func callNewOrder(order *model.GoodsOrder) (err error) {
jxutils.CallMsgHandlerAsync(func() {

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"time"
"git.rosy.net.cn/baseapi/platformapi/wxpay"
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
"git.rosy.net.cn/jx-callback/business/jxutils"
@@ -25,16 +25,16 @@ func getOrderBrief(order *model.GoodsOrder) string {
func pay4OrderByWX(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayType string) (orderPay *model.OrderPay, err error) {
payCreatedAt := time.Now()
param := &wxpay.CreateOrderParam{
param := &wxpayapi.CreateOrderParam{
OutTradeNo: utils.Int64ToStr(GenPayOrderID(order)),
Body: getOrderBrief(order),
NotifyURL: globals.WxpayNotifyURL,
OutTradeNo: order.VendorOrderID,
SpbillCreateIP: ctx.GetRealRemoteIP(),
TradeType: vendorPayType2WxpayType(vendorPayType),
TotalFee: int(order.ActualPayPrice),
TimeStart: wxpay.Time2PayTime(payCreatedAt),
// TimeExpire: wxpay.Time2PayTime(payCreatedAt.Add(PayWaitingTime)),
TimeStart: wxpayapi.Time2PayTime(payCreatedAt),
// TimeExpire: wxpayapi.Time2PayTime(payCreatedAt.Add(PayWaitingTime)),
}
if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini {
param.OpenID = authInfo.GetAuthID()
@@ -42,10 +42,12 @@ func pay4OrderByWX(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayTyp
result, err := api.WxpayAPI.CreateUnifiedOrder(param)
if err == nil {
orderPay = &model.OrderPay{
VendorOrderID: order.VendorOrderID,
VendorID: order.VendorID,
PayOrderID: param.OutTradeNo,
PayType: model.PayTypeWX,
VendorPayType: vendorPayType,
VendorOrderID: order.VendorOrderID,
VendorID: order.VendorID,
Status: 0,
PayCreatedAt: payCreatedAt,
PrepayID: result.PrepayID,
@@ -56,37 +58,35 @@ func pay4OrderByWX(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayTyp
return orderPay, err
}
func OnWxPayCallback(msg *wxpay.CallbackMsg) (err error) {
func OnWxPayCallback(msg *wxpayapi.CallbackMsg) (err error) {
globals.SugarLogger.Debugf("OnWxPayCallback msg:%s", utils.Format4Output(msg, true))
switch msg.MsgType {
case wxpay.MsgTypePay:
err = onWxpayFinished(msg.Data.(*wxpay.PayResultMsg))
case wxpay.MsgTypeRefund:
err = onWxpayRefund(msg.Data.(*wxpay.RefundResultMsg))
case wxpayapi.MsgTypePay:
err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg))
case wxpayapi.MsgTypeRefund:
err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg))
}
return err
}
func onWxpayFinished(msg *wxpay.PayResultMsg) (err error) {
func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) {
orderPay := &model.OrderPay{
VendorOrderID: msg.OutTradeNo,
VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(msg.OutTradeNo),
PayType: model.PayTypeWX,
PayOrderID: msg.OutTradeNo,
PayType: model.PayTypeWX,
}
orderPay.DeletedAt = utils.DefaultTimeValue
db := dao.GetDB()
if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "DeletedAt"); err == nil {
orderPay.VendorPayType = msg.TradeType
orderPay.PayFinishedAt = utils.Time2Pointer(wxpay.PayTime2Time(msg.TimeEnd))
if err = dao.GetEntity(db, orderPay, "PayOrderID", "PayType", "DeletedAt"); err == nil {
orderPay.PayFinishedAt = utils.Time2Pointer(wxpayapi.PayTime2Time(msg.TimeEnd))
orderPay.TransactionID = msg.TransactionID
orderPay.OriginalData = utils.Format4Output(msg, true)
if msg.ResultCode == wxpay.ResponseCodeSuccess {
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
orderPay.Status = model.PayStatusYes
} else {
orderPay.Status = model.PayStatusFailed
}
dao.UpdateEntity(db, orderPay)
if msg.ResultCode == wxpay.ResponseCodeSuccess {
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
err = OnPayFinished(orderPay)
}
} else {
@@ -95,13 +95,13 @@ func onWxpayFinished(msg *wxpay.PayResultMsg) (err error) {
return err
}
func onWxpayRefund(msg *wxpay.RefundResultMsg) (err error) {
func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) {
orderPayRefund := &model.OrderPayRefund{
RefundID: msg.ReqInfoObj.OutRefundNo,
}
db := dao.GetDB()
if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil {
if msg.ResultCode == wxpay.ResponseCodeSuccess {
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
orderPayRefund.Status = model.RefundStatusYes
} else {
orderPayRefund.Status = model.RefundStatusFailed
@@ -126,13 +126,14 @@ func onWxpayRefund(msg *wxpay.RefundResultMsg) (err error) {
return err
}
func refundOrderByWX(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string) (orderPayRefund *model.OrderPayRefund, err error) {
result, err := api.WxpayAPI.PayRefund(&wxpay.PayRefundParam{
func refundOrderByWX(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) {
result, err := api.WxpayAPI.PayRefund(&wxpayapi.PayRefundParam{
OutTradeNo: orderPay.VendorOrderID,
NotifyURL: globals.WxpayNotifyURL,
OutRefundNo: refundID,
TotalFee: orderPay.TotalFee,
RefundFee: orderPay.TotalFee,
RefundFee: refundFee,
RefundDesc: wxpayapi.CData(refundDesc),
})
if err == nil {
orderPayRefund = &model.OrderPayRefund{

View File

@@ -16,9 +16,18 @@ func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
}
func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) {
order, err = partner.CurOrderManager.LoadOrder(orderID, model.VendorIDJX)
return order, err
}
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX)
if err == nil {
status = order.Status
}
return status, err
}
func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
var status int
if isAcceptIt {
@@ -86,6 +95,10 @@ func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *mode
}
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
if model.IsOrderJXTemp(order) {
} else {
err = localjx.AgreeOrRefuseCancel(ctx, order, isAgree, reason)
}
return err
}
@@ -99,6 +112,10 @@ func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.Goods
}
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
if model.IsOrderJXTemp(order) {
} else {
err = localjx.AdjustOrder(ctx, order, removedSkuList, reason)
}
return err
}
@@ -106,14 +123,6 @@ func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode strin
return vendorOrderIDs, err
}
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder) (tipFee int64, err error) {
return tipFee, err
}
func (c *PurchaseHandler) AddWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee2Add int64) (err error) {
return err
}
func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, vendorOrderID, selfTakeCode string) (err error) {
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX)
if err == nil {

View File

@@ -9,25 +9,25 @@ import (
"git.rosy.net.cn/jx-callback/business/partner"
)
func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
return err
}
// func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
// return err
// }
func (p *PurchaseHandler) GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*partner.BareCategoryInfo, err error) {
return cats, err
}
func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
return nil
}
// func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
// return nil
// }
func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
return nil
}
// func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
// return nil
// }
func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) {
return err
}
// func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) {
// return err
// }
func (p *PurchaseHandler) CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) {
return err
@@ -45,21 +45,21 @@ func (p *PurchaseHandler) ReorderCategories2(ctx *jxcontext.Context, vendorOrgCo
return err
}
func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
return err
}
// func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// return err
// }
// func (p *PurchaseHandler) ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) {
// return skuNameExt, err
// }
func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
return err
}
// func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// return err
// }
func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
return err
}
// func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
// return err
// }
func (p *PurchaseHandler) CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) {
return err

View File

@@ -13,6 +13,17 @@ import (
"git.rosy.net.cn/jx-callback/globals/api"
)
func jxActType2Mtwm(actType int) int {
if actType == model.ActSkuDirectDown {
actType = mtwmapi.RetailActTypeDirectDown
} else if actType == model.ActSkuSecKill {
actType = mtwmapi.RetailActTypeSecKill
} else {
actType = 0
}
return actType
}
func actOrderRules2Mtwm(actOrderRules []*model.ActOrderRule) (actDetails []*mtwmapi.FullDiscountActDetail) {
for _, v := range actOrderRules {
actDetails = append(actDetails, &mtwmapi.FullDiscountActDetail{
@@ -73,7 +84,7 @@ func createOneShopAct(act *model.Act2, vendorStoreID string, actStoreSku []*mode
actData := storeSku2ActData(act, actStoreSku, isCreateOrUpdate)
if len(actData) > 0 {
if globals.EnableMtwmStoreWrite {
actResult, err2 := api.MtwmAPI.RetailDiscountBatchSave(vendorStoreID, actData)
actResult, err2 := api.MtwmAPI.RetailDiscountBatchSave(vendorStoreID, jxActType2Mtwm(act.Type), actData)
globals.SugarLogger.Debugf("mtwm createOneShopAct err2:%v", err2)
if err = err2; err != nil {
return err
@@ -96,10 +107,10 @@ func createOneShopAct(act *model.Act2, vendorStoreID string, actStoreSku []*mode
return err
}
func cancelOneShopAct(ctx *jxcontext.Context, actStoreSku []*model.ActStoreSku2) (err error) {
func cancelOneShopAct(ctx *jxcontext.Context, act *model.Act2, actStoreSku []*model.ActStoreSku2) (err error) {
if list := storeSku2ActData4Delete(actStoreSku, nil /*model.IsSyncStatusNeedDelete*/); len(list) > 0 {
if globals.EnableMtwmStoreWrite {
err = api.MtwmAPI.RetailDiscountDelete(actStoreSku[0].VendorStoreID, list)
err = api.MtwmAPI.RetailDiscountDelete(actStoreSku[0].VendorStoreID, jxActType2Mtwm(act.Type), list)
}
}
return err
@@ -129,13 +140,13 @@ func createSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.A
return getActStoreSkuFromTaskResult(result), err
}
func cancelSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, actStoreSku []*model.ActStoreSku2) (canceledList []*model.ActStoreSku2, err error) {
func cancelSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (canceledList []*model.ActStoreSku2, err error) {
globals.SugarLogger.Debugf("mtwm cancelSkuAct")
actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
task := tasksch.NewParallelTask("mtwm cancelSkuAct", nil, ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
actStoreSkuList := batchItemList[0].([]*model.ActStoreSku2)
if err = cancelOneShopAct(ctx, actStoreSkuList); err == nil {
if err = cancelOneShopAct(ctx, act, actStoreSkuList); err == nil {
retVal = []interface{}{actStoreSkuList}
}
return retVal, err
@@ -162,7 +173,7 @@ func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITa
}
err = func() (err error) {
if model.IsSyncStatusDelete(act.SyncStatus) {
canceledList, err2 := cancelSkuAct(ctx, nil, actStoreSkuList)
canceledList, err2 := cancelSkuAct(ctx, nil, act, actStoreSkuList)
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, canceledList, model.SyncFlagModifiedMask)...)
if err = err2; err == nil {
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
@@ -183,7 +194,7 @@ func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITa
}
}
if len(actStoreSkuList4Delete) > 0 {
deletedList, err2 := cancelSkuAct(ctx, nil, actStoreSkuList4Delete)
deletedList, err2 := cancelSkuAct(ctx, nil, act, actStoreSkuList4Delete)
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, deletedList, model.SyncFlagDeletedMask)...)
if err = err2; err != nil {
return err

View File

@@ -65,7 +65,7 @@ var (
fakeFinishedPickup: model.OrderStatusFinishedPickup,
fakeOrderAdjustFinished: model.OrderStatusAdjust,
fakeRefuseUserApplyCancel: model.OrderStatusUnlocked,
fakeRefuseUserApplyCancel: model.OrderStatusVendorRejectCancel,
fakeUserApplyCancel: model.OrderStatusApplyCancel,
fakeUserUndoApplyCancel: model.OrderStatusUndoApplyCancel,
fakeMerchantAgreeApplyCancel: model.OrderStatusCanceled,
@@ -99,6 +99,14 @@ func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *
return order, err
}
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
status, err = api.MtwmAPI.OrderViewStatus(utils.Str2Int64(vendorOrderID))
if err == nil {
status = p.getStatusFromVendorStatus(utils.Int2Str(status))
}
return status, err
}
func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
result := orderData
vendorOrderID := utils.Int64ToStr(utils.MustInterface2Int64(result["order_id"]))
@@ -127,6 +135,7 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo
OrderCreatedAt: getTimeFromTimestamp(utils.MustInterface2Int64(result["ctime"])),
OriginalData: string(utils.MustMarshal(result)),
ActualPayPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(result["total"])),
BaseFreightMoney: jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["shipping_fee"], 0)),
InvoiceTitle: utils.Interface2String(result["invoice_title"]),
InvoiceTaxerID: utils.Interface2String(result["taxpayer_id"]),
@@ -746,3 +755,18 @@ func (p *PurchaseHandler) onNumberDowngrade(msg *mtwmapi.CallbackMsg) (response
tasksch.HandleTask(task, nil, true).Run()
return response
}
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
orderInfo, err := api.MtwmAPI.GetDistributeOrderDetail(vendorOrderID, vendorStoreID)
if err == nil {
tipFee = jxutils.StandardPrice2Int(orderInfo.TipAmount)
}
return tipFee, err
}
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
if globals.EnableMtwmStoreWrite {
err = api.MtwmAPI.OrderModityTips(vendorOrderID, vendorStoreID, jxutils.IntPrice2Standard(tipFee))
}
return err
}

View File

@@ -18,6 +18,14 @@ func TestGetOrder(t *testing.T) {
t.Log(utils.Format4Output(result, false))
}
func TestGetOrderStatus(t *testing.T) {
result, err := CurPurchaseHandler.GetOrderStatus("", "71884881906304496")
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}
func TestListOrders(t *testing.T) {
result, err := CurPurchaseHandler.ListOrders(jxcontext.AdminCtx, "", nil, time.Now(), "4626746")
if err != nil {

View File

@@ -101,6 +101,7 @@ func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName strin
}
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) {
var name string
if db == nil {
db = dao.GetDB()
}
@@ -115,10 +116,16 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
return err
}
mergedStoreStatus := jxutils.MergeStoreStatus(storeDetail.Status, storeDetail.VendorStatus)
name = remoteStoreInfo.Name
if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
if storeDetail.VendorStoreName != "" {
name = storeDetail.VendorStoreName
}
}
// openLevel, isOnline := bizStatusJX2Mtwm(mergedStoreStatus)
params := map[string]interface{}{
"name": remoteStoreInfo.Name, //jxutils.ComposeStoreName(storeDetail.Store.Name, model.VendorIDMTWM),
"address": storeDetail.Address, // 美团好像地址也不能改的?
"name": name, //jxutils.ComposeStoreName(storeDetail.Store.Name, model.VendorIDMTWM),
"address": storeDetail.Address, // 美团好像地址也不能改的?
"longitude": jxutils.IntCoordinate2Standard(int(remoteStoreInfo.Longitude)),
"latitude": jxutils.IntCoordinate2Standard(int(remoteStoreInfo.Latitude)),
"phone": storeDetail.Tel1,
@@ -127,6 +134,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
"open_level": remoteStoreInfo.OpenLevel,
"is_online": remoteStoreInfo.IsOnline,
"third_tag_name": remoteStoreInfo.ThirdTagName,
"promotion_info": storeDetail.PromoteInfo,
}
// globals.SugarLogger.Debug(utils.Format4Output(params, false))
if globals.EnableMtwmStoreWrite {

View File

@@ -44,7 +44,7 @@ func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
case partner.FuncCreateStoreSkus:
batchSize = 1 // 可考虑用批量操作
case partner.FuncUpdateStoreSkus:
batchSize = mtwmapi.MaxStoreSkuBatchSize
batchSize = 1 // mtwmapi.MaxStoreSkuBatchSize
case partner.FuncGetStoreSkusFullInfo:
batchSize = 1
}
@@ -291,7 +291,9 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI
skus[0]["price"] = foodData["price"]
}
skus[0]["stock"] = stockCount2Mtwm(model.MaxStoreSkuStockQty)
skus[0]["upc"] = storeSku.Upc
if storeSku.Upc != "" {
skus[0]["upc"] = storeSku.Upc
}
if foodData["tag_id"] != nil {
skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用
}
@@ -432,7 +434,9 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas
if err != nil {
return nil, err
}
skuNameList = append(skuNameList, vendorSku2Jx(skuInfo))
if skuName := vendorSku2Jx(skuInfo); skuName != nil {
skuNameList = append(skuNameList, skuName)
}
} else {
var storeSkuMap map[string]*partner.StoreSkuInfo
if storeSkuList != nil {
@@ -449,7 +453,9 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas
} else {
for _, v := range result {
if storeSkuMap[v.AppFoodCode] != nil {
skuNameList = append(skuNameList, vendorSku2Jx(v))
if skuName := vendorSku2Jx(v); skuName != nil {
skuNameList = append(skuNameList, skuName)
}
}
}
}
@@ -462,6 +468,10 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas
}
func vendorSku2Jx(appFood *mtwmapi.AppFood) (skuName *partner.SkuNameInfo) {
if len(appFood.SkuList) == 0 {
globals.SugarLogger.Warnf("vendorSku2Jx, strange appFood:%s", utils.Format4Output(appFood, true))
return nil
}
prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(appFood.Name)
vendorSku := appFood.SkuList[0]
weight := int(utils.Str2Int64WithDefault(vendorSku.Weight, 0))
@@ -507,7 +517,9 @@ func vendorSku2Jx(appFood *mtwmapi.AppFood) (skuName *partner.SkuNameInfo) {
func vendorSkuList2Jx(appFoodList []*mtwmapi.AppFood) (skuNameList []*partner.SkuNameInfo) {
for _, appFood := range appFoodList {
skuNameList = append(skuNameList, vendorSku2Jx(appFood))
if skuName := vendorSku2Jx(appFood); skuName != nil {
skuNameList = append(skuNameList, skuName)
}
}
return skuNameList
}

View File

@@ -2,6 +2,7 @@ package wsc
import (
"errors"
"fmt"
"time"
"git.rosy.net.cn/baseapi/platformapi/weimobapi"
@@ -108,6 +109,10 @@ func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *
return order, err
}
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
return 0, fmt.Errorf("未实现")
}
func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
result := orderData
vendorOrderID := utils.Int64ToStr(utils.MustInterface2Int64(result["orderNo"]))

View File

@@ -246,7 +246,7 @@ func GetRecipeDetail(ctx *jxcontext.Context, recipeID int) (recipeDetail *FoodRe
}
choiceMap := make(map[int8][]*dao.FoodRecipeItemChoiceExt)
for _, v := range itemChoiceList {
v.SkuName = jxutils.ComposeSkuName(v.Prefix, v.SkuNameName, v.Comment, v.Unit, v.SpecQuality, v.SpecUnit, 0)
v.SkuName = jxutils.ComposeSkuNameOriginal(v.Prefix, v.SkuNameName, v.Comment, v.Unit, v.SpecQuality, v.SpecUnit, 0)
choiceMap[v.Index] = append(choiceMap[v.Index], v)
}

View File

@@ -15,6 +15,7 @@ dadaAppSecret = "2c717ad914767d6e2beb3f743db9e477"
mtwmAppID = "589"
mtwmSecret = "a81eb3df418d83d6a1a4b7c572156d2f"
mtwmCallbackURL = "http://callback.jxc4.com"
mtwmCookieStr = "_lxsdk_cuid=16eb02a8a02c8-0a92cb9af9798c-3d375b01-15f900-16eb02a8a02c8; _lxsdk=16eb02a8a02c8-0a92cb9af9798c-3d375b01-15f900-16eb02a8a02c8; device_uuid=!aaa93749-2445-4e1e-b178-956ac0ea5e45; pushToken=0sMxJkF87HeJFNGInMgnpvQ3ohIqeo_UMZ8VDif29S6s*; _lx_utm=utm_source%3DBaidu%26utm_medium%3Dorganic; wpush_server_url=wss://wpush.meituan.com; acctId=26599188; token=0o7UnNs2yauqdj86R145ow78W9cT9krlWpKPmCan2z7Q*; brandId=-1; wmPoiId=-1; isOfflineSelfOpen=0; city_id=0; isChain=1; existBrandPoi=true; ignore_set_router_proxy=true; region_id=; region_version=0; newCategory=false; bsid=PgNahlgfXvqnBiqv9tIi9zg7LDWtV8n70tkl_GhfueXgrLxV9BEb1rP9emUMnUUKPI6rANs_Y-chSdYLZS3KCA; cityId=510100; provinceId=510000; city_location_id=0; location_id=0; JSESSIONID=uht6v2iau9s6fx86r1ue6vzd; set_info=%7B%22wmPoiId%22%3A-1%2C%22ignoreSetRouterProxy%22%3Atrue%7D; igateApp=shangouepc; LX_SC_CONSTANT=c_nehoktcu; shopCategory=food; _lxsdk_s=16f40af4486-049-a66-a48%7C26337904%7C37"
autonaviKey = "ef64f638f31e05cb7bde28790f7309fe"
@@ -58,8 +59,8 @@ wxpayNotifyURL = "http://callback.test.jxc4.com/wxpay/msg/"
backstageHost = "http://www.jxc4.com"
wxBackstageHost = "http://wx.jxc4.com"
jdStorePageCookie = "OPJQMA7B3FTKCAUGO7FHCH5NMBGAWGGXYRNLEHYYZNGNPNIBCAM4IOEPG3NT3RIA44G5C3535Q5LGG4F4SR4AZVLGYKYTKFJJKEAOXENVBL5VXNILRP3GLNVVWA26XZ3VGSYOHA72RICMVZS3G53DTEH3LYUCSS54VI6WPOAGGDK532VYPEWWVCXUFRWENWDI4PEKM7SXBZ5BJO6DBLLERUA74YR2CVCGP4WUROCAHAMXKJ2VBGHTZYRL2DHR3BMXAHCTBAHYQLL24K5YI2PULRJL2UGAVD7VFRMEYTOXYHWCYVDXJ6HYFIPWIN3ULLXDDLN2ICON4GRK"
jd2StorePageCookie = "CK5GE5MR2UIOBOZC7BBZLLSI7MVDWPEQ4BRJTJQ2OP3ZFKYDDYTHXLZR3RDCQD6WXIWTDOSXTP3AQEC2D3ZS24VYF7PTTKKUKN7G4XBQS3QOBGUDNLQNEY7CLSNLWZCC7LNI6GZOWOOEN72AWG53MMCURHIQRBG7CGEGVIZQNRKV2NAWXHUA2REY6NP2B3GHPO6S4H35ST5KQXRJWL5LJSIWZHXGPYA3OGPRNAHBLVVNTQE6OL2RPMHQYNXCFMU5QQERDWPFLIWKB7W4GI7GHKLYDY"
jdStorePageCookie = "YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHD6O37OTAHUCKU6ALXATYTGMHNFLM4XRLVSFUQAJR77M4URSZRKVO55243TDVXLO25PP4UYSPTTPMNRUFXDNP4WPE566Q6V4AH32F7HT"
jd2StorePageCookie = "CK5GE5MR2UIOBOZC7BBZLLSI7MVDWPEQ4BRJTJQ2OP3ZFKYDDYTFFV4XOXKLERC2UXFT44TMCUMRFP3C25HD6W3PYONTQCOML6YIZA5Z37P62UXFE655IRGYJ4ZLQIEBYQM32FABIN5RVJYZWPQWSRTZURNRLYV57XJEDWZT5UVZRYUBTN3AT6JJJJ22YHE6ZHCN6LCH27JHSRO55YA6TJH6G54IF72X3UAXCKW5P2G2MT3U6I3527NQFMAFLHXBZKQFFMYUKUHUU4GZWD4O7GO45Y"
ebaiStorePageCookieWMUSS = "B0AAFQCAAAGbhkuMCsvcyYBDkkyAxBGIBlgXAQYVwc7VwYZFkx2HDoPSmo5eV1femopWgJRawhgAALG04cg1RUmhUakBbJRdgPS0tNEhnQhNRewwuWwYYBDEFPCQSDXV5YWA6PAVRHUJ9SnVGMThYAjNjLw9pRxIbS04-XFo05AQgBl%7ERLA33vWcR73gEAKZ"
ebaiStorePageCookieWMSTOKEN = "gAALgNAAAGfBI5YEBHSQdZY1InIS8CVQU9aBU1f3VLWVQqKHAAAc5LnRLZ1QLLx0S5IuzCSX8ZQ7oUwAAUr-GEm9JpRc9AQAAsLkLHHXzuhh2lZkbyrcAAAWBESKg3ZA"
@@ -198,7 +199,7 @@ jdOrgCode = "339032"
jdToken = "84541069-fbe2-424b-b625-9b2ba1d4c9e6"
jdAppKey = "5d5577a2506f41b8b4ec520ba83490f5"
jdSecret = "0b01b9eeb15b41dab1c3d05d95c17a26"
jdStorePageCookie = "YDYCWYUGKSROMV3MKJQIFINJ5CLPYH6IRVFUMFJD3JI6VQKHX3YPHTWDIDBNMCBUKSY3P7SKAHHKR7PHQDSFRXZEWXA4XOUTALIQDGDYIEUCMDPWSYGDVT42DJ27CD27QKCR3UN7KF7EPIHGPR7GCRTBD5DAHYMIODMDYESTI4PQWPK4CSWXGB2U4Y7R57ZUWN2T5LH4LE5SSAFFJCY53F5ZPCFR2RAUWYMCKHC4Y4QRFKYYLPHHZ2B3SCDWNLTVJOU24WJL4PVF3PPYDNTOLLXDABUFAZSE6C6CNOMI6L2TAK43JJIJQRQAQUQSU537ZFLVPGBYFDJYY"
jdStorePageCookie = "YDYCWYUGKSROMV3MKJQIFINJ5CLPYH6IRVFUMFJD3JI6VQKHX3YPHTWDIDBNMCBUKSY3P7SKAHHKR7PHQDSFRXZEWXA4XOUTALIQDGDYIEUCMDPWSYGDVT42DJ27CD27QKCR3UN7KF7EPIHGPR7GCRTBD5YGNZW4AIACY4HXDMCETEWCPFKOTM4HRJBSMMQJ77SR62PYMP6RCG33IRQGP6PRCKAO4M7FUA7G2ZM2SFQ6F6WUNO5GXDJSVUELLBJT"
ebaiSource = "35957"
ebaiSecret = "10013fbb7c2ddad7"
@@ -208,6 +209,7 @@ ebaiStorePageCookieWMSTOKEN = "gAAA4OkFSZBsOayRIAnRqd24YRRVvWgRFE2w2CGtjKlAIsYg1
mtwmAppID = "4123"
mtwmSecret = "df2c88338b85f830cebce2a9eab56628"
mtwmCallbackURL = "http://callback-jxgy.jxc4.com"
mtwmCookieStr = "_lxsdk_cuid=16f413bd94fc8-0daccb808f461b-1d336b5a-13c680-16f413bd94fc8; _lxsdk=16f413bd94fc8-0daccb808f461b-1d336b5a-13c680-16f413bd94fc8; uuid=d1e8adb3d2774b89fe6e.1577347439.1.0.0; uuid_update=true; wpush_server_url=wss://wpush.meituan.com; acctId=62884810; token=0LhaIAAgrL1Hy0DDATjZqt4lRHauN_bBL3q0AvxUFUWo*; brandId=-1; wmPoiId=-1; isOfflineSelfOpen=0; city_id=0; isChain=1; existBrandPoi=true; ignore_set_router_proxy=true; region_id=; region_version=0; newCategory=false; bsid=SUVq2IfzZ53EHaTVoCE3UsmKkH5ZevxTjkwpNcaLKkbUOBkEyuZp8mPFwhgqkxsCGNjZILNj5aV8uVSQc888bg; device_uuid=!625e0297-431a-49ad-8b18-a0562c38a8eb; cityId=510100; provinceId=510000; city_location_id=0; location_id=0; pushToken=0LhaIAAgrL1Hy0DDATjZqt4lRHauN_bBL3q0AvxUFUWo*; set_info=%7B%22wmPoiId%22%3A-1%2C%22ignoreSetRouterProxy%22%3Atrue%7D; igateApp=shangouepc; LX_SC_CONSTANT=c_nehoktcu; shopCategory=food; JSESSIONID=unlrbu07lvm2s734eyedxr0j; _lxsdk_s=16f413bd950-189-8bb-8df%7C%7C33"
enableStoreWrite = true
enableJdStoreWrite = true
@@ -284,6 +286,10 @@ jdStorePageCookie = "5EOCZRXVCRXBTYD5EPV6FOXRCQWFFQO75FRMJ3BAKZ5JXY6XTJECMWXK5OZ
ebaiSource = "62289"
ebaiSecret = "d3ec2358d6a819ea"
ebaiStorePageCookieWMUSS = "AHYHAAApIX5oBXUFKFsXKEdObiclRUhTFRZ1MUh7KEMiClB7MnB5G3VvIB5KN0USAABjQ4KngBfQ4Wcj9ebWYiEHBxCyNiBT1Yc111PhQ7UBluCENnCUB0HjIzfCAaHjAKEDoscT8sDL8JDDuQD81NaQ1dW3kN1MS9DeFMPgwC2YYROVy7AV3cKhMPkQrBwA"
ebaiStorePageCookieWMSTOKEN = "UAABRL3ZhLykdGFQBBDxXVDBuYisaB3tQHjUmHlQ5cEAs5dxMdG0R-EwVILAy_CV1Vlw_nbQAA0ijuEe-F2xUzAQAAAdujHKzhohkrxY0c5LsAAH0CeSGnywAHBQAAMA"
mtwmCookieStr = "_lxsdk_cuid=169b7bc1b9fc8-05092471a96611-12376d51-1fa400-169b7bc1b9fc8; _lxsdk=169b7bc1b9fc8-05092471a96611-12376d51-1fa400-169b7bc1b9fc8; uuid=7a6a1345b4a3f7aa5f81.1553565752.1.0.0; _ga=GA1.2.285163436.1559264188; uuid_update=true; pushToken=0sz3wYPQoNug6okzOjEacuvrEWGRhuv6gL5ZWX98prCw*; device_uuid=!88124822-2b68-4425-865d-a3ffffe355af; wpush_server_url=wss://wpush.meituan.com; acctId=26535718; token=0vt6ufSF1X8GXpVq3N5zhE5FhcgONSuNTg4LiqkqEyTM*; brandId=-1; wmPoiId=2523687; isOfflineSelfOpen=0; city_id=999999; isChain=0; existBrandPoi=false; ignore_set_router_proxy=false; region_id=2000000001; region_version=1522820107; newCategory=false; bsid=g54gdBCxg9fu4t99gGLf770bFzBT_eUQXA3_FWLgDeCWrEtsNdXkJtckKTvMEthURtXVg_j0mhDauKPgDUgZyQ; cityId=510100; provinceId=510000; city_location_id=10000004; location_id=10000005; set_info=%7B%22wmPoiId%22%3A2523687%2C%22region_id%22%3A%222000000001%22%2C%22region_version%22%3A1522820107%7D; igateApp=shangouepc; shopCategory=market; LX_SC_CONSTANT=c_nehoktcu; JSESSIONID=43y9tjdcnjh2kojf6qfehvdy; _lxsdk_s=16f4145a84c-d6a-c22-64c%7C%7C19"
mtpsAppKey = "25e816550bc9484480642f19a95f13fd"
mtpsSecret = "r4$HqrKx9~=7?2Jfo,$Z~a7%~k!Au&pEdI2)oPJvSbH2ao@2N0[8wSIvtuumh_J^"

View File

@@ -287,6 +287,7 @@ func (c *ActController) RefreshPageActs() {
// @Param token header string true "认证token"
// @Param skuIDs query string true "skuID列表"
// @Param vendorID query int true "厂商ID"
// @Param types query string false "活动类型列表"
// @Param isAsync query bool false "是否异步"
// @Param isContinueWhenError query bool false "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
@@ -294,9 +295,9 @@ func (c *ActController) RefreshPageActs() {
// @router /DeleteSkusFromAct [delete]
func (c *ActController) DeleteSkusFromAct() {
c.callDeleteSkusFromAct(func(params *tActDeleteSkusFromActParams) (retVal interface{}, errCode string, err error) {
var skuIDs []int
if err = jxutils.Strings2Objs(params.SkuIDs, &skuIDs); err == nil {
retVal, err = act.DeleteSkusFromAct(params.Ctx, params.VendorID, skuIDs, params.IsAsync, params.IsContinueWhenError)
var skuIDs, types []int
if err = jxutils.Strings2Objs(params.SkuIDs, &skuIDs, params.Types, &types); err == nil {
retVal, err = act.DeleteSkusFromAct(params.Ctx, params.VendorID, types, skuIDs, params.IsAsync, params.IsContinueWhenError)
}
return retVal, "", err
})
@@ -308,6 +309,7 @@ func (c *ActController) DeleteSkusFromAct() {
// @Param type formData int true "活动类型3直降4秒杀美团当前不支持秒杀"
// @Param vendorID formData int true "厂商ID当前只支持京东0京西用于记录活动信息9"
// @Param actStoreSkuList formData string true "活动门店商品信息"
// @Param lockTime formData string false "平台价格锁定截止时间"
// @Param isAsync formData bool false "是否异步,缺省否(暂时只支持同步)"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
@@ -316,7 +318,10 @@ func (c *ActController) ForceUpdateVendorPrice() {
c.callForceUpdateVendorPrice(func(params *tActForceUpdateVendorPriceParams) (retVal interface{}, errCode string, err error) {
var actStoreSkuList []*act.ActStoreSkuParam
if err = jxutils.Strings2Objs(params.ActStoreSkuList, &actStoreSkuList); err == nil {
retVal, err = act.ForceUpdateVendorPrice(params.Ctx, params.VendorID, params.Type, actStoreSkuList, params.IsAsync)
timeList, err2 := jxutils.BatchStr2Time(params.LockTime)
if err = err2; err == nil {
retVal, err = act.ForceUpdateVendorPrice(params.Ctx, params.VendorID, params.Type, actStoreSkuList, timeList[0], params.IsAsync)
}
}
return retVal, "", err
})

View File

@@ -191,6 +191,9 @@ func (c *SkuController) UpdateSkuName() {
// dummySkuName := &model.SkuName{}
payload := make(map[string]interface{})
if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil {
delete(payload, "exPrefix")
delete(payload, "exPrefixBegin")
delete(payload, "exPrefixEnd")
retVal, err = cms.UpdateSkuName(params.Ctx, params.NameID, payload)
}
return retVal, "", err
@@ -375,3 +378,40 @@ func (c *SkuController) GetStoreSkuSalesInfo() {
return retVal, "", err
})
}
// @Title 根据名字查询京东商品UPC信息
// @Description 根据名字查询京东商品UPC信息
// @Param token header string true "认证token"
// @Param name query string false "商品名"
// @Param upcCode query string false "upcCode,不支持模糊"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetJdUpcCodeByName [get]
func (c *SkuController) GetJdUpcCodeByName() {
c.callGetJdUpcCodeByName(func(params *tSkuGetJdUpcCodeByNameParams) (retVal interface{}, errCode string, err error) {
retVal, err = cms.GetJdUpcCodeByName(params.Ctx, params.Name, params.UpcCode)
return retVal, "", err
})
}
// @Title 批量设置商品额外前缀
// @Description 批量设置商品额外前缀
// @Param token header string true "认证token"
// @Param nameIDs formData string true "商品nameIDs"
// @Param exPrefix formData string true "商品额外前缀"
// @Param fromDate formData string true "生效开始时间,格式 2006-01-01 "
// @Param toDate formData string true "生效结束时间,格式 2006-01-01 "
// @Param isAsync formData bool false "是否异步"
// @Param isContinueWhenError formData bool false "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /UpdateSkuNamesExPrefix [put]
func (c *SkuController) UpdateSkuNamesExPrefix() {
c.callUpdateSkuNamesExPrefix(func(params *tSkuUpdateSkuNamesExPrefixParams) (retVal interface{}, errCode string, err error) {
var skuIDList []int
if err = jxutils.Strings2Objs(params.NameIDs, &skuIDList); err == nil {
retVal, err = cms.UpdateSkuNamesExPrefix(params.Ctx, skuIDList, params.ExPrefix, params.FromDate, params.ToDate, params.IsAsync, params.IsContinueWhenError)
}
return retVal, "", err
})
}

View File

@@ -589,20 +589,21 @@ func (c *StoreController) GetVendorStoreInfo() {
// @Description 查询门店价格评分
// @Param token header string true "认证token"
// @Param storeIDs formData string false "门店列表"
// @Param vendorIDs formData string false "厂商列表"
// @Param snapDate formData string true "时间默认前一天格式2006-01-02"
// @Param fromScore formData int false "分数范围开始 默认0"
// @Param toScore formData int false "分数范围结束 默认100"
// @Param sort formData int false "排序,默认降序0为降序,1为升序"
// @Param sort formData int false "分数排序,-1降序-升序 ,直降排序,-2降序2升序,秒杀排序,-3降序,3升序"
// @Param offset formData int false "门店列表起始序号以0开始缺省为0"
// @Param pageSize formData int false "门店列表页大小缺省为50-1表示全部"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetStorePriceScore [post]
func (c *StoreController) GetStorePriceScore() {
var storeIDList []int
var storeIDList, vendorIDList []int
c.callGetStorePriceScore(func(params *tStoreGetStorePriceScoreParams) (retVal interface{}, errCode string, err error) {
if jxutils.Strings2Objs(params.StoreIDs, &storeIDList); err == nil {
retVal, err = cms.GetStorePriceScore(params.Ctx, storeIDList, params.FromScore, params.ToScore, params.Sort, params.SnapDate, params.Offset, params.PageSize)
if jxutils.Strings2Objs(params.StoreIDs, &storeIDList, params.VendorIDs, &vendorIDList); err == nil {
retVal, err = cms.GetStorePriceScore(params.Ctx, storeIDList, vendorIDList, params.FromScore, params.ToScore, params.Sort, params.SnapDate, params.Offset, params.PageSize)
}
return retVal, "", err
})
@@ -611,13 +612,25 @@ func (c *StoreController) GetStorePriceScore() {
// @Title 生成门店价格分数表
// @Description 生成门店价格分数表
// @Param token header string true "认证token"
// @Param forRefresh formData bool true "是否是刷新中位价重新生成分数表"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /CreateStorePriceScore [post]
func (c *StoreController) CreateStorePriceScore() {
c.callCreateStorePriceScore(func(params *tStoreCreateStorePriceScoreParams) (retVal interface{}, errCode string, err error) {
err = cms.CreateStorePriceScore(params.Ctx, params.ForRefresh)
err = cms.CreateStorePriceScore(params.Ctx)
return retVal, "", err
})
}
// @Title 刷新store_map的京东等级
// @Description 刷新store_map的京东等级
// @Param token header string true "认证token"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /RefreshJdLevel [post]
func (c *StoreController) RefreshJdLevel() {
c.callRefreshJdLevel(func(params *tStoreRefreshJdLevelParams) (retVal interface{}, errCode string, err error) {
err = cms.RefreshJdLevel(params.Ctx)
return retVal, "", err
})
}

View File

@@ -43,6 +43,7 @@ type StoreSkuController struct {
// @Param jdSyncStatus query int false "京东同步标识"
// @Param ebaiSyncStatus query int false "饿百同步标识"
// @Param mtwmSyncStatus query int false "美团外卖同步标识"
// @Param lockTime query string false "价格锁定时间"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetStoreSkus [get]
@@ -83,6 +84,7 @@ func (c *StoreSkuController) GetStoreSkus() {
// @Param jdSyncStatus query int false "京东同步标识"
// @Param ebaiSyncStatus query int false "饿百同步标识"
// @Param mtwmSyncStatus query int false "美团外卖同步标识"
// @Param lockTime query string false "价格锁定时间"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetStoresSkus [get,post]
@@ -448,7 +450,7 @@ func (c *StoreSkuController) GetMissingStoreSkuFromOrder() {
// @Title 根据门店信息查找推荐商品(按销量)
// @Description 根据门店信息查找推荐商品(按销量)
// @Param token header string false "认证token"
// @Param token header string true "认证token"
// @Param storeIDs query string true "门店列表"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
@@ -463,18 +465,33 @@ func (c *StoreSkuController) GetTopSkusByStoreIDs() {
})
}
// @Title 根据城市信息查找推荐商品(按销量)
// @Description 根据城市信息查找推荐商品(按销量)
// @Param token header string true "认证token"
// @Param cityCode query int true "城市id"
// @Param storeID query int false "门店id"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetTopSkusByCityCode [get]
func (c *StoreSkuController) GetTopSkusByCityCode() {
c.callGetTopSkusByCityCode(func(params *tStoreSkuGetTopSkusByCityCodeParams) (retVal interface{}, errCode string, err error) {
retVal, err = cms.GetTopSkusByCityCode(params.Ctx, params.CityCode, params.StoreID)
return retVal, "", err
})
}
// @Title 根据门店信息查找推荐分类(按商品销量)
// @Description 根据门店信息查找推荐分类(按商品销量)
// @Param token header string false "认证token"
// @Param token header string true "认证token"
// @Param storeIDs query string true "门店列表"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetTopCategorysByStoreIDs [get]
func (c *StoreSkuController) GetTopCategorysByStoreIDs() {
// @router /GetTopCategoriesByStoreIDs [get]
func (c *StoreSkuController) GetTopCategoriesByStoreIDs() {
var storeIDList []int
c.callGetTopCategorysByStoreIDs(func(params *tStoreSkuGetTopCategorysByStoreIDsParams) (retVal interface{}, errCode string, err error) {
c.callGetTopCategoriesByStoreIDs(func(params *tStoreSkuGetTopCategoriesByStoreIDsParams) (retVal interface{}, errCode string, err error) {
if jxutils.Strings2Objs(params.StoreIDs, &storeIDList); err == nil {
retVal, err = cms.GetTopCategorysByStoreIDs(params.Ctx, storeIDList)
retVal, err = cms.GetTopCategoriesByStoreIDs(params.Ctx, storeIDList)
}
return retVal, "", err
})
@@ -517,3 +534,77 @@ func (c *StoreSkuController) RefreshJxPriceByExcel() {
return retVal, "", err
})
}
// @Title 根据Excel中SkuID批量关注商品
// @Description 根据Excel中SkuID批量关注商品
// @Param token header string true "认证token"
// @Param isAsync formData bool true "是否异步,缺省是同步"
// @Param isContinueWhenError formData bool true "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /FocusStoreSkusByExcel [post]
func (c *StoreSkuController) FocusStoreSkusByExcel() {
c.callFocusStoreSkusByExcel(func(params *tStoreSkuFocusStoreSkusByExcelParams) (retVal interface{}, errCode string, err error) {
r := c.Ctx.Request
files := r.MultipartForm.File["userfiles"]
retVal, err = cms.FocusStoreSkusByExcel(params.Ctx, files, params.IsAsync, params.IsContinueWhenError)
return retVal, "", err
})
}
// @Title 得到门店的分类列表
// @Description 得到门店的分类列表(按商品销量)
// @Param token header string true "认证token"
// @Param storeID query int true "门店ID"
// @Param parentID query int false "父分类id"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetStoreCategories [get]
func (c *StoreSkuController) GetStoreCategories() {
c.callGetStoreCategories(func(params *tStoreSkuGetStoreCategoriesParams) (retVal interface{}, errCode string, err error) {
if params.MapData["parentID"] == nil {
params.ParentID = -1
}
retVal, err = cms.GetStoreCategories(params.Ctx, params.StoreID, params.ParentID)
return retVal, "", err
})
}
// @Title 获取各平台所有门店某商品的价格
// @Description 获取各平台所有门店某商品的价格
// @Param token header string true "认证token"
// @Param skuID formData int true "商品ID"
// @Param vendorIDs 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 /GetVendorStoreSkuPrice [post]
func (c *StoreSkuController) GetVendorStoreSkuPrice() {
var vendorIDList []int
c.callGetVendorStoreSkuPrice(func(params *tStoreSkuGetVendorStoreSkuPriceParams) (retVal interface{}, errCode string, err error) {
if jxutils.Strings2Objs(params.VendorIDs, &vendorIDList); err == nil {
retVal, err = cms.GetVendorStoreSkuPrice(params.Ctx, vendorIDList, params.SkuID, params.IsAsync, params.IsContinueWhenError)
}
return retVal, "", err
})
}
// @Title 根据skuID关注商品价格为中位价部分可售
// @Description 根据skuID关注商品价格为中位价部分可售
// @Param token header string true "认证token"
// @Param skuIDs 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 /FocusStoreSkusBySku [post]
func (c *StoreSkuController) FocusStoreSkusBySku() {
var skuIDList []int
c.callFocusStoreSkusBySku(func(params *tStoreSkuFocusStoreSkusBySkuParams) (retVal interface{}, errCode string, err error) {
if jxutils.Strings2Objs(params.SkuIDs, &skuIDList); err == nil {
retVal, err = cms.FocusStoreSkusBySku(params.Ctx, skuIDList, params.IsAsync, params.IsContinueWhenError)
}
return retVal, "", err
})
}

View File

@@ -205,7 +205,7 @@ func (c *SyncController) SyncSkuNames() {
}
// @Title 删除本地没有的平台门店商品信息
// @Description 删除本地没有的平台门店商品信息
// @Description 删除本地没有的平台门店商品信息(已废弃)
// @Param token header string true "认证token"
// @Param storeIDs query string true "门店ID列表"
// @Param vendorIDs query string true "厂商ID列表"
@@ -225,7 +225,7 @@ func (c *SyncController) PruneMissingStoreSkus() {
}
// @Title 把京西有,平台无且没有待创建标记的商品加上待创建标记
// @Description 把京西有,平台无且没有待创建标记的商品加上待创建标记
// @Description 把京西有,平台无且没有待创建标记的商品加上待创建标记(已废弃)
// @Param token header string true "认证token"
// @Param storeIDs formData string false "门店ID列表"
// @Param vendorIDs formData string false "运营商ID列表(京东0 美团1 饿百3)"
@@ -244,6 +244,28 @@ func (c *SyncController) AddCreateFlagForJxStoreSku() {
})
}
// @Title 把京西有,平台无且没有待创建标记的商品加上待创建标记
// @Description 把京西有,平台无且没有待创建标记的商品加上待创建标记
// @Param token header string true "认证token"
// @Param storeIDs formData string false "门店ID列表"
// @Param vendorIDs formData string false "运营商ID列表(京东0 美团1 饿百3)"
// @Param optType formData int true "操作方式"
// @Param isForce formData bool false "是否强制刷新"
// @Param isAsync formData bool false "是否异步操作"
// @Param isContinueWhenError formData bool false "单个同步失败是否继续缺省false"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /AmendAndPruneStoreStuff [post]
func (c *SyncController) AmendAndPruneStoreStuff() {
c.callAmendAndPruneStoreStuff(func(params *tSyncAmendAndPruneStoreStuffParams) (retVal interface{}, errCode string, err error) {
var storeIDs, vendorIDs []int
if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs, params.VendorIDs, &vendorIDs); err == nil {
retVal, err = cms.CurVendorSync.AmendAndPruneStoreStuff(params.Ctx, vendorIDs, storeIDs, params.IsAsync, params.IsContinueWhenError, params.OptType, params.IsForce)
}
return retVal, "", err
})
}
// @Title 初始化多门店平台商品库(及商家分类)
// @Description 初始化多门店平台商品库(及商家分类)
// @Param token header string true "认证token"

View File

@@ -3,8 +3,10 @@ package controllers
import (
"net/http"
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/partner/delivery/dada"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego"
)
@@ -30,3 +32,21 @@ func (c *DadaDeliveryController) Msg() {
c.Abort("404")
}
}
func (c *DadaDeliveryController) Notify() {
if c.Ctx.Input.Method() == http.MethodPost {
obj, notifyResponse := api.DadaAPI.GetNotifyMsg(c.Ctx.Input.RequestBody)
if notifyResponse == nil {
err := api.DadaAPI.ConfirmRidderCancel(obj.MessageObj.OrderID, obj.MessageObj.DadaOrderID, true)
globals.SugarLogger.Debugf("dada notify, obj:%s, err:%v", utils.Format4Output(obj, false), err)
}
if notifyResponse == nil {
notifyResponse = dadaapi.SuccessNotifyResponse
} else {
c.Data["json"] = notifyResponse
c.ServeJSON()
}
} else {
c.Abort("404")
}
}

View File

@@ -19,12 +19,12 @@ type DjswController struct {
beego.Controller
}
func (c *DjswController) handleMsg(isNeedDecode bool, handler func(*jdapi.API, interface{}) *jdapi.CallbackResponse) (callbackResponse *jdapi.CallbackResponse) {
callbackMsg, mapData, callbackResponse := jdapi.GetCallbackMsg2(getUsefulRequest(c.Ctx))
func (c *DjswController) handleMsg(handler func(*jdapi.API, interface{}) *jdapi.CallbackResponse) (callbackResponse *jdapi.CallbackResponse) {
callbackMsg, mapData, callbackResponse := jdapi.GetCallbackMsg(getUsefulRequest(c.Ctx))
globals.SugarLogger.Debug(utils.Format4Output(callbackMsg, true))
if callbackResponse == nil {
if jdAPI := jd.GetAPIByAppKey(callbackMsg.AppKey); jdAPI != nil {
if callbackResponse = jdAPI.CheckCallbackValidation2(mapData, callbackMsg.Sign); callbackResponse == nil {
if jdAPI := jd.GetAPI(jd.AppKey2OrgCode(callbackMsg.AppKey)); jdAPI != nil {
if callbackResponse = jdAPI.CheckCallbackValidation(mapData, callbackMsg.Sign); callbackResponse == nil {
callbackResponse = handler(jdAPI, callbackMsg.Param)
}
} else {
@@ -34,9 +34,9 @@ func (c *DjswController) handleMsg(isNeedDecode bool, handler func(*jdapi.API, i
return callbackResponse
}
func (c *DjswController) orderStatus(isCancelOrder bool) {
func (c *DjswController) orderStatus() {
if c.Ctx.Input.Method() == http.MethodPost {
callbackResponse := c.handleMsg(isCancelOrder, func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse := c.handleMsg(func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse = jd.OnOrderMsg(obj.(*jdapi.CallbackOrderMsg))
return callbackResponse
})
@@ -48,48 +48,52 @@ func (c *DjswController) orderStatus(isCancelOrder bool) {
}
func (c *DjswController) NewOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) OrderAdjust() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) OrderWaitOutStore() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) PickFinishOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) DeliveryOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) FinishOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) LockOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) UnlockOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) UserCancelOrder() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) ApplyCancelOrder() {
c.orderStatus(true)
c.orderStatus()
}
func (c *DjswController) VenderAuditApplyCancelOrder() {
c.orderStatus()
}
func (c *DjswController) PushDeliveryStatus() {
if c.Ctx.Input.Method() == http.MethodPost {
callbackResponse := c.handleMsg(true, func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse := c.handleMsg(func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse = jd.OnWaybillMsg(obj.(*jdapi.CallbackDeliveryStatusMsg))
return callbackResponse
})
@@ -101,7 +105,7 @@ func (c *DjswController) PushDeliveryStatus() {
}
func (c *DjswController) OrderCommentPush() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) Token() {
@@ -116,7 +120,7 @@ func (c *DjswController) Token() {
func (c *DjswController) StockIsHave() {
// globals.SugarLogger.Info(string(c.Ctx.Input.RequestBody))
if c.Ctx.Input.Method() == http.MethodPost {
callbackResponse := c.handleMsg(true, func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse := c.handleMsg(func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
return callbackResponse
})
c.Data["json"] = c.transferResponse("StockIsHave", callbackResponse)
@@ -128,7 +132,7 @@ func (c *DjswController) StockIsHave() {
func (c *DjswController) SinglePromoteCreate() {
if c.Ctx.Input.Method() == http.MethodPost {
callbackResponse := c.handleMsg(false, func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse := c.handleMsg(func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse = jd.OnActMsg(obj.(*jdapi.CallbackOrderMsg))
return callbackResponse
})
@@ -141,7 +145,7 @@ func (c *DjswController) SinglePromoteCreate() {
func (c *DjswController) StoreCrud() {
if c.Ctx.Input.Method() == http.MethodPost {
callbackResponse := c.handleMsg(false, func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse := c.handleMsg(func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) {
callbackResponse = jd.OnStoreMsg(obj.(*jdapi.CallbackOrderMsg))
return callbackResponse
})
@@ -188,11 +192,11 @@ func (c *DjswController) NewAfterSaleBill() {
}
func (c *DjswController) AfterSaleBillStatus() {
c.orderStatus(false)
c.orderStatus()
}
func (c *DjswController) OrderAccounting() {
c.orderStatus(false)
c.orderStatus()
}
func getUsefulRequest(ctx *context.Context) *http.Request {
@@ -208,3 +212,7 @@ func (c *DjswController) nullOperation() {
func (c *DjswController) UpdateSku() {
c.nullOperation()
}
func (c *DjswController) OrderAddTips() {
c.orderStatus()
}

View File

@@ -220,12 +220,29 @@ func (c *OrderController) GetOrderInfo() {
// @Param vendorOrderID query string true "订单ID"
// @Param vendorID query int true "订单所属的厂商ID"
// @Param isNotEnded query bool false "是否只是没有结束的运单"
// @Param isGetPos query bool false "是否得到骑手位置"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetOrderWaybillInfo [get]
func (c *OrderController) GetOrderWaybillInfo() {
c.callGetOrderWaybillInfo(func(params *tOrderGetOrderWaybillInfoParams) (retVal interface{}, errCode string, err error) {
retVal, err = orderman.FixedOrderManager.GetOrderWaybillInfo(params.Ctx, params.VendorOrderID, params.VendorID, params.IsNotEnded)
retVal, err = orderman.FixedOrderManager.GetOrderWaybillInfo(params.Ctx, params.VendorOrderID, params.VendorID, params.IsNotEnded, params.IsGetPos)
return retVal, "", err
})
}
// @Title 补全遗漏的订单
// @Description 补全遗漏的订单
// @Param token header string true "认证token"
// @Param vendorOrderID formData string true "订单ID"
// @Param vendorID formData int true "订单所属的厂商ID"
// @Param tipFee formData int true "小费"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /UpdateOrderWaybillTip [post]
func (c *OrderController) UpdateOrderWaybillTip() {
c.callUpdateOrderWaybillTip(func(params *tOrderUpdateOrderWaybillTipParams) (retVal interface{}, errCode string, err error) {
err = defsch.FixedScheduler.SetOrderWaybillTip(params.Ctx, params.VendorOrderID, params.VendorID, int64(params.TipFee))
return retVal, "", err
})
}
@@ -514,7 +531,7 @@ func (c *OrderController) GetPrinterStatus() {
})
}
func skuList2Map(skuList []*model.OrderSku) (skuCount int, skuMap map[int64]*model.OrderSku) {
func skuList2Map(skuList []*model.OrderSku) (skuCount int, skuMap map[int64]*model.OrderSku, outSkuList []*model.OrderSku) {
skuMap = make(map[int64]*model.OrderSku)
for _, sku := range skuList {
skuCount += sku.Count
@@ -524,12 +541,13 @@ func skuList2Map(skuList []*model.OrderSku) (skuCount int, skuMap map[int64]*mod
if skuMap[index] == nil {
tmpSku := *sku
skuMap[index] = &tmpSku
outSkuList = append(outSkuList, skuMap[index])
} else {
skuMap[index].Count += sku.Count
}
}
}
return skuCount, skuMap
return skuCount, skuMap, outSkuList
}
func getSkuFromMap(skuMap map[int64]*model.OrderSku, skuID, actID int) (sku *model.OrderSku) {
@@ -554,6 +572,7 @@ func (c *OrderController) AdjustOrder() {
var skuList []*model.OrderSku
err = jxutils.Strings2Objs(params.RemovedSkuInfo, &skuList)
if err == nil {
_, _, skuList = skuList2Map(skuList)
var order *model.GoodsOrder
order, err = partner.CurOrderManager.LoadOrder(params.VendorOrderID, params.VendorID)
if err == nil {
@@ -780,6 +799,7 @@ func (c *OrderController) PartRefundOrder() {
var skuList []*model.OrderSku
err = jxutils.Strings2Objs(params.RefundSkuList, &skuList)
if err == nil {
_, _, skuList = skuList2Map(skuList)
var order *model.GoodsOrder
order, err = partner.CurOrderManager.LoadOrder(params.VendorOrderID, params.VendorID)
if err == nil {
@@ -798,7 +818,7 @@ func (c *OrderController) PartRefundOrder() {
}
func fillSkuList(skuList, orderSkuList []*model.OrderSku) (isSame bool, err error) {
skuCount, orderSkuMap := skuList2Map(orderSkuList)
skuCount, orderSkuMap, _ := skuList2Map(orderSkuList)
skuCount2 := 0
for _, sku := range skuList {
skuCount2 += sku.Count
@@ -875,3 +895,33 @@ func (c *OrderController) RefreshOrdersWithoutJxStoreID() {
return retVal, "", err
})
}
// @Title 获取投诉原因
// @Description 获取投诉原因
// @Param token header string true "认证token"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetComplaintReasons [get]
func (c *OrderController) GetComplaintReasons() {
c.callGetComplaintReasons(func(params *tOrderGetComplaintReasonsParams) (retVal interface{}, errCode string, err error) {
retVal = orderman.GetComplaintReasons()
return retVal, "", err
})
}
// @Title 投诉骑手(三方运送)
// @Description 投诉骑手(三方运送)
// @Param token header string true "认证token"
// @Param vendorOrderID formData string true "订单ID"
// @Param vendorID formData int true "订单所属厂商ID"
// @Param waybillVendorID formData int true "运单所属厂商ID"
// @Param complaintID formData int true "投诉原因ID"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /ComplaintRider [post]
func (c *OrderController) ComplaintRider() {
c.callComplaintRider(func(params *tOrderComplaintRiderParams) (retVal interface{}, errCode string, err error) {
err = orderman.ComplaintRider(params.Ctx, params.VendorOrderID, params.VendorID, params.WaybillVendorID, params.ComplaintID)
return retVal, "", err
})
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"net/http"
"git.rosy.net.cn/baseapi/platformapi/wxpay"
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
"git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego"
@@ -17,19 +17,19 @@ type WXPayController struct {
func (c *WXPayController) Msg() {
if c.Ctx.Input.Method() == http.MethodPost {
msg, callbackResponse := api.WxpayAPI.GetCallbackMsg(c.Ctx.Request)
// globals.SugarLogger.Debugf("wxpay callback msg:%s, callbackResponse:%s, %t", utils.Format4Output(msg, true), utils.Format4Output(callbackResponse, true), callbackResponse == nil)
// globals.SugarLogger.Debugf("wxpayapi callback msg:%s, callbackResponse:%s, %t", utils.Format4Output(msg, true), utils.Format4Output(callbackResponse, true), callbackResponse == nil)
var err error
if callbackResponse == nil {
if msg.MsgType == wxpay.MsgTypeUnkown {
if msg.MsgType == wxpayapi.MsgTypeUnkown {
err = fmt.Errorf("未知的微信支付回调类型:%d", msg.MsgType)
} else {
err = localjx.OnWxPayCallback(msg)
}
}
if callbackResponse == nil {
callbackResponse = wxpay.SuccessResponse
callbackResponse = wxpayapi.SuccessResponse
} else if err != nil {
callbackResponse = wxpay.Err2CallbackResponse(err, "")
callbackResponse = wxpayapi.Err2CallbackResponse(err, "")
}
c.Data["xml"] = callbackResponse
c.ServeXML()

Some files were not shown because too many files have changed in this diff Show More