Merge branch 'master' into get-store
This commit is contained in:
355
business/jxstore/act/act.go
Normal file
355
business/jxstore/act/act.go
Normal file
@@ -0,0 +1,355 @@
|
||||
package act
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
)
|
||||
|
||||
const (
|
||||
ActionTypeNA = 0
|
||||
)
|
||||
|
||||
type ActOrderRuleParam struct {
|
||||
SalePrice int64 `orm:"" json:"salePrice"` // 满的价格
|
||||
DeductPrice int64 `orm:"" json:"deductPrice"` // 减的价格
|
||||
}
|
||||
|
||||
type ActStoreSkuParam struct {
|
||||
Action int // -1删除,1修改,2新增
|
||||
|
||||
StoreID int `orm:"column(store_id)" json:"storeID"`
|
||||
SkuID int `orm:"column(sku_id)" json:"skuID"`
|
||||
|
||||
PricePercentage int `orm:"" json:"pricePercentage"` // 单品级活动用,SKU级的价格比例,非0覆盖Act中的PricePercentage
|
||||
ActPrice int64 `orm:"" json:"actPrice"` // 单品级活动用,SKU级指定的价格,非0覆盖CustomPricePercentage与Act中的PricePercentage
|
||||
|
||||
Stock int `orm:"" json:"stock"` // 订单级活动用
|
||||
}
|
||||
|
||||
type ActDetail struct {
|
||||
model.Act2
|
||||
}
|
||||
|
||||
func ActStoreSkuParam2Map(actStoreSku []*ActStoreSkuParam) (actStoreSkuMap map[int][]*ActStoreSkuParam) {
|
||||
if len(actStoreSku) > 0 {
|
||||
for _, v := range actStoreSku {
|
||||
actStoreSkuMap[v.StoreID] = append(actStoreSkuMap[v.StoreID], v)
|
||||
}
|
||||
}
|
||||
return actStoreSkuMap
|
||||
}
|
||||
|
||||
func genStoreSkuMapKey(storeID, skuID int) int64 {
|
||||
return int64(storeID) + int64(skuID)*1000000
|
||||
}
|
||||
|
||||
func ActStoreSkuParam2Model(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actStoreSku []*ActStoreSkuParam) (actMapList []*model.ActMap, actStoreMapList []*model.ActStoreMap, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap, err error) {
|
||||
if len(actStoreSku) > 0 {
|
||||
storeIDMap := make(map[int]int)
|
||||
skuIDMap := make(map[int]int)
|
||||
storeSkuParamMap := make(map[int][]*ActStoreSkuParam)
|
||||
for _, v := range actStoreSku {
|
||||
storeIDMap[v.StoreID] = 1
|
||||
skuIDMap[v.SkuID] = 1
|
||||
storeSkuParamMap[v.StoreID] = append(storeSkuParamMap[v.StoreID], v)
|
||||
}
|
||||
db := dao.GetDB()
|
||||
|
||||
storeSkuList, err2 := dao.GetStoresSkusInfo(db, jxutils.IntMap2List(storeIDMap), jxutils.IntMap2List(skuIDMap))
|
||||
if err = err2; err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
storeSkuMap := make(map[int64]*model.StoreSkuBind)
|
||||
for _, v := range storeSkuList {
|
||||
storeSkuMap[genStoreSkuMapKey(v.StoreID, v.SkuID)] = v
|
||||
}
|
||||
|
||||
wholeValidVendorMap := make(map[int]int)
|
||||
for storeID, oneStoreSkuParam := range storeSkuParamMap {
|
||||
validVendorMap := make(map[int]int)
|
||||
validSkuMap := make(map[int]int)
|
||||
for _, vendorID := range vendorIDs {
|
||||
storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID)
|
||||
if err = err2; err == nil {
|
||||
for _, v := range oneStoreSkuParam {
|
||||
if storeSkuInfo := storeSkuMap[genStoreSkuMapKey(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
|
||||
validVendorMap[vendorID] = 1
|
||||
validSkuMap[v.SkuID] = 1
|
||||
actSkuMap := &model.ActStoreSkuMap{
|
||||
ActID: act.ID,
|
||||
StoreID: storeID,
|
||||
SkuID: v.SkuID,
|
||||
VendorID: vendorID,
|
||||
|
||||
SyncStatus: model.SyncFlagNewMask,
|
||||
}
|
||||
if v.ActPrice != 0 {
|
||||
actSkuMap.ActualActPrice = v.ActPrice
|
||||
} else {
|
||||
percentage := act.PricePercentage
|
||||
if v.PricePercentage != 0 {
|
||||
percentage = v.PricePercentage
|
||||
}
|
||||
percentage = percentage * int(storeDetail.PricePercentage) / 100
|
||||
actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(storeSkuInfo.Price, percentage, 0))
|
||||
}
|
||||
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
|
||||
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
|
||||
}
|
||||
}
|
||||
} else if !dao.IsNoRowsError(err) {
|
||||
return nil, nil, nil, nil, err
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range oneStoreSkuParam {
|
||||
if validSkuMap[v.SkuID] == 1 {
|
||||
if storeSkuInfo := storeSkuMap[genStoreSkuMapKey(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
|
||||
storeSku := &model.ActStoreSku{
|
||||
ActID: act.ID,
|
||||
StoreID: v.StoreID,
|
||||
SkuID: v.SkuID,
|
||||
OriginalPrice: int64(storeSkuInfo.Price),
|
||||
PricePercentage: v.PricePercentage,
|
||||
ActPrice: v.ActPrice,
|
||||
Stock: v.Stock,
|
||||
}
|
||||
dao.WrapAddIDCULDEntity(storeSku, ctx.GetUserName())
|
||||
actStoreSkuList = append(actStoreSkuList, storeSku)
|
||||
}
|
||||
}
|
||||
}
|
||||
for vendorID := range validVendorMap {
|
||||
wholeValidVendorMap[vendorID] = 1
|
||||
actStoreMap := &model.ActStoreMap{
|
||||
ActID: act.ID,
|
||||
StoreID: storeID,
|
||||
VendorID: vendorID,
|
||||
|
||||
SyncStatus: model.SyncFlagNewMask,
|
||||
}
|
||||
dao.WrapAddIDCULDEntity(actStoreMap, ctx.GetUserName())
|
||||
actStoreMapList = append(actStoreMapList, actStoreMap)
|
||||
}
|
||||
}
|
||||
for vendorID := range wholeValidVendorMap {
|
||||
actMap := &model.ActMap{
|
||||
ActID: act.ID,
|
||||
VendorID: vendorID,
|
||||
|
||||
SyncStatus: model.SyncFlagNewMask,
|
||||
}
|
||||
dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName())
|
||||
actMapList = append(actMapList, actMap)
|
||||
}
|
||||
}
|
||||
return actMapList, actStoreMapList, actStoreSkuList, actStoreSkuMapList, err
|
||||
}
|
||||
|
||||
func CreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam) (actID int, err error) {
|
||||
vendorIDMap := make(map[int]bool)
|
||||
for _, v := range vendorIDs {
|
||||
vendorIDMap[v] = true
|
||||
}
|
||||
db := dao.GetDB()
|
||||
dao.WrapAddIDCULDEntity(act, ctx.GetUserName())
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
dao.Rollback(db)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
err = dao.CreateEntity(db, act)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
actMapList, actStoreMapList, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, act, vendorIDs, actStoreSku)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
isEmptyAct := true
|
||||
for _, list := range []interface{}{
|
||||
actMapList, actStoreMapList, actStoreSkuList, actStoreSkuMapList,
|
||||
} {
|
||||
if len(utils.Interface2Slice(list)) > 0 {
|
||||
err = dao.CreateMultiEntities(db, list)
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return 0, err
|
||||
}
|
||||
isEmptyAct = false
|
||||
}
|
||||
}
|
||||
if isEmptyAct {
|
||||
dao.Rollback(db)
|
||||
return 0, fmt.Errorf("没有门店及SKU满足需求,空操作")
|
||||
}
|
||||
dao.Commit(db)
|
||||
actID = act.ID
|
||||
err = SyncAct(ctx, actID, nil, nil, nil)
|
||||
return actID, err
|
||||
}
|
||||
|
||||
func QueryActs(ctx *jxcontext.Context, actID int, keyword string, statusList []int, actTypeList []int, storeID, skuID int, beginAt, endAt time.Time) (actList []*model.Act, err error) {
|
||||
return actList, err
|
||||
}
|
||||
|
||||
func GetActDetail(ctx *jxcontext.Context, actID int) (actDetail *ActDetail, err error) {
|
||||
return actDetail, err
|
||||
}
|
||||
|
||||
// func GetAcVendorInfo(ctx *jxcontext.Context, actID int) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func GetAcStoresVendorInfo(ctx *jxcontext.Context, actID int, storeIDs []int) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func GetAcStoresSkusVendorInfo(ctx *jxcontext.Context, actID int, storeIDs, skuIDs []int) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
func parseActStoreSkuParam(actStoreSku []*ActStoreSkuParam) {
|
||||
|
||||
}
|
||||
|
||||
func UpdateAct(ctx *jxcontext.Context, act *model.Act, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func CancelAct(ctx *jxcontext.Context, actID int) (err error) {
|
||||
db := dao.GetDB()
|
||||
act := &model.Act{}
|
||||
act.ID = actID
|
||||
if err = dao.GetEntity(db, act); err != nil {
|
||||
return err
|
||||
}
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
dao.Rollback(db)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
dao.UpdateEntityLogically(db, act, map[string]interface{}{
|
||||
model.FieldStatus: model.ActStatusCanceled,
|
||||
}, ctx.GetUserName(), nil)
|
||||
_, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, &model.ActMap{}, nil, ctx.GetUserName(), map[string]interface{}{
|
||||
model.FieldActID: actID,
|
||||
}, model.FieldSyncStatus, model.SyncFlagModifiedMask)
|
||||
if err == nil {
|
||||
dao.Commit(db)
|
||||
globals.SugarLogger.Debugf("CancelAct track:%s", ctx.GetTrackInfo())
|
||||
err = SyncAct(ctx, actID, nil, nil, nil)
|
||||
} else {
|
||||
dao.Rollback(db)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func SyncAct(ctx *jxcontext.Context, actID int, vendorIDs, storeIDs, skuIDs []int) (err error) {
|
||||
var actOrderRules []*model.ActOrderRule
|
||||
db := dao.GetDB()
|
||||
actMap, err := dao.GetActVendorInfo(db, actID, vendorIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actStoreMap, err := dao.GetActStoreVendorInfo(db, actID, vendorIDs, storeIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, vendorIDs, storeIDs, skuIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var realVendorIDs []int
|
||||
for vendorID := range actMap {
|
||||
realVendorIDs = append(realVendorIDs, vendorID)
|
||||
}
|
||||
|
||||
task := tasksch.NewParallelTask("SyncAct", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
vendorID := batchItemList[0].(int)
|
||||
handler := partner.GetPurchasePlatformFromVendorID(vendorID)
|
||||
if handler == nil {
|
||||
err = fmt.Errorf("不被支持的vendorID:%d", vendorID)
|
||||
} else {
|
||||
act := actMap[vendorID]
|
||||
actStore := actStoreMap[vendorID]
|
||||
actStoreSku := actStoreSkuMap[vendorID]
|
||||
// globals.SugarLogger.Debugf("%s", utils.Format4Output(act, false))
|
||||
// globals.SugarLogger.Debugf("%s", utils.Format4Output(actStore, false))
|
||||
// globals.SugarLogger.Debugf("%s", utils.Format4Output(actStoreSku, false))
|
||||
if act != nil && actStore != nil && actStoreSku != nil {
|
||||
if model.IsSyncStatusNeedCreate(act.SyncStatus) {
|
||||
err = handler.CreateAct(ctx, task, act, actOrderRules, actStore, actStoreSku)
|
||||
} else if model.IsSyncStatusNeedUpdate(act.SyncStatus) {
|
||||
if act.Status == model.ActStatusCanceled {
|
||||
err = handler.CancelAct(ctx, task, act, actStore, actStoreSku)
|
||||
} else {
|
||||
// actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update := splitActStore(actStore)
|
||||
// err = handler.UpdateAct(ctx, task, act, actOrderRules, actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update, actStoreSku)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
actMap := &model.ActMap{}
|
||||
actMap.ID = act.MapID
|
||||
dao.UpdateEntityLogically(db, actMap, map[string]interface{}{
|
||||
model.FieldSyncStatus: 0,
|
||||
model.FieldVendorActID: act.VendorActID,
|
||||
}, ctx.GetUserName(), nil)
|
||||
for _, v := range actStore {
|
||||
storeMap := model.ActStoreMap{}
|
||||
storeMap.ID = v.MapID
|
||||
dao.UpdateEntityLogically(db, storeMap, map[string]interface{}{
|
||||
model.FieldSyncStatus: 0,
|
||||
model.FieldVendorActID: v.VendorActID,
|
||||
}, ctx.GetUserName(), nil)
|
||||
}
|
||||
for _, v := range actStoreSku {
|
||||
storeSkuMap := model.ActStoreSkuMap{}
|
||||
storeSkuMap.ID = v.MapID
|
||||
dao.UpdateEntityLogically(db, storeSkuMap, map[string]interface{}{
|
||||
model.FieldSyncStatus: 0,
|
||||
model.FieldVendorActID: v.VendorActID,
|
||||
}, ctx.GetUserName(), nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}, realVendorIDs)
|
||||
tasksch.ManageTask(task).Run()
|
||||
_, err = task.GetResult(0)
|
||||
return err
|
||||
}
|
||||
|
||||
func splitActStore(actStore []*model.ActStore2) (actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update []*model.ActStore2) {
|
||||
for _, v := range actStore {
|
||||
if model.IsSyncStatusNeedDelete(v.SyncStatus) {
|
||||
if !dao.IsVendorThingIDEmpty(v.VendorActID) {
|
||||
actStoreMap2Remove = append(actStoreMap2Remove, v)
|
||||
}
|
||||
} else if model.IsSyncStatusNeedCreate(v.SyncStatus) {
|
||||
actStoreMap2Add = append(actStoreMap2Add, v)
|
||||
} else if model.IsSyncStatusNeedUpdate(v.SyncStatus) {
|
||||
actStoreMap2Update = append(actStoreMap2Update, v)
|
||||
}
|
||||
}
|
||||
return actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update
|
||||
}
|
||||
68
business/jxstore/act/act_test.go
Normal file
68
business/jxstore/act/act_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package act
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
|
||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
|
||||
func TestInitDb(t *testing.T) {
|
||||
dao.ExecuteSQL(dao.GetDB(), `
|
||||
DROP TABLE IF EXISTS act,act_map, act_order_rule, act_store_map, act_store_sku, act_store_sku_map;
|
||||
`)
|
||||
}
|
||||
|
||||
func TestCreateAct(t *testing.T) {
|
||||
actID, err := CreateAct(jxcontext.AdminCtx, &model.Act{
|
||||
Name: "测试活动2",
|
||||
PricePercentage: 80,
|
||||
}, []int{0, 1, 3}, nil, []*ActStoreSkuParam{
|
||||
&ActStoreSkuParam{
|
||||
StoreID: 100119,
|
||||
SkuID: 30828,
|
||||
},
|
||||
&ActStoreSkuParam{
|
||||
StoreID: 100119,
|
||||
SkuID: 30827,
|
||||
},
|
||||
&ActStoreSkuParam{
|
||||
StoreID: 100118,
|
||||
SkuID: 30592,
|
||||
},
|
||||
&ActStoreSkuParam{
|
||||
StoreID: 100118,
|
||||
SkuID: 30565,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
globals.SugarLogger.Debug(actID)
|
||||
}
|
||||
|
||||
func TestCancelAct(t *testing.T) {
|
||||
err := CancelAct(jxcontext.AdminCtx, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncAct(t *testing.T) {
|
||||
err := SyncAct(jxcontext.AdminCtx, 1, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,12 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
serviceInfo map[string]interface{}
|
||||
serviceInfo map[string]interface{}
|
||||
allowUpdatePlaceFieldsMap = map[string]bool{
|
||||
"name": true,
|
||||
"enabled": true,
|
||||
"mtpsPrice": true,
|
||||
}
|
||||
)
|
||||
|
||||
func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
|
||||
@@ -55,6 +60,8 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
|
||||
"shopChineseNames": model.ShopChineseNames,
|
||||
"printerVendorInfo": model.PrinterVendorInfo,
|
||||
"purchaseVendorInfo": model.PurchaseVendorInfo,
|
||||
"afsReasonTypeName": model.AfsReasonTypeName,
|
||||
"afsAppealTypeName": model.AfsAppealTypeName,
|
||||
},
|
||||
}
|
||||
Init()
|
||||
@@ -124,12 +131,18 @@ func UpdatePlaces(ctx *jxcontext.Context, places []map[string]interface{}, userN
|
||||
if len(places) == 0 {
|
||||
return 0, ErrMissingInput
|
||||
}
|
||||
updateFields := []string{}
|
||||
for k := range places[0] {
|
||||
if allowUpdatePlaceFieldsMap[k] {
|
||||
updateFields = append(updateFields, k)
|
||||
}
|
||||
}
|
||||
for _, place := range places {
|
||||
if place["code"] == nil {
|
||||
return 0, ErrMissingInput
|
||||
}
|
||||
placeid := &model.Place{}
|
||||
valid := dao.NormalMakeMapByFieldList(place, []string{"jdCode", "enabled", "mtpsPrice"}, userName)
|
||||
valid := dao.NormalMakeMapByFieldList(place, updateFields, userName)
|
||||
if num, err = dao.UpdateEntityLogically(nil, placeid, valid, userName, utils.Params2Map("Code", place["code"])); err != nil {
|
||||
return num, err
|
||||
}
|
||||
|
||||
@@ -13,6 +13,12 @@ import (
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
type MessageStatusExt struct {
|
||||
model.MessageStatus
|
||||
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
db := dao.GetDB()
|
||||
dao.Begin(db)
|
||||
@@ -128,8 +134,11 @@ func GetStoreMessages(ctx *jxcontext.Context, msgIDs, storeIDs, types []int, fro
|
||||
|
||||
func GetStoreMessageStatuses(ctx *jxcontext.Context, msgIDs, storeIDs []int, fromReadCount, toReadCount int, fromTime, toTime time.Time, keyword string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
||||
sql := `
|
||||
SELECT SQL_CALC_FOUND_ROWS t1.*
|
||||
SELECT SQL_CALC_FOUND_ROWS
|
||||
t1.*,
|
||||
t2.title
|
||||
FROM message_status t1
|
||||
JOIN message t2 ON t2.id = t1.message_id
|
||||
WHERE 1 = 1
|
||||
`
|
||||
sqlParams := []interface{}{}
|
||||
@@ -167,7 +176,7 @@ func GetStoreMessageStatuses(ctx *jxcontext.Context, msgIDs, storeIDs []int, fro
|
||||
db := dao.GetDB()
|
||||
dao.Begin(db)
|
||||
defer dao.Commit(db)
|
||||
var msgStatusList []*model.MessageStatus
|
||||
var msgStatusList []*MessageStatusExt
|
||||
// globals.SugarLogger.Debug(sql)
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false))
|
||||
if err = dao.GetRows(db, &msgStatusList, sql, sqlParams...); err == nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
@@ -14,6 +15,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"
|
||||
)
|
||||
|
||||
type SkuNamesInfo struct {
|
||||
@@ -25,6 +27,19 @@ var (
|
||||
ErrInputCatsDoesntMatch = errors.New("输入的类别列表不合法,需要输入一个父ID下的所有子类别")
|
||||
)
|
||||
|
||||
var (
|
||||
ebaiUploadRTFShopID string // 饿百找一个店用于调用SkuUploadRTF
|
||||
)
|
||||
|
||||
func getAndSetEbaiUploadRTFShopID() (shopID string) {
|
||||
if ebaiUploadRTFShopID == "" {
|
||||
if storeDetail, err := dao.GetStoreDetail(dao.GetDB(), 0, model.VendorIDEBAI); err == nil {
|
||||
ebaiUploadRTFShopID = utils.Int2Str(storeDetail.Store.ID)
|
||||
}
|
||||
}
|
||||
return ebaiUploadRTFShopID
|
||||
}
|
||||
|
||||
// parentID 为-1表示所有
|
||||
func GetVendorCategories(ctx *jxcontext.Context, vendorID int, parentID string) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
cond := map[string]interface{}{
|
||||
@@ -72,7 +87,7 @@ func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string
|
||||
|
||||
dao.WrapAddIDCULDEntity(cat, userName)
|
||||
cat.JdSyncStatus = model.SyncFlagNewMask
|
||||
cat.JdID = 0 //jxutils.GenFakeID()
|
||||
cat.JdID = 0
|
||||
cat.Name = strings.Trim(cat.Name, " ")
|
||||
if cat.Seq <= 0 {
|
||||
var maxSeq struct {
|
||||
@@ -93,19 +108,83 @@ func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string
|
||||
func UpdateCategory(ctx *jxcontext.Context, categoryID int, payload map[string]interface{}, userName string) (num int64, err error) {
|
||||
cat := &model.SkuCategory{}
|
||||
cat.ID = categoryID
|
||||
valid := dao.NormalMakeMapByStructObject(payload, cat, userName)
|
||||
db := dao.GetDB()
|
||||
if err = dao.GetEntity(db, cat); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valid := dao.StrictMakeMapByStructObject(payload, cat, userName)
|
||||
if len(valid) > 0 {
|
||||
syncStatus := 0
|
||||
if valid["name"] != nil {
|
||||
valid["name"] = strings.Trim(valid["name"].(string), " ")
|
||||
syncStatus = model.SyncFlagModifiedMask
|
||||
}
|
||||
db := dao.GetDB()
|
||||
if num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, cat, valid, userName, nil, model.FieldJdSyncStatus, model.SyncFlagModifiedMask); err == nil {
|
||||
if num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, cat, valid, userName, nil, model.FieldJdSyncStatus, syncStatus); err == nil {
|
||||
SetStoreCategorySyncStatus2(db, nil, []int{categoryID}, model.SyncFlagModifiedMask)
|
||||
if valid["jdCategoryID"] != nil || valid["ebaiCategoryID"] != nil || valid["mtwmCategoryID"] != nil ||
|
||||
valid["jdPricePercentage"] != nil || valid["ebaiPricePercentage"] != nil || valid["mtwmPricePercentage"] != nil {
|
||||
if skuList, err2 := dao.GetSkuByCats(db, []int{categoryID}); err2 == nil && len(skuList) > 0 {
|
||||
var skuIDs []int
|
||||
for _, sku := range skuList {
|
||||
skuIDs = append(skuIDs, sku.ID)
|
||||
}
|
||||
if valid["jdCategoryID"] != nil {
|
||||
dao.SetSkuSyncStatus(db, model.VendorIDJD, skuIDs, model.SyncFlagModifiedMask)
|
||||
}
|
||||
|
||||
// todo 如下逻辑,在不同平台同时改pricePercentage与平台分类映射时,会不必要的打上多余的标记
|
||||
var vendorIDs []int
|
||||
syncStatus := model.SyncFlagModifiedMask
|
||||
if valid["jdPricePercentage"] != nil {
|
||||
vendorIDs = append(vendorIDs, model.VendorIDJD)
|
||||
syncStatus |= model.SyncFlagPriceMask
|
||||
}
|
||||
|
||||
if valid["ebaiPricePercentage"] != nil {
|
||||
vendorIDs = append(vendorIDs, model.VendorIDEBAI)
|
||||
syncStatus |= model.SyncFlagPriceMask
|
||||
} else if valid["ebaiCategoryID"] != nil {
|
||||
vendorIDs = append(vendorIDs, model.VendorIDEBAI)
|
||||
}
|
||||
|
||||
if valid["mtwmPricePercentage"] != nil {
|
||||
vendorIDs = append(vendorIDs, model.VendorIDMTWM)
|
||||
syncStatus |= model.SyncFlagPriceMask
|
||||
} else if valid["mtwmCategoryID"] != nil {
|
||||
vendorIDs = append(vendorIDs, model.VendorIDMTWM)
|
||||
}
|
||||
if len(vendorIDs) > 0 {
|
||||
SetStoreSkuSyncStatus2(db, nil, vendorIDs, skuIDs, syncStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = CurVendorSync.SyncCategory(ctx, db, categoryID, false, userName)
|
||||
}
|
||||
}
|
||||
return num, err
|
||||
}
|
||||
|
||||
func SetStoreCategorySyncStatus2(db *dao.DaoDB, storeIDs []int, catIDs []int, syncStatus int) (num int64, err error) {
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil || err != nil {
|
||||
dao.Rollback(db)
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
for _, vendorID := range CurVendorSync.SingleStoreVendorIDs {
|
||||
num2, err2 := dao.SetStoreCategorySyncStatus(db, vendorID, storeIDs, catIDs, syncStatus)
|
||||
if err = err2; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
num += num2
|
||||
}
|
||||
dao.Commit(db)
|
||||
return num, nil
|
||||
}
|
||||
|
||||
func ReorderCategories(ctx *jxcontext.Context, parentID int, categoryIDs []int, userName string) (err error) {
|
||||
var cats []*model.SkuCategory
|
||||
parentCat := &model.SkuCategory{}
|
||||
@@ -211,8 +290,8 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
|
||||
sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike)
|
||||
|
||||
if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil {
|
||||
sql += " OR t2.jd_id = ? OR t1.id = ? OR t1.category_id = ?"
|
||||
sqlParams = append(sqlParams, keywordInt64, keywordInt64, keywordInt64)
|
||||
sql += " OR t1.id = ? OR t2.id = ? OR t2.jd_id = ? OR t1.category_id = ?"
|
||||
sqlParams = append(sqlParams, keywordInt64, keywordInt64, keywordInt64, keywordInt64)
|
||||
}
|
||||
sql += ")"
|
||||
}
|
||||
@@ -340,6 +419,7 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
|
||||
t1.name,
|
||||
t1.brand_id,
|
||||
t1.category_id,
|
||||
t1.jd_category_id,
|
||||
t1.is_global,
|
||||
t1.unit,
|
||||
t1.price,
|
||||
@@ -348,6 +428,7 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
|
||||
t1.status,
|
||||
t1.is_spu,
|
||||
t1.img_hash_code,
|
||||
t1.desc_img,
|
||||
t1.upc`
|
||||
if isBySku {
|
||||
sql += `,
|
||||
@@ -365,6 +446,7 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
|
||||
t1.name,
|
||||
t1.brand_id,
|
||||
t1.category_id,
|
||||
t1.jd_category_id,
|
||||
t1.is_global,
|
||||
t1.unit,
|
||||
t1.price,
|
||||
@@ -373,6 +455,7 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
|
||||
t1.status,
|
||||
t1.is_spu,
|
||||
t1.img_hash_code,
|
||||
t1.desc_img,
|
||||
t1.upc,
|
||||
t1.jd_id,
|
||||
t1.jd_sync_status,
|
||||
@@ -463,30 +546,39 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s
|
||||
skuNameExt.SpecQuality = skuNameExt.Skus[0].SpecQuality
|
||||
skuNameExt.SpecUnit = skuNameExt.Skus[0].SpecUnit
|
||||
}
|
||||
imgContent, imgMD5, err := jxutils.DownloadFileByURL(skuNameExt.Img)
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
if skuNameExt.ImgHashCode == "" {
|
||||
skuNameExt.ImgHashCode = imgMD5
|
||||
} else if skuNameExt.ImgHashCode != imgMD5 {
|
||||
dao.Rollback(db)
|
||||
return nil, errors.New("图片HASH值不同")
|
||||
}
|
||||
imgHintMap, err := UploadImg2Platforms(ctx, nil, skuNameExt.Img, imgContent, "")
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
skuNameExt.ImgWeimob = imgHintMap[model.VendorIDWSC]
|
||||
skuNameExt.ImgEbai = imgHintMap[model.VendorIDEBAI]
|
||||
|
||||
if globals.EnableStoreWrite {
|
||||
imgContent, imgMD5, err := jxutils.DownloadFileByURL(skuNameExt.Img)
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
if skuNameExt.ImgHashCode == "" {
|
||||
skuNameExt.ImgHashCode = imgMD5
|
||||
} else if skuNameExt.ImgHashCode != imgMD5 {
|
||||
dao.Rollback(db)
|
||||
return nil, errors.New("图片HASH值不同")
|
||||
}
|
||||
imgHintMap, err := UploadImg2Platforms(ctx, nil, skuNameExt.Img, imgContent, "")
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
skuNameExt.ImgWeimob = imgHintMap[model.VendorIDWSC]
|
||||
skuNameExt.ImgEbai = imgHintMap[model.VendorIDEBAI]
|
||||
|
||||
if skuNameExt.DescImg != "" && getAndSetEbaiUploadRTFShopID() != "" {
|
||||
skuNameExt.DescImgEbai, err = api.EbaiAPI.SkuUploadRTF(getAndSetEbaiUploadRTFShopID(), ebaiapi.BuildRFTFromImgs(skuNameExt.DescImg))
|
||||
}
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err = dao.CreateEntity(db, &skuNameExt.SkuName); err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
// beginJDID := jxutils.GenFakeID()
|
||||
for _, sku := range skuNameExt.Skus {
|
||||
dao.WrapAddIDCULDEntity(sku, userName)
|
||||
sku.NameID = skuNameExt.ID
|
||||
@@ -496,7 +588,6 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
}
|
||||
// beginJDID++
|
||||
}
|
||||
for _, placeCode := range skuNameExt.Places {
|
||||
placeBind := &model.SkuNamePlaceBind{}
|
||||
@@ -528,9 +619,12 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
|
||||
if err = dao.GetEntity(db, skuName); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if _, ok := payload["isSpu"]; ok {
|
||||
delete(payload, "isSpu")
|
||||
}
|
||||
delete(payload, "isSpu")
|
||||
delete(payload, "ImgHashCode")
|
||||
delete(payload, "ImgWeimob")
|
||||
delete(payload, "ImgEbai")
|
||||
delete(payload, "descImgEbai")
|
||||
|
||||
valid := dao.StrictMakeMapByStructObject(payload, skuName, userName)
|
||||
valid = utils.RemoveGeneralMapKeys(valid, model.FieldSpecQuality, model.FieldSpecUnit)
|
||||
_, hasPlaces := payload["places"]
|
||||
@@ -550,19 +644,35 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
if valid["img"] != nil {
|
||||
imgContent, imgMD5, err2 := jxutils.DownloadFileByURL(valid["img"].(string))
|
||||
if err = err2; err != nil {
|
||||
return 0, err
|
||||
if globals.EnableStoreWrite {
|
||||
if valid["img"] != nil {
|
||||
imgContent, imgMD5, err2 := jxutils.DownloadFileByURL(valid["img"].(string))
|
||||
if err = err2; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valid["ImgHashCode"] = imgMD5
|
||||
imgHintMap, err := UploadImg2Platforms(ctx, nil, valid["img"].(string), imgContent, "")
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return 0, err
|
||||
}
|
||||
valid["ImgWeimob"] = imgHintMap[model.VendorIDWSC]
|
||||
valid["ImgEbai"] = imgHintMap[model.VendorIDEBAI]
|
||||
}
|
||||
valid["ImgHashCode"] = imgMD5
|
||||
imgHintMap, err := UploadImg2Platforms(ctx, nil, valid["img"].(string), imgContent, "")
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return 0, err
|
||||
if valid["descImg"] != nil {
|
||||
descImg := valid["descImg"].(string)
|
||||
if descImg != "" {
|
||||
if getAndSetEbaiUploadRTFShopID() != "" {
|
||||
valid["descImgEbai"], err = api.EbaiAPI.SkuUploadRTF(getAndSetEbaiUploadRTFShopID(), ebaiapi.BuildRFTFromImgs(descImg))
|
||||
if err != nil {
|
||||
dao.Rollback(db)
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
valid["descImgEbai"] = ""
|
||||
}
|
||||
}
|
||||
valid["ImgWeimob"] = imgHintMap[model.VendorIDWSC]
|
||||
valid["ImgEbai"] = imgHintMap[model.VendorIDEBAI]
|
||||
}
|
||||
if num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, skuName, valid, userName, nil, model.FieldJdSyncStatus, model.SyncFlagModifiedMask); err == nil && num == 1 {
|
||||
if utils.Interface2Int64WithDefault(payload["isGlobal"], 0) == 0 && payload["places"] != nil {
|
||||
@@ -588,8 +698,14 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
|
||||
model.FieldNameID: nameID,
|
||||
}, model.FieldJdSyncStatus, model.SyncFlagModifiedMask)
|
||||
if err == nil {
|
||||
dao.Commit(db)
|
||||
_, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName)
|
||||
skuIDs, err2 := dao.GetSkuIDByNames(db, []int{nameID})
|
||||
if err = err2; err == nil && len(skuIDs) > 0 {
|
||||
_, err = SetStoreSkuSyncStatus2(db, nil, CurVendorSync.SingleStoreVendorIDs, skuIDs, model.SyncFlagModifiedMask)
|
||||
}
|
||||
if err == nil {
|
||||
dao.Commit(db)
|
||||
_, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,6 +713,27 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf
|
||||
return num, err
|
||||
}
|
||||
|
||||
func SetStoreSkuSyncStatus2(db *dao.DaoDB, storeIDs []int, vendorIDs, skuIDs []int, syncStatus int) (num int64, err error) {
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil || err != nil {
|
||||
dao.Rollback(db)
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
for _, vendorID := range vendorIDs {
|
||||
num2, err2 := dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, skuIDs, syncStatus)
|
||||
if err = err2; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
num += num2
|
||||
}
|
||||
dao.Commit(db)
|
||||
return num, nil
|
||||
}
|
||||
|
||||
func DeleteSkuName(ctx *jxcontext.Context, nameID int, userName string) (num int64, err error) {
|
||||
db := dao.GetDB()
|
||||
dao.Begin(db)
|
||||
@@ -647,7 +784,7 @@ func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string)
|
||||
dao.WrapAddIDCULDEntity(sku, userName)
|
||||
sku.JdSyncStatus = model.SyncFlagNewMask
|
||||
sku.NameID = nameID
|
||||
sku.JdID = 0 //jxutils.GenFakeID()
|
||||
sku.JdID = 0
|
||||
if err = dao.CreateEntity(db, sku); err == nil {
|
||||
result, err2 := GetSkuNames(ctx, "", false, utils.Params2Map("skuID", sku.ID), 0, 0)
|
||||
if err = err2; err == nil {
|
||||
@@ -691,8 +828,10 @@ func UpdateSku(ctx *jxcontext.Context, skuID int, payload map[string]interface{}
|
||||
`, utils.DefaultTimeValue, skuID, model.SpecialUnit); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
dao.Commit(db)
|
||||
_, err = CurVendorSync.SyncSku(ctx, db, -1, sku.ID, false, false, userName)
|
||||
if _, err = SetStoreSkuSyncStatus2(db, nil, CurVendorSync.SingleStoreVendorIDs, []int{skuID}, model.SyncFlagModifiedMask); err == nil {
|
||||
dao.Commit(db)
|
||||
_, err = CurVendorSync.SyncSku(ctx, db, -1, sku.ID, false, false, userName)
|
||||
}
|
||||
} else {
|
||||
err = ErrEntityNotExist
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@ import (
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/feieapi"
|
||||
"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/jxutils/excel"
|
||||
"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/tasksch"
|
||||
@@ -19,6 +21,7 @@ import (
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/model/legacymodel"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
@@ -59,6 +62,37 @@ var (
|
||||
ErrCanNotFindVendor = errors.New("vendorID参数不合法")
|
||||
)
|
||||
|
||||
var (
|
||||
dadaDistrictMap = map[string]string{
|
||||
"苏州工业园区": "工业园区",
|
||||
"郫都区": "郫县",
|
||||
"管城回族区": "管城区",
|
||||
"昆山市": "1",
|
||||
"常熟市": "1",
|
||||
"太仓市": "1",
|
||||
"虞山街道": "虞山镇",
|
||||
"常福街道": "虞山镇",
|
||||
}
|
||||
|
||||
storeKeyPropertyMap = map[string]int{
|
||||
"name": 1,
|
||||
"cityCode": 1,
|
||||
"districtCode": 1,
|
||||
"address": 1,
|
||||
"tel1": 1,
|
||||
"tel2": 1,
|
||||
"openTime1": 1,
|
||||
"closeTime1": 1,
|
||||
"openTime2": 1,
|
||||
"closeTime2": 1,
|
||||
"lng": 1,
|
||||
"lat": 1,
|
||||
"deliveryRangeType": 1,
|
||||
"deliveryRange": 1,
|
||||
"status": 1,
|
||||
}
|
||||
)
|
||||
|
||||
// todo 门店绑定信息可以考虑以数组形式返回,而不是现在这样
|
||||
func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interface{}, offset, pageSize int) (retVal *StoresInfo, err error) {
|
||||
sql := `
|
||||
@@ -92,17 +126,46 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa
|
||||
t1.printer_sn,
|
||||
t1.printer_key,
|
||||
t1.printer_vendor_id,
|
||||
|
||||
t1.licence_type,
|
||||
t1.licence_corp_name,
|
||||
t1.licence_owner_name,
|
||||
t1.licence_address,
|
||||
t1.licence_valid,
|
||||
t1.licence_expire,
|
||||
t1.id_name,
|
||||
t1.id_code,
|
||||
t1.id_valid,
|
||||
t1.id_expire,
|
||||
t1.licence2_image,
|
||||
t1.licence2_code,
|
||||
t1.licence2_valid,
|
||||
t1.licence2_expire,
|
||||
t1.market_man_name,
|
||||
t1.market_man_phone,
|
||||
t1.jx_brand_fee_factor,
|
||||
t1.market_add_fee_factor,
|
||||
t1.payee_name,
|
||||
t1.payee_account_no,
|
||||
t1.payee_bank_branch_name,
|
||||
t1.payee_bank_name,
|
||||
|
||||
t1.pay_percentage,
|
||||
t1.operator_name,
|
||||
t1.operator_phone,
|
||||
|
||||
city.name city_name,
|
||||
district.name district_name,
|
||||
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"vendorStoreID":"', m1.vendor_store_id, '", "vendorID":', m1.vendor_id,
|
||||
', "status":', m1.status, ', "pricePercentage":', m1.price_percentage, ', "vendorStoreName":"',
|
||||
CONCAT('[', GROUP_CONCAT(DISTINCT CONCAT('{"vendorStoreID":"', m1.vendor_store_id, '", "vendorID":', m1.vendor_id,
|
||||
', "status":', m1.status, ', "pricePercentage":', m1.price_percentage, ', "vendorStoreName":"',
|
||||
CASE m1.vendor_id
|
||||
WHEN 0 THEN IF(jd.name IS NULL, '', jd.name)
|
||||
WHEN 3 THEN IF(eb.col_name IS NULL, '', eb.col_name)
|
||||
ELSE ''
|
||||
END,
|
||||
'"}')), ']') store_map_str,
|
||||
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"vendorStoreID":"', m2.vendor_store_id, '", "vendorID":', m2.vendor_id, ', "status":', m2.status, "}")), "]") courier_map_str
|
||||
'", "isSync":', m1.is_sync, '}')), ']') store_map_str,
|
||||
CONCAT('[', GROUP_CONCAT(DISTINCT CONCAT('{"vendorStoreID":"', m2.vendor_store_id, '", "vendorID":', m2.vendor_id,
|
||||
', "status":', m2.status, '}')), ']') courier_map_str
|
||||
FROM store t1
|
||||
LEFT JOIN place city ON t1.city_code = city.code AND city.level = 2
|
||||
LEFT JOIN place district ON t1.district_code = district.code AND district.level = 3
|
||||
@@ -228,7 +291,7 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa
|
||||
}
|
||||
|
||||
sql += sqlWhere + `
|
||||
GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
|
||||
GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53
|
||||
ORDER BY t1.id DESC
|
||||
LIMIT ? OFFSET ?`
|
||||
pageSize = jxutils.FormalizePageSize(pageSize)
|
||||
@@ -249,8 +312,9 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false))
|
||||
// globals.SugarLogger.Debug(sql)
|
||||
var storeList []*StoreExt
|
||||
mapLimit := false
|
||||
if err = dao.GetRows(db, &storeList, sql, sqlParams...); err == nil {
|
||||
mapLimit := false
|
||||
// globals.SugarLogger.Debugf("GetStores, len(storeList):%d", len(storeList))
|
||||
var (
|
||||
mapLatitude, mapLongitude float64
|
||||
mapRadius int
|
||||
@@ -289,8 +353,9 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa
|
||||
}
|
||||
}
|
||||
dao.Commit(db)
|
||||
|
||||
retVal.MapCenterLng, retVal.MapCenterLat = getMapCenter(retVal.Stores)
|
||||
if mapLimit {
|
||||
retVal.MapCenterLng, retVal.MapCenterLat = getMapCenter(retVal.Stores)
|
||||
}
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
@@ -365,6 +430,15 @@ func GetVendorStore(ctx *jxcontext.Context, vendorStoreID string, vendorID int)
|
||||
return nil, ErrCanNotFindVendor
|
||||
}
|
||||
|
||||
func isUpdateStoreNeedSync(valid map[string]interface{}) bool {
|
||||
for k := range valid {
|
||||
if storeKeyPropertyMap[k] == 1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interface{}, userName string) (num int64, err error) {
|
||||
globals.SugarLogger.Debugf("UpdateStore storeID:%d, payload:%s", storeID, utils.Format4Output(payload, false))
|
||||
|
||||
@@ -458,14 +532,18 @@ func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interfa
|
||||
dao.Rollback(db)
|
||||
}()
|
||||
if num, err = dao.UpdateEntityLogically(db, store, valid, userName, nil); err == nil && num == 1 {
|
||||
dummy := &model.StoreMap{}
|
||||
_, err2 := dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, dummy, nil, userName, map[string]interface{}{
|
||||
model.FieldStoreID: store.ID,
|
||||
}, model.FieldSyncStatus, syncStatus)
|
||||
if err = err2; err == nil {
|
||||
if isUpdateStoreNeedSync(valid) {
|
||||
dummy := &model.StoreMap{}
|
||||
_, err2 := dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, dummy, nil, userName, map[string]interface{}{
|
||||
model.FieldStoreID: store.ID,
|
||||
}, model.FieldSyncStatus, syncStatus)
|
||||
if err = err2; err == nil {
|
||||
dao.Commit(db)
|
||||
globals.SugarLogger.Debugf("UpdateStore track:%s, before call SyncStore", ctx.GetTrackInfo())
|
||||
_, err = CurVendorSync.SyncStore(ctx, db, -1, store.ID, false, userName)
|
||||
}
|
||||
} else {
|
||||
dao.Commit(db)
|
||||
globals.SugarLogger.Debugf("UpdateStore track:%s, before call SyncStore", ctx.GetTrackInfo())
|
||||
_, err = CurVendorSync.SyncStore(ctx, db, -1, store.ID, false, userName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -474,6 +552,42 @@ func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interfa
|
||||
return num, err
|
||||
}
|
||||
|
||||
func SetStoreStatus(ctx *jxcontext.Context, storeID, status int) (err error) {
|
||||
payload := map[string]interface{}{
|
||||
"status": status,
|
||||
}
|
||||
_, err = UpdateStore(ctx, storeID, payload, ctx.GetUserName())
|
||||
return err
|
||||
}
|
||||
|
||||
func EnableHaveRestStores(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
storeInfo, err := GetStores(ctx, "", map[string]interface{}{
|
||||
"statuss": string(utils.MustMarshal([]int{model.StoreStatusHaveRest})),
|
||||
}, 0, model.UnlimitedPageSize)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(storeInfo.Stores) == 0 {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
task := tasksch.NewParallelTask("EnableHaveRestStores", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
store := batchItemList[0].(*StoreExt)
|
||||
err = SetStoreStatus(ctx, store.ID, model.StoreStatusOpened)
|
||||
return nil, err
|
||||
}, storeInfo.Stores)
|
||||
tasksch.ManageTask(task).Run()
|
||||
if !isAsync {
|
||||
if _, err = task.GetResult(0); err == nil {
|
||||
hint = utils.Int2Str(len(storeInfo.Stores))
|
||||
}
|
||||
} else {
|
||||
hint = task.GetID()
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func CreateStore(ctx *jxcontext.Context, storeExt *StoreExt, userName string) (id int, err error) {
|
||||
globals.SugarLogger.Debugf("CreateStore storeExt:%s", utils.Format4Output(storeExt, false))
|
||||
store := &storeExt.Store
|
||||
@@ -547,6 +661,9 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID
|
||||
if storeID == 0 {
|
||||
return nil, fmt.Errorf("storeID不能为0")
|
||||
}
|
||||
if vendorID != model.VendorIDJD && (storeMap.AutoPickup == 0) {
|
||||
return nil, fmt.Errorf("非京东平台要求必须自动拣货")
|
||||
}
|
||||
userName := ctx.GetUserName()
|
||||
if handler := CurVendorSync.GetStoreHandler(vendorID); handler != nil {
|
||||
store, err2 := handler.ReadStore(storeMap.VendorStoreID)
|
||||
@@ -605,6 +722,11 @@ func DeleteStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendor
|
||||
}
|
||||
|
||||
func UpdateStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID int, payload map[string]interface{}, userName string) (num int64, err error) {
|
||||
if vendorID != model.VendorIDJD {
|
||||
if autoPickup, ok := payload["autoPickup"]; ok && autoPickup == 0 {
|
||||
return 0, fmt.Errorf("非京东平台要求必须自动拣货")
|
||||
}
|
||||
}
|
||||
storeHandler := CurVendorSync.GetStoreHandler(vendorID)
|
||||
if storeHandler == nil {
|
||||
return 0, ErrCanNotFindVendor
|
||||
@@ -651,7 +773,7 @@ func UpdateStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendor
|
||||
storeSkuBind := &model.StoreSkuBind{}
|
||||
if num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, storeSkuBind, nil, userName, map[string]interface{}{
|
||||
model.FieldStoreID: storeID,
|
||||
}, dao.GetSyncStatusStructField(model.VendorNames[vendorID]), model.SyncFlagModifiedMask); err != nil {
|
||||
}, dao.GetSyncStatusStructField(model.VendorNames[vendorID]), model.SyncFlagPriceMask); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
@@ -797,9 +919,22 @@ func AddStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID
|
||||
dao.WrapAddIDCULDEntity(storeCourierMap, userName)
|
||||
storeCourierMap.StoreID = storeID
|
||||
storeCourierMap.VendorID = vendorID
|
||||
|
||||
if db == nil {
|
||||
db = dao.GetDB()
|
||||
}
|
||||
if vendorID == model.VendorIDDada {
|
||||
storeList, err2 := dao.GetMissingDadaStores(db, storeID, false)
|
||||
if err = err2; err == nil && len(storeList) > 0 {
|
||||
storeList[0].DadaStoreID = storeCourierMap.VendorStoreID
|
||||
err = updateOrCreateDadaStore(storeList[0])
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("AddStoreCourierMap GetMissingDadaStores error:%v, len(storeList):%d", err, len(storeList))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -809,15 +944,6 @@ func AddStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID
|
||||
}()
|
||||
if err = dao.CreateEntity(db, storeCourierMap); err == nil {
|
||||
dao.Commit(db)
|
||||
if vendorID == model.VendorIDDada {
|
||||
storeList, err := dao.GetMissingDadaStores(db, storeID, false)
|
||||
if err == nil && len(storeList) > 0 {
|
||||
storeList[0].DadaStoreID = storeCourierMap.VendorStoreID
|
||||
err = updateOrCreateDadaStore(storeList[0])
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("AddStoreCourierMap GetMissingDadaStores error:%v, len(storeList):%d", err, len(storeList))
|
||||
}
|
||||
}
|
||||
outStoreCourierMap = storeCourierMap
|
||||
if err == nil {
|
||||
_, err = CurVendorSync.SyncStore(ctx, db, storeCourierMap.VendorID, storeID, false, userName)
|
||||
@@ -871,46 +997,74 @@ func RefreshMissingDadaStores(ctx *jxcontext.Context, storeID int, isAsync, isCo
|
||||
task := tasksch.NewParallelTask("RefreshMissingDadaStores", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
storeDetail := batchItemList[0].(*dao.StoreDetail2)
|
||||
var resultList []interface{}
|
||||
if storeDetail.DadaStoreID == "" {
|
||||
if storeDetail.DistrictName == "" || storeDetail.CityName == "" {
|
||||
return nil, fmt.Errorf("门店:%s的城市码或区码有错误", storeDetail.Name)
|
||||
}
|
||||
db := dao.GetDB()
|
||||
_, err = AddStoreCourierMap(ctx, db, storeDetail.ID, model.VendorIDDada, &model.StoreCourierMap{
|
||||
if _, err = AddStoreCourierMap(ctx, db, storeDetail.ID, model.VendorIDDada, &model.StoreCourierMap{
|
||||
VendorStoreID: utils.Int2Str(storeDetail.ID),
|
||||
Status: model.StoreStatusOpened,
|
||||
})
|
||||
}); err == nil {
|
||||
resultList = append(resultList, 1)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
return resultList, err
|
||||
}, storeList)
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
hint = task.ID
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
resultList, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
hint = utils.Int2Str(len(resultList))
|
||||
}
|
||||
} else {
|
||||
hint = task.ID
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func updateOrCreateDadaStore(storeDetail *dao.StoreDetail2) (err error) {
|
||||
_, err = api.DadaAPI.ShopDetail(storeDetail.DadaStoreID)
|
||||
if err != nil {
|
||||
if codeErr, ok := err.(*utils.ErrorWithCode); ok && codeErr.IntCode() == dadaapi.ResponseCodeShopNotExist {
|
||||
_, err = api.DadaAPI.ShopAdd(storeDetail.DadaStoreID, composeDadaStoreName(storeDetail), dadaapi.BusinessTypeConvStore, storeDetail.CityName,
|
||||
storeDetail.DistrictName, storeDetail.Address, jxutils.IntCoordinate2Standard(storeDetail.Lng), jxutils.IntCoordinate2Standard(storeDetail.Lat),
|
||||
storeDetail.Tel1, storeDetail.Tel1, nil)
|
||||
if storeDetail.DistrictName == "" {
|
||||
return fmt.Errorf("门店的区码有问题,请检查")
|
||||
}
|
||||
if storeDetail.CityName == "" {
|
||||
return fmt.Errorf("门店的城市码有问题,请检查")
|
||||
}
|
||||
if dadaDistrictMap[storeDetail.DistrictName] != "" {
|
||||
if dadaDistrictMap[storeDetail.DistrictName] == "1" { // 区镇信息
|
||||
storeDetail.CityName = storeDetail.DistrictName
|
||||
storeDetail.DistrictName, _ = api.AutonaviAPI.GetCoordinateTownInfo(jxutils.IntCoordinate2Standard(storeDetail.Lng), jxutils.IntCoordinate2Standard(storeDetail.Lat))
|
||||
}
|
||||
} else {
|
||||
params := map[string]interface{}{
|
||||
"station_name": composeDadaStoreName(storeDetail),
|
||||
"business": dadaapi.BusinessTypeConvStore,
|
||||
"city_name": storeDetail.CityName,
|
||||
"area_name": storeDetail.DistrictName,
|
||||
"station_address": storeDetail.Address,
|
||||
"lng": jxutils.IntCoordinate2Standard(storeDetail.Lng),
|
||||
"lat": jxutils.IntCoordinate2Standard(storeDetail.Lat),
|
||||
"contact_name": storeDetail.Tel1,
|
||||
"phone": storeDetail.Tel1,
|
||||
if dadaDistrictMap[storeDetail.DistrictName] != "" {
|
||||
storeDetail.DistrictName = dadaDistrictMap[storeDetail.DistrictName]
|
||||
}
|
||||
}
|
||||
if globals.EnableStoreWrite {
|
||||
_, err = api.DadaAPI.ShopDetail(storeDetail.DadaStoreID)
|
||||
if err != nil {
|
||||
if codeErr, ok := err.(*utils.ErrorWithCode); ok && codeErr.IntCode() == dadaapi.ResponseCodeShopNotExist {
|
||||
_, err = api.DadaAPI.ShopAdd(storeDetail.DadaStoreID, composeDadaStoreName(storeDetail), dadaapi.BusinessTypeConvStore, storeDetail.CityName,
|
||||
storeDetail.DistrictName, storeDetail.Address, jxutils.IntCoordinate2Standard(storeDetail.Lng), jxutils.IntCoordinate2Standard(storeDetail.Lat),
|
||||
storeDetail.Tel1, storeDetail.Tel1, nil)
|
||||
}
|
||||
} else {
|
||||
params := map[string]interface{}{
|
||||
"station_name": composeDadaStoreName(storeDetail),
|
||||
"business": dadaapi.BusinessTypeConvStore,
|
||||
"city_name": storeDetail.CityName,
|
||||
"area_name": storeDetail.DistrictName,
|
||||
"station_address": storeDetail.Address,
|
||||
"lng": jxutils.IntCoordinate2Standard(storeDetail.Lng),
|
||||
"lat": jxutils.IntCoordinate2Standard(storeDetail.Lat),
|
||||
"contact_name": storeDetail.Tel1,
|
||||
"phone": storeDetail.Tel1,
|
||||
}
|
||||
err = api.DadaAPI.ShopUpdate(storeDetail.DadaStoreID, params)
|
||||
}
|
||||
err = api.DadaAPI.ShopUpdate(storeDetail.DadaStoreID, params)
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("门店ID:%d,门店名:%s,错误描述:%s", storeDetail.Store.ID, storeDetail.Name, err.Error())
|
||||
globals.SugarLogger.Debugf("updateOrCreateDadaStore storeID:%d failed with error:%v", storeDetail.ID, err)
|
||||
}
|
||||
return err
|
||||
@@ -919,3 +1073,91 @@ func updateOrCreateDadaStore(storeDetail *dao.StoreDetail2) (err error) {
|
||||
func composeDadaStoreName(storeDetail *dao.StoreDetail2) (storeName string) {
|
||||
return storeDetail.Name + "-" + storeDetail.DadaStoreID
|
||||
}
|
||||
|
||||
func ExportShopsHealthInfo(ctx *jxcontext.Context, vendorIDs, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
db := dao.GetDB()
|
||||
vendorID := model.VendorIDEBAI
|
||||
storeMapList, err := dao.GetStoresMapList(db, []int{vendorID}, storeIDs, model.StoreStatusAll)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
storeMap2 := make(map[string]*model.StoreMap)
|
||||
for _, v := range storeMapList {
|
||||
storeMap2[v.VendorStoreID] = v
|
||||
}
|
||||
if len(storeMapList) > 0 {
|
||||
var healthInfoList []interface{}
|
||||
var excelBin []byte
|
||||
var excelURL string
|
||||
task := tasksch.NewSeqTask(fmt.Sprintf("ExportShopHealthInfo[%s]", model.VendorChineseNames[vendorID]), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
switch step {
|
||||
case 0:
|
||||
subTask := tasksch.NewParallelTask(fmt.Sprintf("ExportShopHealthInfo2[%s]", model.VendorChineseNames[vendorID]), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
storeMap := batchItemList[0].(*model.StoreMap)
|
||||
healthInfo, err := ebai.CurPurchaseHandler.GetShopHealthInfo(storeMap.VendorStoreID)
|
||||
if err == nil {
|
||||
retVal = []map[string]interface{}{healthInfo}
|
||||
}
|
||||
return retVal, err
|
||||
}, storeMapList)
|
||||
tasksch.AddChild(task, subTask).Run()
|
||||
healthInfoList, err = subTask.GetResult(0)
|
||||
if isContinueWhenError && err != nil && len(healthInfoList) > 0 {
|
||||
err = nil
|
||||
}
|
||||
case 1:
|
||||
var healthInfoList2 []map[string]interface{}
|
||||
for _, v := range healthInfoList {
|
||||
mapInfo := v.(map[string]interface{})
|
||||
mapInfo["real_shop_id"] = storeMap2[utils.Interface2String(mapInfo["merchant_id"])].StoreID
|
||||
healthInfoList2 = append(healthInfoList2, mapInfo)
|
||||
}
|
||||
excelConf := &excel.Obj2ExcelSheetConfig{
|
||||
Title: "饿百门店情况导出",
|
||||
Data: healthInfoList2,
|
||||
CaptionList: []string{
|
||||
"real_shop_id",
|
||||
"merchant_id",
|
||||
"merchant_name",
|
||||
"hours",
|
||||
"sku_num",
|
||||
"target_jiedan",
|
||||
"is_healthy",
|
||||
"bad_order_rate",
|
||||
},
|
||||
}
|
||||
excelBin = excel.Obj2Excel([]*excel.Obj2ExcelSheetConfig{excelConf})
|
||||
case 2:
|
||||
keyPart := []string{
|
||||
ctx.GetUserName(),
|
||||
"饿百门店情况",
|
||||
}
|
||||
keyPart = append(keyPart, time.Now().Format("20060102T150405")+".xlsx")
|
||||
key := "export/" + strings.Join(keyPart, "_")
|
||||
excelURL, err = jxutils.UploadExportContent(excelBin, key)
|
||||
if err == nil {
|
||||
task.SetNoticeMsg(excelURL)
|
||||
}
|
||||
globals.SugarLogger.Debugf("导出饿百门店情况excelURL:%s, err:%v", excelURL, err)
|
||||
}
|
||||
return nil, err
|
||||
}, 3)
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
if err == nil {
|
||||
hint = excelURL
|
||||
}
|
||||
} else {
|
||||
hint = task.GetID()
|
||||
}
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func GetCorporationInfo(ctx *jxcontext.Context, licenceCode string) (corporationInfo *jdapi.CorporationInfo, err error) {
|
||||
corporationInfo, err = api.JdAPI.GetCorporationInfo("", licenceCode)
|
||||
return corporationInfo, err
|
||||
}
|
||||
|
||||
@@ -6,8 +6,14 @@ import (
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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/business/partner"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxcallback/auth/weixin"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
@@ -20,6 +26,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
MaxSkuUnitPrice = 100000
|
||||
|
||||
CopyStoreSkuModeFresh = "fresh"
|
||||
CopyStoreSkuModeUpdate = "update"
|
||||
// CopyStoreSkuModeAdd = "add"
|
||||
@@ -48,24 +56,26 @@ type StoreSkuNamesInfo struct {
|
||||
// UpdateStoreSku用,API调用时
|
||||
type StoreSkuBindSkuInfo struct {
|
||||
SkuID int `json:"skuID"`
|
||||
IsSale int `json:"isSale"` // -1:不可售,0:忽略,1:可售
|
||||
IsSale int `json:"isSale,omitempty"` // -1:不可售,0:忽略,1:可售
|
||||
|
||||
ElmID int64 `json:"elmID"`
|
||||
EbaiID int64 `json:"ebaiID"`
|
||||
ElmID int64 `json:"elmID,omitempty"`
|
||||
EbaiID int64 `json:"ebaiID,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateStoreSku用,API调用时
|
||||
type StoreSkuBindInfo struct {
|
||||
StoreID int `json:"storeID"`
|
||||
NameID int `json:"nameID"`
|
||||
UnitPrice int `json:"unitPrice"` // 对于是份的SKU就是单价(每斤价格),其它则为总价
|
||||
IsFocus int `json:"isFocus"` // -1:不关注,0:忽略,1:关注
|
||||
IsSale int `json:"isSale"` // -1:不可售,0:忽略,1:可售
|
||||
SubStoreID int `json:"subStoreID"`
|
||||
Skus []*StoreSkuBindSkuInfo `json:"skus"`
|
||||
SubStoreID int `json:"subStoreID,omitempty"`
|
||||
Skus []*StoreSkuBindSkuInfo `json:"skus,omitempty"`
|
||||
}
|
||||
|
||||
type tStoreSkuBindAndSpec struct {
|
||||
model.StoreSkuBind
|
||||
Name string
|
||||
SpecQuality float32
|
||||
SpecUnit string
|
||||
SkuNamePrice int
|
||||
@@ -88,6 +98,11 @@ type StoreOpRequestInfo struct {
|
||||
UnitPrice int `json:"unitPrice"`
|
||||
}
|
||||
|
||||
const (
|
||||
maxStoreNameBind = 3000 // 最大门店SkuName bind个数
|
||||
maxStoreNameBind2 = 10000 // 最大门店乘SkuName个数
|
||||
)
|
||||
|
||||
func GetStoreSkus(ctx *jxcontext.Context, storeID int, isFocus bool, keyword string, isBySku bool, params map[string]interface{}, offset, pageSize int) (skuNamesInfo *StoreSkuNamesInfo, err error) {
|
||||
return GetStoresSkus(ctx, []int{storeID}, isFocus, keyword, isBySku, params, offset, pageSize)
|
||||
}
|
||||
@@ -102,7 +117,7 @@ func GetStoresSkus(ctx *jxcontext.Context, storeIDs []int, isFocus bool, keyword
|
||||
JOIN store t3 ON t3.id IN (` + dao.GenQuestionMarks(len(storeIDs)) + `)
|
||||
LEFT JOIN store_sku_bind t4 ON t4.sku_id = t2.id AND t4.deleted_at = ? AND t4.store_id = t3.id
|
||||
LEFT JOIN sku_name_place_bind t5 ON t1.id = t5.name_id AND t3.city_code = t5.place_code
|
||||
WHERE t1.deleted_at = ? AND (t1.is_global = 1 OR t5.id IS NOT NULL OR t4.status = ?)/* AND t1.status = ?*/
|
||||
WHERE t1.deleted_at = ? AND (t1.is_global = 1 OR t5.id IS NOT NULL OR 1 = ?)/* AND t1.status = ?*/
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
utils.DefaultTimeValue,
|
||||
@@ -110,7 +125,7 @@ func GetStoresSkus(ctx *jxcontext.Context, storeIDs []int, isFocus bool, keyword
|
||||
storeIDs,
|
||||
utils.DefaultTimeValue,
|
||||
utils.DefaultTimeValue,
|
||||
model.SkuStatusNormal,
|
||||
utils.Bool2Int(isFocus),
|
||||
// model.SkuStatusNormal,
|
||||
}
|
||||
if isFocus {
|
||||
@@ -122,12 +137,12 @@ func GetStoresSkus(ctx *jxcontext.Context, storeIDs []int, isFocus bool, keyword
|
||||
}
|
||||
if keyword != "" {
|
||||
keywordLike := "%" + keyword + "%"
|
||||
sql += " AND (t1.name LIKE ? OR t1.prefix LIKE ? OR t2.comment LIKE ?"
|
||||
sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike)
|
||||
sql += " AND (t1.name LIKE ? OR t1.prefix LIKE ? OR t1.upc LIKE ? OR t2.comment LIKE ?"
|
||||
sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike)
|
||||
|
||||
if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil {
|
||||
sql += " OR t2.jd_id = ? OR t4.id = ?"
|
||||
sqlParams = append(sqlParams, keywordInt64, keywordInt64)
|
||||
sql += " OR t1.id = ? OR t2.id = ? OR t2.jd_id = ? OR t4.ebai_id = ? OR t4.mtwm_id = ?"
|
||||
sqlParams = append(sqlParams, keywordInt64, keywordInt64, keywordInt64, keywordInt64, keywordInt64)
|
||||
}
|
||||
sql += ")"
|
||||
}
|
||||
@@ -197,14 +212,36 @@ func GetStoresSkus(ctx *jxcontext.Context, storeIDs []int, isFocus bool, keyword
|
||||
sqlParams = append(sqlParams, skuIDs)
|
||||
}
|
||||
}
|
||||
if isFocus && params["fromStatus"] != nil {
|
||||
fromStatus := params["fromStatus"].(int)
|
||||
toStatus := fromStatus
|
||||
if params["toStatus"] != nil {
|
||||
toStatus = params["toStatus"].(int)
|
||||
if isFocus {
|
||||
if params["fromStatus"] != nil {
|
||||
fromStatus := params["fromStatus"].(int)
|
||||
toStatus := fromStatus
|
||||
if params["toStatus"] != nil {
|
||||
toStatus = params["toStatus"].(int)
|
||||
}
|
||||
sql += " AND t4.status >= ? AND t4.status <= ?"
|
||||
sqlParams = append(sqlParams, fromStatus, toStatus)
|
||||
}
|
||||
if params["jdSyncStatus"] != nil || params["ebaiSyncStatus"] != nil || params["mtwmSyncStatus"] != nil {
|
||||
realVendorMap, err2 := getValidStoreVendorMap(db, storeIDs)
|
||||
if err = err2; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sql += " AND ( 1 = 0"
|
||||
if params["jdSyncStatus"] != nil && realVendorMap[model.VendorIDJD] == 1 {
|
||||
sql += " OR (t4.jd_sync_status & ? <> 0 AND t4.jd_sync_status & ? = 0 AND t2.jd_id <> 0 AND t1.status = ? AND t2.status = ?)"
|
||||
sqlParams = append(sqlParams, params["jdSyncStatus"], model.SyncFlagDeletedMask|model.SyncFlagNewMask, model.SkuStatusNormal, model.SkuStatusNormal)
|
||||
}
|
||||
if params["ebaiSyncStatus"] != nil && realVendorMap[model.VendorIDEBAI] == 1 {
|
||||
sql += " OR (t4.ebai_sync_status & ? <> 0 AND t4.ebai_sync_status & ? = 0)"
|
||||
sqlParams = append(sqlParams, params["ebaiSyncStatus"], model.SyncFlagDeletedMask|model.SyncFlagNewMask)
|
||||
}
|
||||
if params["mtwmSyncStatus"] != nil && realVendorMap[model.VendorIDMTWM] == 1 {
|
||||
sql += " OR (t4.mtwm_sync_status & ? <> 0 AND t4.mtwm_sync_status & ? = 0)"
|
||||
sqlParams = append(sqlParams, params["mtwmSyncStatus"], model.SyncFlagDeletedMask|model.SyncFlagNewMask)
|
||||
}
|
||||
sql += ")"
|
||||
}
|
||||
sql += " AND t4.status >= ? AND t4.status <= ?"
|
||||
sqlParams = append(sqlParams, fromStatus, toStatus)
|
||||
}
|
||||
sql += `
|
||||
GROUP BY
|
||||
@@ -392,6 +429,80 @@ func GetStoresSkus(ctx *jxcontext.Context, storeIDs []int, isFocus bool, keyword
|
||||
return skuNamesInfo, err
|
||||
}
|
||||
|
||||
func getValidStoreVendorMap(db *dao.DaoDB, storeIDs []int) (realVendorMap map[int]int, err error) {
|
||||
storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, model.StoreStatusAll)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
realVendorMap = make(map[int]int)
|
||||
for _, v := range storeMapList {
|
||||
if v.IsSync != 0 {
|
||||
realVendorMap[v.VendorID] = 1
|
||||
}
|
||||
}
|
||||
return realVendorMap, nil
|
||||
}
|
||||
|
||||
func GetStoreAbnormalSkuCount(ctx *jxcontext.Context, storeID, syncStatus int, isBySku bool, params map[string]interface{}) (count int, err error) {
|
||||
db := dao.GetDB()
|
||||
realVendorMap, err2 := getValidStoreVendorMap(db, []int{storeID})
|
||||
if err = err2; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
sql := `
|
||||
SELECT COUNT(*) ct`
|
||||
if !isBySku {
|
||||
sql += `
|
||||
FROM (
|
||||
SELECT DISTINCT t3.id`
|
||||
}
|
||||
sql += `
|
||||
FROM store_sku_bind t1
|
||||
JOIN sku t2 ON t2.id = t1.sku_id AND t2.deleted_at = ?
|
||||
JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ?
|
||||
WHERE t1.deleted_at = ? AND t1.store_id = ? AND
|
||||
((t2.status = ? AND t3.status = ?) OR t1.status = ?) AND
|
||||
(1 = 0`
|
||||
sqlParams := []interface{}{
|
||||
utils.DefaultTimeValue,
|
||||
utils.DefaultTimeValue,
|
||||
utils.DefaultTimeValue,
|
||||
storeID,
|
||||
model.SkuStatusNormal,
|
||||
model.SkuStatusNormal,
|
||||
model.SkuStatusNormal,
|
||||
}
|
||||
for _, vendorID := range []int{model.VendorIDJD, model.VendorIDEBAI, model.VendorIDMTWM} {
|
||||
if realVendorMap[vendorID] != 0 {
|
||||
prefix := dao.ConvertDBFieldPrefix(model.VendorNames[vendorID])
|
||||
sql += fmt.Sprintf(" OR (t1.%s_sync_status & ? <> 0 AND t1.%s_sync_status & ? = 0", prefix, prefix)
|
||||
sqlParams = append(sqlParams, syncStatus, model.SyncFlagDeletedMask|model.SyncFlagNewMask)
|
||||
if model.MultiStoresVendorMap[vendorID] == 1 {
|
||||
sql += fmt.Sprintf(" AND t2.%s_id <> 0 AND t2.status = ? AND t3.status = ?", prefix)
|
||||
sqlParams = append(sqlParams, model.SkuStatusNormal, model.SkuStatusNormal)
|
||||
}
|
||||
sql += ")"
|
||||
}
|
||||
}
|
||||
sql += ")"
|
||||
if params["fromStatus"] != nil {
|
||||
fromStatus := params["fromStatus"].(int)
|
||||
toStatus := fromStatus
|
||||
if params["toStatus"] != nil {
|
||||
toStatus = params["toStatus"].(int)
|
||||
}
|
||||
sql += " AND t1.status >= ? AND t1.status <= ?"
|
||||
sqlParams = append(sqlParams, fromStatus, toStatus)
|
||||
}
|
||||
if !isBySku {
|
||||
sql += `
|
||||
) t1`
|
||||
}
|
||||
err = dao.GetRow(db, &count, sql, sqlParams...)
|
||||
return count, err
|
||||
}
|
||||
|
||||
func GetStoresSkusSaleInfo(ctx *jxcontext.Context, storeIDs []int, skuIDs []int, fromTime, toTime time.Time, fromCount, toCount int) (saleInfoList []*SkuSaleInfo, err error) {
|
||||
globals.SugarLogger.Debugf("GetStoresSkusSaleInfo storeIDs:%v, fromTime:%v, toTime:%v, fromCount:%d, toCount:%d", storeIDs, fromTime, toTime, fromCount, toCount)
|
||||
|
||||
@@ -436,24 +547,65 @@ func UpdateStoreSku(ctx *jxcontext.Context, storeID int, skuBindInfo *StoreSkuBi
|
||||
}
|
||||
|
||||
func UpdateStoreSkus(ctx *jxcontext.Context, storeID int, skuBindInfos []*StoreSkuBindInfo, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
// skuIDs, err := updateStoresSkusWithoutSync(ctx, []int{storeID}, skuBindInfos)
|
||||
// num = int64(len(skuIDs))
|
||||
// if err == nil && num > 0 {
|
||||
// db := dao.GetDB()
|
||||
// _, err = CurVendorSync.SyncStoresSkus(ctx, db, nil, []int{storeID}, skuIDs, false, false)
|
||||
// return int64(len(skuIDs)), err
|
||||
// }
|
||||
// return 0, err
|
||||
return UpdateStoresSkus(ctx, []int{storeID}, skuBindInfos, isAsync, isContinueWhenError)
|
||||
}
|
||||
|
||||
func UpdateStoresSkus(ctx *jxcontext.Context, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
var num int64
|
||||
skuIDs, err := updateStoresSkusWithoutSync(ctx, storeIDs, skuBindInfos)
|
||||
db := dao.GetDB()
|
||||
skuIDs, err := updateStoresSkusWithoutSync(ctx, db, storeIDs, skuBindInfos)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
num = int64(len(skuIDs))
|
||||
if num > 0 {
|
||||
db := dao.GetDB()
|
||||
hint, err = CurVendorSync.SyncStoresSkus(ctx, db, nil, storeIDs, skuIDs, isAsync, isContinueWhenError)
|
||||
hint, err = CurVendorSync.SyncStoresSkus(ctx, db, nil, storeIDs, skuIDs, false, isAsync, isContinueWhenError)
|
||||
}
|
||||
if num == 0 || !isAsync || hint == "" {
|
||||
hint = utils.Int64ToStr(num)
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func UpdateStoresSkusByBind(ctx *jxcontext.Context, skuBindInfos []*StoreSkuBindInfo, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
if len(skuBindInfos) > maxStoreNameBind {
|
||||
return "", fmt.Errorf("门店商品信息大于%d", maxStoreNameBind)
|
||||
}
|
||||
skuBindInfosMap := make(map[int][]*StoreSkuBindInfo)
|
||||
storeIDMap := make(map[int]int)
|
||||
for _, v := range skuBindInfos {
|
||||
if v.StoreID > 9 {
|
||||
skuBindInfosMap[v.StoreID] = append(skuBindInfosMap[v.StoreID], v)
|
||||
storeIDMap[v.StoreID] = 1
|
||||
}
|
||||
}
|
||||
storeIDs := jxutils.IntMap2List(storeIDMap)
|
||||
sort.Ints(storeIDs)
|
||||
var num int64
|
||||
skuIDMap := make(map[int]int)
|
||||
db := dao.GetDB()
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
dao.Rollback(db)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
for _, storeID := range storeIDs {
|
||||
skuIDs, err2 := updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosMap[storeID])
|
||||
if err = err2; err != nil {
|
||||
dao.Rollback(db)
|
||||
return "", err
|
||||
}
|
||||
for _, v := range skuIDs {
|
||||
skuIDMap[v] = 1
|
||||
}
|
||||
num += int64(len(skuIDs))
|
||||
}
|
||||
dao.Commit(db)
|
||||
if num > 0 {
|
||||
skuIDs := jxutils.IntMap2List(skuIDMap)
|
||||
hint, err = CurVendorSync.SyncStoresSkus(ctx, db, nil, storeIDs, skuIDs, false, isAsync, isContinueWhenError)
|
||||
}
|
||||
if num == 0 || !isAsync || hint == "" {
|
||||
hint = utils.Int64ToStr(num)
|
||||
@@ -504,13 +656,41 @@ func checkStoresSkusSaleCity(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs []i
|
||||
return err
|
||||
}
|
||||
|
||||
func updateStoresSkusWithoutSync(ctx *jxcontext.Context, storeIDs []int, skuBindInfos []*StoreSkuBindInfo) (needSyncSkus []int, err error) {
|
||||
func uniqueStoreIDs(storeIDs []int) []int {
|
||||
storeIDMap := make(map[int]int)
|
||||
for _, v := range storeIDs {
|
||||
storeIDMap[v] = 1
|
||||
}
|
||||
return jxutils.IntMap2List(storeIDMap)
|
||||
}
|
||||
|
||||
func uniqueStoreNameBind(skuBindInfos []*StoreSkuBindInfo) (outSkuBindInfos []*StoreSkuBindInfo) {
|
||||
nameIDMap := make(map[int]int)
|
||||
for _, v := range skuBindInfos {
|
||||
if nameIDMap[v.NameID] != 1 {
|
||||
outSkuBindInfos = append(outSkuBindInfos, v)
|
||||
nameIDMap[v.NameID] = 1
|
||||
}
|
||||
}
|
||||
return outSkuBindInfos
|
||||
}
|
||||
|
||||
func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs []int, skuBindInfos []*StoreSkuBindInfo) (needSyncSkus []int, err error) {
|
||||
if len(storeIDs)*len(skuBindInfos) > maxStoreNameBind2 {
|
||||
return nil, fmt.Errorf("门店商品信息大于%d", maxStoreNameBind2)
|
||||
}
|
||||
|
||||
storeIDs = uniqueStoreIDs(storeIDs)
|
||||
skuBindInfos = uniqueStoreNameBind(skuBindInfos)
|
||||
|
||||
sort.Ints(storeIDs)
|
||||
globals.SugarLogger.Debugf("updateStoresSkusWithoutSync, storeIDs:%v, skuBindInfos:%s", storeIDs, utils.Format4Output(skuBindInfos, false))
|
||||
db := dao.GetDB()
|
||||
if err = checkStoresSkusSaleCity(ctx, db, storeIDs, skuBindInfos); err != nil {
|
||||
return nil, err
|
||||
if db == nil {
|
||||
db = dao.GetDB()
|
||||
}
|
||||
// if err = checkStoresSkusSaleCity(ctx, db, storeIDs, skuBindInfos); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
if storeIDs, skuBindInfos, err = filterStorePriceChange(ctx, storeIDs, skuBindInfos); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -527,27 +707,45 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, storeIDs []int, skuBind
|
||||
}()
|
||||
for _, storeID := range storeIDs {
|
||||
for _, skuBindInfo := range skuBindInfos {
|
||||
// 关注且没有给价时,需要尝试从store_sku_bind中得到已有的单价
|
||||
needGetExistingUnitPrice := skuBindInfo.UnitPrice == 0 && skuBindInfo.IsFocus == 1
|
||||
inSkuBinds := skuBindInfo.Skus
|
||||
var allBinds []*tStoreSkuBindAndSpec
|
||||
sql := `
|
||||
SELECT
|
||||
t2.*,
|
||||
t1.id real_sku_id, t1.spec_quality, t1.spec_unit,
|
||||
t3.price sku_name_price, t3.unit sku_name_unit
|
||||
t1.id real_sku_id, t1.spec_quality, t1.spec_unit,`
|
||||
if needGetExistingUnitPrice {
|
||||
sql += " IF(t5.unit_price > 0, t5.unit_price, t3.price) sku_name_price,"
|
||||
}
|
||||
sql += `
|
||||
t3.unit sku_name_unit, t3.name
|
||||
FROM sku t1
|
||||
JOIN store ts ON ts.id = ? AND ts.deleted_at = ?
|
||||
LEFT JOIN store_sku_bind t2 ON t2.sku_id = t1.id AND t2.store_id = ts.id AND t2.deleted_at = ?
|
||||
JOIN sku_name t3 ON t1.name_id = t3.id AND t3.deleted_at = ?
|
||||
WHERE t1.name_id = ? AND t1.deleted_at = ?
|
||||
FOR UPDATE`
|
||||
JOIN sku_name t3 ON t1.name_id = t3.id AND t3.deleted_at = ?`
|
||||
sqlParams := []interface{}{
|
||||
storeID,
|
||||
utils.DefaultTimeValue,
|
||||
utils.DefaultTimeValue,
|
||||
utils.DefaultTimeValue,
|
||||
skuBindInfo.NameID,
|
||||
utils.DefaultTimeValue,
|
||||
}
|
||||
if needGetExistingUnitPrice {
|
||||
sql += `
|
||||
LEFT JOIN (
|
||||
SELECT t7.store_id, t8.name_id, CAST(AVG(t7.unit_price) AS SIGNED) unit_price
|
||||
FROM store_sku_bind t7
|
||||
JOIN sku t8 ON t8.id = t7.sku_id AND t8.name_id = ?
|
||||
WHERE t7.deleted_at = ? AND t7.store_id = ?
|
||||
GROUP BY 1,2
|
||||
) t5 ON t5.store_id = ts.id AND t5.name_id = t1.name_id`
|
||||
sqlParams = append(sqlParams, skuBindInfo.NameID, utils.DefaultTimeValue, storeID)
|
||||
}
|
||||
sql += `
|
||||
WHERE t1.name_id = ? AND t1.deleted_at = ?
|
||||
FOR UPDATE`
|
||||
sqlParams = append(sqlParams, skuBindInfo.NameID, utils.DefaultTimeValue)
|
||||
// globals.SugarLogger.Debug(sql)
|
||||
if err = dao.GetRows(db, &allBinds, sql, sqlParams...); err == nil {
|
||||
if len(allBinds) > 0 {
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(allBinds, false))
|
||||
@@ -557,6 +755,10 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, storeIDs []int, skuBind
|
||||
}
|
||||
unitPrice := 0
|
||||
if skuBindInfo.UnitPrice != 0 {
|
||||
if skuBindInfo.UnitPrice > MaxSkuUnitPrice {
|
||||
dao.Rollback(db)
|
||||
return nil, fmt.Errorf("商品:%s价格:%s太夸张", allBinds[0].Name, jxutils.IntPrice2StandardCurrencyString(int64(skuBindInfo.UnitPrice)))
|
||||
}
|
||||
unitPrice = skuBindInfo.UnitPrice
|
||||
} else {
|
||||
unitPrice = allBinds[0].UnitPrice
|
||||
@@ -650,7 +852,7 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, storeIDs []int, skuBind
|
||||
updateFieldMap[model.FieldUpdatedAt] = 1
|
||||
updateFieldMap[model.FieldLastOperator] = 1
|
||||
|
||||
setStoreSkuBindStatus(skuBind, model.SyncFlagModifiedMask)
|
||||
// setStoreSkuBindStatus(skuBind, model.SyncFlagModifiedMask)
|
||||
dao.WrapUpdateULEntity(skuBind, userName)
|
||||
if num, err = dao.UpdateEntity(db, skuBind /*, utils.Map2KeySlice(updateFieldMap)...*/); err != nil {
|
||||
dao.Rollback(db)
|
||||
@@ -712,11 +914,11 @@ func updateStoreSkusSaleWithoutSync(ctx *jxcontext.Context, storeID int, skuBind
|
||||
}
|
||||
if num, err = dao.UpdateEntityLogically(db, skuBind, map[string]interface{}{
|
||||
model.FieldStatus: skuBind.Status,
|
||||
model.FieldJdSyncStatus: skuBind.JdSyncStatus | model.SyncFlagSaleMask | model.SyncFlagModifiedMask,
|
||||
model.FieldEbaiSyncStatus: skuBind.EbaiSyncStatus | model.SyncFlagSaleMask | model.SyncFlagModifiedMask,
|
||||
model.FieldMtwmSyncStatus: skuBind.MtwmSyncStatus | model.SyncFlagSaleMask | model.SyncFlagModifiedMask,
|
||||
model.FieldElmSyncStatus: skuBind.ElmSyncStatus | model.SyncFlagSaleMask | model.SyncFlagModifiedMask,
|
||||
model.FieldWscSyncStatus: skuBind.WscSyncStatus | model.SyncFlagSaleMask | model.SyncFlagModifiedMask,
|
||||
model.FieldJdSyncStatus: skuBind.JdSyncStatus | model.SyncFlagSaleMask,
|
||||
model.FieldEbaiSyncStatus: skuBind.EbaiSyncStatus | model.SyncFlagSaleMask,
|
||||
model.FieldMtwmSyncStatus: skuBind.MtwmSyncStatus | model.SyncFlagSaleMask,
|
||||
model.FieldElmSyncStatus: skuBind.ElmSyncStatus | model.SyncFlagSaleMask,
|
||||
model.FieldWscSyncStatus: skuBind.WscSyncStatus | model.SyncFlagSaleMask,
|
||||
}, userName, map[string]interface{}{
|
||||
model.FieldStoreID: storeID,
|
||||
model.FieldSkuID: v.SkuID,
|
||||
@@ -734,7 +936,21 @@ func updateStoreSkusSaleWithoutSync(ctx *jxcontext.Context, storeID int, skuBind
|
||||
return needSyncSkus, err
|
||||
}
|
||||
|
||||
func uniqueStoreSkuBind(skuBindSkuInfos []*StoreSkuBindSkuInfo) (outSkuBindSkuInfos []*StoreSkuBindSkuInfo) {
|
||||
skuIDMap := make(map[int]int)
|
||||
for _, v := range skuBindSkuInfos {
|
||||
if skuIDMap[v.SkuID] != 1 {
|
||||
outSkuBindSkuInfos = append(outSkuBindSkuInfos, v)
|
||||
skuIDMap[v.SkuID] = 1
|
||||
}
|
||||
}
|
||||
return outSkuBindSkuInfos
|
||||
}
|
||||
|
||||
func UpdateStoresSkusSale(ctx *jxcontext.Context, storeIDs []int, skuBindSkuInfos []*StoreSkuBindSkuInfo, userName string, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
storeIDs = uniqueStoreIDs(storeIDs)
|
||||
skuBindSkuInfos = uniqueStoreSkuBind(skuBindSkuInfos)
|
||||
|
||||
var num int64
|
||||
for _, storeID := range storeIDs {
|
||||
skuIDs, err2 := updateStoreSkusSaleWithoutSync(ctx, storeID, skuBindSkuInfos, userName)
|
||||
@@ -749,7 +965,7 @@ func UpdateStoresSkusSale(ctx *jxcontext.Context, storeIDs []int, skuBindSkuInfo
|
||||
skuIDs = append(skuIDs, v.SkuID)
|
||||
}
|
||||
db := dao.GetDB()
|
||||
hint, err = CurVendorSync.SyncStoresSkus(ctx, db, nil, storeIDs, skuIDs, isAsync, isContinueWhenError)
|
||||
hint, err = CurVendorSync.SyncStoresSkus(ctx, db, nil, storeIDs, skuIDs, false, isAsync, isContinueWhenError)
|
||||
}
|
||||
if num == 0 || !isAsync || hint == "" {
|
||||
hint = utils.Int64ToStr(num)
|
||||
@@ -823,11 +1039,11 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode
|
||||
now,
|
||||
pricePercentage,
|
||||
pricePercentage,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask,
|
||||
model.SyncFlagPriceMask,
|
||||
model.SyncFlagPriceMask,
|
||||
model.SyncFlagPriceMask,
|
||||
model.SyncFlagPriceMask,
|
||||
model.SyncFlagPriceMask,
|
||||
toStoreID,
|
||||
utils.DefaultTimeValue,
|
||||
}
|
||||
@@ -927,11 +1143,11 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode
|
||||
pricePercentage,
|
||||
pricePercentage,
|
||||
pricePercentage,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask | model.SyncFlagSaleMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask | model.SyncFlagSaleMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask | model.SyncFlagSaleMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask | model.SyncFlagSaleMask,
|
||||
model.SyncFlagModifiedMask | model.SyncFlagPriceMask | model.SyncFlagSaleMask,
|
||||
model.SyncFlagStoreSkuOnlyMask,
|
||||
model.SyncFlagStoreSkuOnlyMask,
|
||||
model.SyncFlagStoreSkuOnlyMask,
|
||||
model.SyncFlagStoreSkuOnlyMask,
|
||||
model.SyncFlagStoreSkuOnlyMask,
|
||||
toStoreID,
|
||||
utils.DefaultTimeValue,
|
||||
}
|
||||
@@ -1349,3 +1565,186 @@ func checkStoreExisting(db *dao.DaoDB, storeID int) (err error) {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RefreshStoresSkuByVendor(ctx *jxcontext.Context, storeIDs []int, vendorID int, isAsync bool) (hint string, err error) {
|
||||
if vendorID != model.VendorIDJD {
|
||||
return "", fmt.Errorf("此功能当前只支持京东到家平台")
|
||||
}
|
||||
db := dao.GetDB()
|
||||
storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, model.StoreStatusAll)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(storeMapList) != len(storeIDs) {
|
||||
return "", fmt.Errorf("门店绑定信息不匹配,请确定门店绑定且只绑定了京东平台")
|
||||
}
|
||||
storeMap := make(map[int]*model.StoreMap)
|
||||
for _, v := range storeMapList {
|
||||
if v.VendorID != vendorID {
|
||||
return "", fmt.Errorf("门店%d绑定的不(只)是京东", v.StoreID)
|
||||
}
|
||||
storeMap[v.StoreID] = v
|
||||
}
|
||||
|
||||
handler := partner.GetPurchasePlatformFromVendorID(vendorID)
|
||||
var storeSkuList []*model.StoreSkuBind
|
||||
rootTask := tasksch.NewSeqTask(fmt.Sprintf("根据厂家门店商品信息相应刷新本地数据:%v", storeIDs), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
switch step {
|
||||
case 0:
|
||||
storeSkuList, err = handler.GetStoresSku(ctx, task, storeIDs)
|
||||
case 1:
|
||||
if len(storeSkuList) > 0 {
|
||||
var skuList []*model.SkuAndName
|
||||
skuList, err = dao.GetSkus(db, nil, nil, nil, nil)
|
||||
if err == nil {
|
||||
skuNameMap := make(map[int]*model.SkuName)
|
||||
skuMap := make(map[int]*model.SkuAndName)
|
||||
for _, sku := range skuList {
|
||||
if skuNameMap[sku.NameID] == nil {
|
||||
skuNameMap[sku.NameID] = &model.SkuName{
|
||||
Unit: sku.Unit,
|
||||
}
|
||||
}
|
||||
skuMap[sku.ID] = sku
|
||||
}
|
||||
for _, v := range storeSkuList {
|
||||
sku := skuMap[v.SkuID]
|
||||
skuName := skuNameMap[sku.NameID]
|
||||
if skuName.IsGlobal == 0 && (jxutils.IsSkuSpecial(sku.SpecQuality, sku.SpecUnit) || skuName.Unit != model.SpecialUnit) {
|
||||
skuName.Price = v.Price
|
||||
skuName.IsGlobal = 1 // 标准价
|
||||
}
|
||||
}
|
||||
for _, v := range storeSkuList {
|
||||
sku := skuMap[v.SkuID]
|
||||
skuName := skuNameMap[sku.NameID]
|
||||
if skuName.IsGlobal == 0 {
|
||||
if skuName.Price == 0 {
|
||||
skuName.Price = jxutils.CaculateUnitPrice(v.Price, sku.SpecQuality, sku.SpecUnit, skuName.Unit)
|
||||
} else {
|
||||
skuName.Price = (skuName.Price + jxutils.CaculateUnitPrice(v.Price, sku.SpecQuality, sku.SpecUnit, skuName.Unit)) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range storeSkuList {
|
||||
pricePercentage := int(storeMap[v.StoreID].PricePercentage)
|
||||
skuName := skuNameMap[skuMap[v.SkuID].NameID]
|
||||
v.Price = jxutils.CaculateSkuPriceFromVendor(v.Price, pricePercentage, 0)
|
||||
v.UnitPrice = jxutils.CaculateSkuPriceFromVendor(skuName.Price, pricePercentage, 0)
|
||||
dao.WrapAddIDCULDEntity(v, ctx.GetUserName())
|
||||
setStoreSkuBindStatus(v, model.SyncFlagNewMask)
|
||||
v.JdSyncStatus = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if len(storeSkuList) > 0 {
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil || err != nil {
|
||||
dao.Rollback(db)
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if _, err = dao.ExecuteSQL(db, `
|
||||
DELETE t1
|
||||
FROM store_sku_bind t1
|
||||
WHERE t1.store_id IN (
|
||||
`+dao.GenQuestionMarks(len(storeIDs))+")", storeIDs); err == nil {
|
||||
if err = dao.CreateMultiEntities(db, storeSkuList); err == nil {
|
||||
hint = utils.Int2Str(len(storeSkuList))
|
||||
dao.Commit(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}, 3)
|
||||
tasksch.ManageTask(rootTask).Run()
|
||||
if isAsync {
|
||||
hint = rootTask.GetID()
|
||||
} else {
|
||||
_, err = rootTask.GetResult(0)
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func GetVendorStoreSkusInfo(ctx *jxcontext.Context, storeID int, vendorIDs, skuIDs []int, isContinueWhenError bool) (skuVendorMap map[int][]*partner.BareStoreSkuInfo, err error) {
|
||||
globals.SugarLogger.Debugf("GetVendorStoreSkusInfo, storeID:%d, vendorIDs:%v, skuID:%v", storeID, vendorIDs, skuIDs)
|
||||
db := dao.GetDB()
|
||||
var locker sync.RWMutex
|
||||
skuVendorMap = make(map[int][]*partner.BareStoreSkuInfo)
|
||||
_, err = CurVendorSync.LoopStoresMap(ctx, db, fmt.Sprintf("GetVendorStoreSkusInfo storeID:%d", storeID), false, false, vendorIDs, []int{storeID},
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
if handler := CurVendorSync.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
|
||||
storeSkuList, err2 := dao.GetStoreSkus2(db, loopMapInfo.VendorID, storeID, skuIDs, false)
|
||||
if err = err2; err == nil && len(storeSkuList) > 0 {
|
||||
bareStoreSkuInfoList := make([]*partner.BareStoreSkuInfo, len(skuIDs))
|
||||
for k, v := range storeSkuList {
|
||||
bareStoreSkuInfoList[k] = &partner.BareStoreSkuInfo{
|
||||
SkuID: v.SkuID,
|
||||
VendorSkuID: v.VendorSkuID,
|
||||
}
|
||||
}
|
||||
outBareStoreSkuInfoList, err2 := handler.GetStoreSkusInfo(ctx, t, loopMapInfo.StoreMapList[0].StoreID, loopMapInfo.StoreMapList[0].VendorStoreID, bareStoreSkuInfoList)
|
||||
if err = err2; err == nil && outBareStoreSkuInfoList != nil {
|
||||
locker.Lock()
|
||||
defer locker.Unlock()
|
||||
skuVendorMap[loopMapInfo.VendorID] = outBareStoreSkuInfoList
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}, true)
|
||||
if err != nil {
|
||||
skuVendorMap = nil
|
||||
}
|
||||
return skuVendorMap, err
|
||||
}
|
||||
|
||||
func SyncJdStoreProducts(ctx *jxcontext.Context, storeIDs, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
db := dao.GetDB()
|
||||
isManageIt := len(storeIDs) != 1 || len(skuIDs) == 0 || len(skuIDs) > 8
|
||||
hint, err = CurVendorSync.LoopStoresMap(ctx, db, fmt.Sprintf("京东商家商品状态同步:%v", storeIDs), isAsync, isManageIt, []int{model.VendorIDJD}, storeIDs,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
if handler := partner.GetPurchasePlatformFromVendorID(loopMapInfo.VendorID); handler != nil {
|
||||
jdHandler := handler.(*jd.PurchaseHandler)
|
||||
hint, err2 := jdHandler.SyncStoreProducts(ctx, t, loopMapInfo.StoreMapList[0].StoreID, skuIDs, false, isContinueWhenError)
|
||||
if err = err2; err == nil {
|
||||
retVal = []interface{}{hint}
|
||||
}
|
||||
}
|
||||
return retVal, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}, isContinueWhenError)
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func GetMissingStoreSkuFromOrder(ctx *jxcontext.Context, fromTime time.Time) (missingList []*StoreSkuBindInfo, err error) {
|
||||
storeSkuList, err := dao.GetMissingStoreSkuFromOrder(dao.GetDB(), nil, fromTime)
|
||||
if err == nil {
|
||||
storeSkuNameMap := make(map[int64]*StoreSkuBindInfo)
|
||||
for _, v := range storeSkuList {
|
||||
skuName := storeSkuNameMap[jxutils.Combine2Int(v.StoreID, v.NameID)]
|
||||
if skuName == nil {
|
||||
skuName = &StoreSkuBindInfo{
|
||||
StoreID: v.StoreID,
|
||||
NameID: v.NameID,
|
||||
IsFocus: 1,
|
||||
IsSale: 1,
|
||||
// 这里没有考虑平台价格比例
|
||||
UnitPrice: jxutils.CaculateUnitPrice(v.RefPrice, v.SpecQuality, v.SpecUnit, v.Unit),
|
||||
}
|
||||
missingList = append(missingList, skuName)
|
||||
}
|
||||
skuName.Skus = append(skuName.Skus, &StoreSkuBindSkuInfo{
|
||||
SkuID: v.SkuID,
|
||||
})
|
||||
}
|
||||
}
|
||||
return missingList, err
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ func init() {
|
||||
}
|
||||
|
||||
func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int, storeStatus int) (err error) {
|
||||
return err
|
||||
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeStatus:%d", vendorStoreID, storeStatus)
|
||||
db := dao.GetDB()
|
||||
storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
@@ -81,14 +82,14 @@ func Init() {
|
||||
}
|
||||
|
||||
func (p *MultiStoreHandlerWrapper) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
|
||||
if jxutils.IsFakeID(cat.JdID) {
|
||||
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.IsFakeID(cat.JdID) {
|
||||
if jxutils.IsEmptyID(cat.JdID) {
|
||||
globals.SugarLogger.Warnf("UpdateCategory fakeid cat:%s should not get here", utils.Format4Output(cat, true))
|
||||
return nil
|
||||
}
|
||||
@@ -97,14 +98,14 @@ func (p *MultiStoreHandlerWrapper) UpdateCategory(db *dao.DaoDB, cat *model.SkuC
|
||||
|
||||
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.IsFakeID(sku.JdID) {
|
||||
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.IsFakeID(sku.JdID) {
|
||||
if jxutils.IsEmptyID(sku.JdID) {
|
||||
globals.SugarLogger.Warnf("UpdateSku fakeid sku:%s should not get here", utils.Format4Output(sku, true))
|
||||
return nil
|
||||
}
|
||||
@@ -213,32 +214,36 @@ func (v *VendorSync) SyncStore(ctx *jxcontext.Context, db *dao.DaoDB, vendorID,
|
||||
vendorID,
|
||||
}
|
||||
}
|
||||
hint, err = v.LoopStoresMap(ctx, db, fmt.Sprintf("同步门店信息:%d", storeID), isAsync, false, vendorIDs, []int{storeID}, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
hint, err = v.LoopStoresMap(ctx, db, fmt.Sprintf("同步门店信息:%d", storeID), isAsync, false, vendorIDs, []int{storeID}, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (resultList interface{}, err error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
handler := v.GetStoreHandler(loopMapInfo.VendorID)
|
||||
if len(loopMapInfo.StoreMapList) > 1 {
|
||||
loopStoreTask := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
var resultList []interface{}
|
||||
storeMap := batchItemList[0].(*model.StoreMap)
|
||||
if err = handler.UpdateStore(db, storeMap.StoreID, userName); err == nil {
|
||||
storeMap.SyncStatus = 0
|
||||
_, err = dao.UpdateEntity(db, storeMap, model.FieldSyncStatus)
|
||||
resultList = append(resultList, 1)
|
||||
}
|
||||
return nil, err
|
||||
return resultList, err
|
||||
}, loopMapInfo.StoreMapList)
|
||||
t.AddChild(loopStoreTask).Run()
|
||||
_, err = loopStoreTask.GetResult(0)
|
||||
return nil, err
|
||||
resultList, err = loopStoreTask.GetResult(0)
|
||||
} else {
|
||||
storeMap := loopMapInfo.StoreMapList[0]
|
||||
if err = handler.UpdateStore(db, storeMap.StoreID, userName); err == nil {
|
||||
storeMap.SyncStatus = 0
|
||||
_, err = dao.UpdateEntity(db, storeMap, model.FieldSyncStatus)
|
||||
}
|
||||
if err == nil {
|
||||
resultList = []interface{}{1}
|
||||
}
|
||||
}
|
||||
storeMap := loopMapInfo.StoreMapList[0]
|
||||
if err = handler.UpdateStore(db, storeMap.StoreID, userName); err == nil {
|
||||
storeMap.SyncStatus = 0
|
||||
_, err = dao.UpdateEntity(db, storeMap, model.FieldSyncStatus)
|
||||
}
|
||||
err = jxutils.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
return nil, err
|
||||
})
|
||||
return hint, err
|
||||
return resultList, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}, true)
|
||||
return hint, makeSyncError(err)
|
||||
}
|
||||
|
||||
func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
|
||||
@@ -259,6 +264,7 @@ func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []i
|
||||
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameIDs:%v, skuIDs:%v, userName:%s", ctx.GetTrackInfo(), nameIDs, skuIDs, userName)
|
||||
return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameIDs:%v, skuIDs:%v", nameIDs, skuIDs), isAsync, userName,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
var resultList []interface{}
|
||||
vendorID := batchItemList[0].(int)
|
||||
multiStoresHandler := v.GetMultiStoreHandler(vendorID)
|
||||
syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()])
|
||||
@@ -297,6 +303,7 @@ func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []i
|
||||
// todo 同一skuName下的sku顺序处理的原因是京东SPU特殊类型必须要序列化同步才能正常处理, db可能会有多线程问题
|
||||
task := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[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(`
|
||||
@@ -333,6 +340,8 @@ func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []i
|
||||
refutil.SetObjFieldByName(sku, syncStatusFieldName, int8(0))
|
||||
if _, err = dao.UpdateEntity(db, sku, updateFields...); err != nil {
|
||||
break
|
||||
} else {
|
||||
resultList = append(resultList, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,22 +351,28 @@ func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []i
|
||||
refutil.SetObjFieldByName(skuName, syncStatusFieldName, int8(0))
|
||||
_, err = dao.UpdateEntity(db, skuName, syncStatusFieldName)
|
||||
}
|
||||
return nil, err
|
||||
return resultList, err
|
||||
}, skuNameList)
|
||||
t.AddChild(task).Run()
|
||||
_, err = task.GetResult(0)
|
||||
result, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
resultList = append(resultList, result...)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
return resultList, err
|
||||
})
|
||||
}
|
||||
|
||||
func (v *VendorSync) SyncStoresCategory(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, storeIDs []int, isAsync bool) (hint string, err error) {
|
||||
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")
|
||||
isManageIt := len(storeIDs) != 1
|
||||
return v.LoopStoresMap(ctx, db, fmt.Sprintf("同步门店分类信息:%v", storeIDs), isAsync, isManageIt, vendorIDs, storeIDs,
|
||||
hint, err = v.LoopStoresMap(ctx, db, fmt.Sprintf("同步门店分类信息:%v", storeIDs), isAsync, isManageIt, vendorIDs, storeIDs,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
if handler := v.GetSingleStoreHandler(loopMapInfo.VendorID); handler != nil {
|
||||
if isForce {
|
||||
dao.SetStoreCategorySyncStatus(db, loopMapInfo.VendorID, storeIDs, nil, model.SyncFlagModifiedMask)
|
||||
}
|
||||
if len(loopMapInfo.StoreMapList) > 1 {
|
||||
loopStoreTask := tasksch.NewSeqTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
@@ -367,73 +382,120 @@ func (v *VendorSync) SyncStoresCategory(ctx *jxcontext.Context, db *dao.DaoDB, v
|
||||
}, len(loopMapInfo.StoreMapList))
|
||||
t.AddChild(loopStoreTask).Run()
|
||||
_, err = loopStoreTask.GetResult(0)
|
||||
return nil, err
|
||||
} else {
|
||||
_, err = handler.SyncStoreCategory(ctx, t, loopMapInfo.StoreMapList[0].StoreID, false)
|
||||
}
|
||||
_, err = handler.SyncStoreCategory(ctx, t, loopMapInfo.StoreMapList[0].StoreID, false)
|
||||
err = jxutils.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}
|
||||
return nil, err
|
||||
})
|
||||
return nil, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}, isContinueWhenError)
|
||||
return hint, makeSyncError(err)
|
||||
}
|
||||
|
||||
//
|
||||
func (v *VendorSync) SyncStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, storeIDs []int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
func (v *VendorSync) SyncStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, storeIDs []int, skuIDs []int, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
globals.SugarLogger.Debug("SyncStoresSkus")
|
||||
isManageIt := len(storeIDs) != 1 || len(skuIDs) == 0 || len(skuIDs) > 8
|
||||
return v.LoopStoresMap(ctx, db, fmt.Sprintf("同步门店商品信息:%v", storeIDs), isAsync, isManageIt, vendorIDs, storeIDs,
|
||||
task, hint, err := v.LoopStoresMap2(ctx, db, fmt.Sprintf("同步门店商品信息:%v", storeIDs), isAsync, isManageIt, vendorIDs, storeIDs,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
|
||||
if isForce {
|
||||
dao.SetStoreSkuSyncStatus(db, loopMapInfo.VendorID, storeIDs, skuIDs, model.SyncFlagModifiedMask)
|
||||
}
|
||||
if len(loopMapInfo.StoreMapList) > 1 {
|
||||
loopStoreTask := tasksch.NewSeqTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
storeID := loopMapInfo.StoreMapList[step].StoreID
|
||||
if _, err = handler.SyncStoreSkus(ctx, task, storeID, skuIDs, false, isContinueWhenError); err != nil {
|
||||
globals.SugarLogger.Debugf("SyncStoresSkus failed1 store:%d failed with error:%v", storeID, err)
|
||||
if isContinueWhenError {
|
||||
err = nil
|
||||
var loopStoreTask tasksch.ITask
|
||||
if model.MultiStoresVendorMap[loopMapInfo.VendorID] == 1 {
|
||||
loopStoreTask = tasksch.NewSeqTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
storeID := loopMapInfo.StoreMapList[step].StoreID
|
||||
if _, err = handler.SyncStoreSkus(ctx, task, storeID, skuIDs, false, isContinueWhenError); err != nil {
|
||||
globals.SugarLogger.Debugf("SyncStoresSkus failed1 store:%d failed with error:%v", storeID, err)
|
||||
if isContinueWhenError {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}, len(loopMapInfo.StoreMapList))
|
||||
return nil, err
|
||||
}, len(loopMapInfo.StoreMapList))
|
||||
} else {
|
||||
loopStoreTask = tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
storeMap := batchItemList[0].(*model.StoreMap)
|
||||
if _, err = handler.SyncStoreSkus(ctx, task, storeMap.StoreID, skuIDs, false, isContinueWhenError); err != nil {
|
||||
globals.SugarLogger.Debugf("SyncStoresSkus failed2 store:%d failed with error:%v", storeMap.StoreID, err)
|
||||
}
|
||||
return nil, err
|
||||
}, loopMapInfo.StoreMapList)
|
||||
}
|
||||
t.AddChild(loopStoreTask).Run()
|
||||
_, err = loopStoreTask.GetResult(0)
|
||||
return nil, err
|
||||
} else {
|
||||
_, err = handler.SyncStoreSkus(ctx, t, loopMapInfo.StoreMapList[0].StoreID, skuIDs, false, isContinueWhenError)
|
||||
}
|
||||
_, err = handler.SyncStoreSkus(ctx, t, loopMapInfo.StoreMapList[0].StoreID, skuIDs, false, isContinueWhenError)
|
||||
err = jxutils.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}
|
||||
return nil, err
|
||||
})
|
||||
return nil, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}, isContinueWhenError)
|
||||
if task != nil {
|
||||
if vendorErr := partner.IsErrChangePriceFailed(task.GetOriginalErr()); vendorErr != nil {
|
||||
platformList := make([]string, len(task.GetDetailErrList()))
|
||||
for k, v := range task.GetDetailErrList() {
|
||||
if vendorErr := partner.IsErrVendorError(v); vendorErr != nil {
|
||||
platformList[k] = model.VendorChineseNames[vendorErr.VendorID()]
|
||||
} else {
|
||||
platformList[k] = "未知"
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("同步价格失败\n失败平台:%s", strings.Join(platformList, ","))
|
||||
} else {
|
||||
err = makeSyncError(err)
|
||||
}
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func (v *VendorSync) FullSyncStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
globals.SugarLogger.Debug("FullSyncStoresSkus")
|
||||
return v.LoopStoresMap(ctx, db, fmt.Sprintf("初始化门店商品信息:%v", storeIDs), isAsync, true, vendorIDs, storeIDs,
|
||||
hint, err = v.LoopStoresMap(ctx, db, fmt.Sprintf("初始化门店商品信息:%v", storeIDs), isAsync, true, vendorIDs, storeIDs,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
|
||||
if len(loopMapInfo.StoreMapList) > 1 {
|
||||
loopStoreTask := tasksch.NewSeqTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
storeID := loopMapInfo.StoreMapList[step].StoreID
|
||||
_, err = handler.FullSyncStoreSkus(ctx, task, storeID, false, isContinueWhenError)
|
||||
return nil, err
|
||||
}, len(loopMapInfo.StoreMapList))
|
||||
var loopStoreTask tasksch.ITask
|
||||
if model.MultiStoresVendorMap[loopMapInfo.VendorID] == 1 {
|
||||
loopStoreTask = tasksch.NewSeqTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
storeID := loopMapInfo.StoreMapList[step].StoreID
|
||||
if _, err = handler.FullSyncStoreSkus(ctx, task, storeID, false, isContinueWhenError); err != nil {
|
||||
globals.SugarLogger.Debugf("FullSyncStoresSkus failed1 store:%d failed with error:%v", storeID, err)
|
||||
if isContinueWhenError {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}, len(loopMapInfo.StoreMapList))
|
||||
} else {
|
||||
loopStoreTask = tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
storeMap := batchItemList[0].(*model.StoreMap)
|
||||
if _, err = handler.FullSyncStoreSkus(ctx, task, storeMap.StoreID, false, isContinueWhenError); err != nil {
|
||||
globals.SugarLogger.Debugf("FullSyncStoresSkus failed2 store:%d failed with error:%v", storeMap.StoreID, err)
|
||||
}
|
||||
return nil, err
|
||||
}, loopMapInfo.StoreMapList)
|
||||
}
|
||||
t.AddChild(loopStoreTask).Run()
|
||||
_, err = loopStoreTask.GetResult(0)
|
||||
return nil, err
|
||||
} else {
|
||||
_, err = handler.FullSyncStoreSkus(ctx, t, loopMapInfo.StoreMapList[0].StoreID, false, isContinueWhenError)
|
||||
}
|
||||
_, err = handler.FullSyncStoreSkus(ctx, t, loopMapInfo.StoreMapList[0].StoreID, false, isContinueWhenError)
|
||||
err = jxutils.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}
|
||||
return nil, err
|
||||
})
|
||||
return nil, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}, isContinueWhenError)
|
||||
return hint, makeSyncError(err)
|
||||
}
|
||||
|
||||
func (v *VendorSync) DeleteRemoteStoreSkus(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
globals.SugarLogger.Debug("DeleteRemoteStoreSkus")
|
||||
return v.LoopStoresMap(ctx, db, fmt.Sprintf("删除远程门店商品信息:%v", storeIDs), isAsync, true, vendorIDs, storeIDs,
|
||||
hint, err = v.LoopStoresMap(ctx, db, fmt.Sprintf("删除远程门店商品信息:%v", storeIDs), isAsync, true, vendorIDs, storeIDs,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
|
||||
if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
|
||||
@@ -446,16 +508,16 @@ func (v *VendorSync) DeleteRemoteStoreSkus(ctx *jxcontext.Context, db *dao.DaoDB
|
||||
}, len(loopMapInfo.StoreMapList))
|
||||
t.AddChild(loopStoreTask).Run()
|
||||
_, err = loopStoreTask.GetResult(0)
|
||||
return nil, err
|
||||
} else {
|
||||
_, err = handler.DeleteRemoteStoreSkus(ctx, t, loopMapInfo.StoreMapList[0].StoreID, false, isContinueWhenError)
|
||||
}
|
||||
_, err = handler.DeleteRemoteStoreSkus(ctx, t, loopMapInfo.StoreMapList[0].StoreID, false, isContinueWhenError)
|
||||
err = jxutils.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}
|
||||
return nil, err
|
||||
})
|
||||
return nil, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID)
|
||||
}, isContinueWhenError)
|
||||
return hint, makeSyncError(err)
|
||||
}
|
||||
|
||||
func (v *VendorSync) LoopStoresMap(ctx *jxcontext.Context, db *dao.DaoDB, taskName string, isAsync, isManageIt bool, vendorIDs []int, storeIDs []int, handler tasksch.WorkFunc) (hint string, err error) {
|
||||
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) {
|
||||
sql := `
|
||||
SELECT t1.*
|
||||
FROM store_map t1
|
||||
@@ -475,11 +537,11 @@ func (v *VendorSync) LoopStoresMap(ctx *jxcontext.Context, db *dao.DaoDB, taskNa
|
||||
sql += " ORDER BY t1.store_id, t1.vendor_id"
|
||||
var storeMapList []*model.StoreMap
|
||||
if err = dao.GetRows(db, &storeMapList, sql, sqlParams...); err != nil {
|
||||
return "", err
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if len(storeMapList) == 0 {
|
||||
return "", nil
|
||||
return nil, "", nil
|
||||
}
|
||||
vendorStoreMap := make(map[int][]*model.StoreMap)
|
||||
for _, v := range storeMapList {
|
||||
@@ -497,21 +559,40 @@ func (v *VendorSync) LoopStoresMap(ctx *jxcontext.Context, db *dao.DaoDB, taskNa
|
||||
if len(loopInfoList) == 1 {
|
||||
taskName = fmt.Sprintf("%s,处理平台%s", taskName, model.VendorChineseNames[loopInfoList[0].VendorID])
|
||||
}
|
||||
task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, handler, loopInfoList)
|
||||
task = tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, handler, loopInfoList)
|
||||
tasksch.HandleTask(task, nil, isManageIt).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
resultList, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
if len(resultList) == 0 {
|
||||
hint = "1" // todo 暂时这样
|
||||
} else {
|
||||
hint = jxutils.TaskResult2Hint(resultList)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hint = task.GetID()
|
||||
}
|
||||
return task.ID, makeSyncError(err)
|
||||
return task, hint, err
|
||||
}
|
||||
|
||||
func (v *VendorSync) LoopStoresMap(ctx *jxcontext.Context, db *dao.DaoDB, taskName string, isAsync, isManageIt bool, vendorIDs []int, storeIDs []int, handler tasksch.WorkFunc, isContinueWhenError bool) (hint string, err error) {
|
||||
_, hint, err = v.LoopStoresMap2(ctx, db, taskName, isAsync, isManageIt, vendorIDs, storeIDs, handler, isContinueWhenError)
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func (v *VendorSync) LoopMultiStoresVendors(ctx *jxcontext.Context, db *dao.DaoDB, taskName string, isAsync bool, userName string, handler tasksch.WorkFunc) (hint string, err error) {
|
||||
task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, handler, v.MultiStoreVendorIDs)
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
result, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
hint = utils.Int2Str(len(result))
|
||||
}
|
||||
} else {
|
||||
hint = task.ID
|
||||
}
|
||||
return task.ID, makeSyncError(err)
|
||||
return hint, makeSyncError(err)
|
||||
}
|
||||
|
||||
func (v *VendorSync) RefreshAllSkusID(ctx *jxcontext.Context, isAsync bool, vendorIDs []int, storeIDs []int) (hint string, err error) {
|
||||
@@ -552,8 +633,10 @@ func (v *VendorSync) RefreshAllStoresID(ctx *jxcontext.Context, isAsync bool, ve
|
||||
|
||||
func makeSyncError(err error) (newErr error) {
|
||||
if err != nil {
|
||||
return &SyncError{
|
||||
Original: err,
|
||||
if _, ok := err.(*SyncError); !ok {
|
||||
return &SyncError{
|
||||
Original: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -61,7 +61,7 @@ func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader, ti
|
||||
globals.SugarLogger.Debugf("SendFilesToStores upload file:%s", fileHeader.Filename)
|
||||
if err == nil {
|
||||
ret := storage.PutRet{}
|
||||
key := "storeBill_" + utils.Int2Str(storeID) + "_" + strings.ToLower(utils.GetUUID()) + path.Ext(fileHeader.Filename)
|
||||
key := "storeBill/" + utils.Int2Str(storeID) + "_" + strings.ToLower(utils.GetUUID()) + path.Ext(fileHeader.Filename)
|
||||
formUploader := storage.NewFormUploader(cfg)
|
||||
for i := 0; i < 3; i++ {
|
||||
if err = formUploader.Put(context.Background(), &ret, upToken, key, file, fileHeader.Size, &storage.PutExtra{}); err == nil {
|
||||
@@ -73,7 +73,7 @@ func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader, ti
|
||||
db := dao.GetDB()
|
||||
billRec := &legacymodel.StoreBill{
|
||||
Date: time.Now(),
|
||||
Url: jxutils.ComposeQiniuResURL(strings.Replace(ret.Key, "http://", "https://", -1)),
|
||||
Url: strings.Replace(jxutils.ComposeQiniuResURL(ret.Key), "http://", "https://", -1),
|
||||
StoreId: storeID,
|
||||
BillName: fileHeader.Filename,
|
||||
ShopName: shopName,
|
||||
|
||||
@@ -57,86 +57,135 @@ func insertPlace(ctx *jxcontext.Context, db *dao.DaoDB, parent *autonavi.Distric
|
||||
}
|
||||
|
||||
func InitPlace(ctx *jxcontext.Context) (err error) {
|
||||
placeList, err2 := api.AutonaviAPI.GetDistricts(autonavi.DistrictLevelDistrict, "")
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
placeList = placeList[0].Districts
|
||||
db := dao.GetDB()
|
||||
if err = TruncateTable(db, "place"); err == nil {
|
||||
placeList, err2 := api.AutonaviAPI.GetDistricts(autonavi.DistrictLevelDistrict, "")
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
placeList = placeList[0].Districts
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil || err != nil {
|
||||
dao.Rollback(db)
|
||||
}()
|
||||
if err = insertPlace(ctx, db, nil, placeList); err != nil {
|
||||
return err
|
||||
}
|
||||
updateSqls := []string{
|
||||
`
|
||||
UPDATE place t1
|
||||
JOIN jde_city t2 ON t1.code = t2.col_tencentAddressCode
|
||||
SET t1.jd_code = t2.col_areaCode;
|
||||
`,
|
||||
`
|
||||
UPDATE place t1
|
||||
JOIN place t2 ON t1.parent_code = t2.code AND t2.jd_code != 0
|
||||
JOIN jde_district t3 ON t1.name = t3.col_areaName AND t2.jd_code = t3.col_cityCode
|
||||
SET t1.jd_code = t3.col_areaCode
|
||||
WHERE t1.level = 3;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN ebde_places t2 ON t1.name = t2.col_city_name
|
||||
SET t1.ebai_code = t2.col_city_id
|
||||
WHERE t1.level = 1 OR t1.level = 2;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN place t1p ON t1.parent_code = t1p.code
|
||||
JOIN ebde_places t2 ON t1.name = t2.col_city_name
|
||||
JOIN ebde_places t2p ON t2.col_parent_id = t2p.col_city_id AND t1p.ebai_code = t2p.col_city_id
|
||||
SET t1.ebai_code = t2.col_city_id
|
||||
WHERE t1.level = 3;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN mtpsdeliveryprice t2 ON t1.code = t2.citycode
|
||||
SET t1.mtps_price = t2.price;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN mtpsdeliveryprice t2 ON t1.name LIKE CONCAT(t2.cityname, '%')
|
||||
SET t1.mtps_price = t2.price
|
||||
WHERE t1.level = 2 AND t1.mtps_price = 0;
|
||||
`,
|
||||
`
|
||||
UPDATE place t1
|
||||
LEFT JOIN (
|
||||
SELECT DISTINCT city_code
|
||||
FROM store
|
||||
UNION DISTINCT
|
||||
SELECT DISTINCT place_code city_code
|
||||
FROM sku_name_place_bind
|
||||
) t2 ON t1.code = t2.city_code
|
||||
SET t1.enabled = 0
|
||||
WHERE t1.level = 2 AND t2.city_code IS NULL;
|
||||
`,
|
||||
}
|
||||
for _, v := range updateSqls {
|
||||
if _, err = dao.ExecuteSQL(db, v); err != nil {
|
||||
return err
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
dao.Commit(db)
|
||||
}()
|
||||
if _, err = dao.ExecuteSQL(db, `
|
||||
DELETE t1
|
||||
FROM place t1
|
||||
WHERE code < 9000000;
|
||||
`); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = insertPlace(ctx, db, nil, placeList); err != nil {
|
||||
return err
|
||||
}
|
||||
updateSqls := []string{
|
||||
`
|
||||
UPDATE place t1
|
||||
JOIN jde_city t2 ON t1.code = t2.col_tencentAddressCode
|
||||
SET t1.jd_code = t2.col_areaCode;
|
||||
`,
|
||||
`
|
||||
UPDATE place t1
|
||||
JOIN place t2 ON t1.parent_code = t2.code AND t2.jd_code != 0
|
||||
JOIN jde_district t3 ON t1.name = t3.col_areaName AND t2.jd_code = t3.col_cityCode
|
||||
SET t1.jd_code = t3.col_areaCode
|
||||
WHERE t1.level = 3;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN ebde_places t2 ON t1.name = t2.col_city_name
|
||||
SET t1.ebai_code = t2.col_city_id
|
||||
WHERE t1.level = 1 OR t1.level = 2;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN place t1p ON t1.parent_code = t1p.code
|
||||
JOIN ebde_places t2 ON t1.name = t2.col_city_name
|
||||
JOIN ebde_places t2p ON t2.col_parent_id = t2p.col_city_id AND t1p.ebai_code = t2p.col_city_id
|
||||
SET t1.ebai_code = t2.col_city_id
|
||||
WHERE t1.level = 3;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN mtpsdeliveryprice t2 ON t1.code = t2.citycode
|
||||
SET t1.mtps_price = t2.price;
|
||||
`,
|
||||
`
|
||||
UPDATE
|
||||
place t1
|
||||
JOIN mtpsdeliveryprice t2 ON t1.name LIKE CONCAT(t2.cityname, '%')
|
||||
SET t1.mtps_price = t2.price
|
||||
WHERE t1.level = 2 AND t1.mtps_price = 0;
|
||||
`,
|
||||
`
|
||||
UPDATE place t1
|
||||
LEFT JOIN (
|
||||
SELECT DISTINCT city_code
|
||||
FROM store
|
||||
UNION DISTINCT
|
||||
SELECT DISTINCT place_code city_code
|
||||
FROM sku_name_place_bind
|
||||
) t2 ON t1.code = t2.city_code
|
||||
SET t1.enabled = 0
|
||||
WHERE t1.level = 2 AND t2.city_code IS NULL;
|
||||
`,
|
||||
}
|
||||
for _, v := range updateSqls {
|
||||
if _, err = dao.ExecuteSQL(db, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dao.Commit(db)
|
||||
return err
|
||||
}
|
||||
|
||||
func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
func RefreshSkuNameImg(ctx *jxcontext.Context, parentTask tasksch.ITask, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
db := dao.GetDB()
|
||||
var skuNameList []*model.SkuName
|
||||
if err = dao.GetRows(db, &skuNameList, `
|
||||
SELECT t1.id, t1.img, MAX(t2.jd_id) jd_id
|
||||
FROM sku_name t1
|
||||
JOIN sku t2 ON t2.name_id = t1.id AND t2.deleted_at = ?
|
||||
WHERE t1.deleted_at = ?
|
||||
GROUP BY 1,2
|
||||
ORDER BY t1.id
|
||||
`, utils.DefaultTimeValue, utils.DefaultTimeValue); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
task := tasksch.NewParallelTask("RefreshSkuNameImg", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
skuName := batchItemList[0].(*model.SkuName)
|
||||
if !jxutils.IsEmptyID(skuName.JdID) {
|
||||
if skuName.Img == "" || isForce {
|
||||
var imgList []*jdapi.SkuPageImg
|
||||
if imgList, err = api.JdAPI.GetSkuPageImageInfo(skuName.JdID); err == nil {
|
||||
if len(imgList) > 0 {
|
||||
skuName.Img = imgList[0].Big
|
||||
_, err = dao.UpdateEntity(db, skuName, "Img")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}, skuNameList)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
} else {
|
||||
hint = task.ID
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func RefreshImgMd5(ctx *jxcontext.Context, parentTask tasksch.ITask, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
db := dao.GetDB()
|
||||
var skuNameList []*model.SkuName
|
||||
if err = dao.GetRows(db, &skuNameList, `
|
||||
@@ -169,7 +218,7 @@ func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError b
|
||||
}
|
||||
return nil, err
|
||||
}, skuNameList)
|
||||
tasksch.ManageTask(task).Run()
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
} else {
|
||||
@@ -178,6 +227,26 @@ func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError b
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
rootTask := tasksch.NewSeqTask("InitSkuName", ctx,
|
||||
func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
switch step {
|
||||
case 0:
|
||||
_, err = RefreshSkuNameImg(ctx, task, isForce, false, isContinueWhenError)
|
||||
case 1:
|
||||
_, err = RefreshImgMd5(ctx, task, isForce, false, isContinueWhenError)
|
||||
}
|
||||
return nil, err
|
||||
}, 2)
|
||||
tasksch.ManageTask(rootTask).Run()
|
||||
if !isAsync {
|
||||
_, err = rootTask.GetResult(0)
|
||||
} else {
|
||||
hint = rootTask.ID
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func InitVendorCategory(ctx *jxcontext.Context, vendorID int) (num int64, err error) {
|
||||
if handler := partner.GetPurchasePlatformFromVendorID(vendorID); handler != nil {
|
||||
cats, err2 := handler.GetVendorCategories(ctx)
|
||||
@@ -437,7 +506,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.MaxSkuNameLen)
|
||||
skuName := jxutils.ComposeSkuName(skuNameExt.Prefix, skuNameExt.Name, sku.Comment, skuNameExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount)
|
||||
fixedStatus := 1
|
||||
if sku.Status != model.SkuStatusNormal {
|
||||
fixedStatus = 2
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||||
@@ -47,11 +48,10 @@ func RefreshRealMobile(ctx *jxcontext.Context, vendorID int, fromTime, toTime ti
|
||||
sql := `
|
||||
SELECT *
|
||||
FROM goods_order
|
||||
WHERE vendor_id = ? AND consignee_mobile2 = '' AND order_created_at <= ?
|
||||
WHERE vendor_id = ? AND consignee_mobile2 = ''
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
vendorID,
|
||||
time.Now().Add(-4 * time.Hour), // 最近的刷新意义不大
|
||||
}
|
||||
if !utils.IsTimeZero(fromTime) {
|
||||
sql += " AND order_created_at >= ?"
|
||||
@@ -97,29 +97,6 @@ func StartGetCityStoreInfo() {
|
||||
}
|
||||
cityCenters = append(cityCenters, guiyang)
|
||||
GetCityStoreInfo(cityCenters)
|
||||
// countries, err := api.AutonaviAPI.GetDistricts(2, "")
|
||||
// if err == nil {
|
||||
// cityCenters := make([]*CityCenter, 0)
|
||||
// country := countries[0]
|
||||
// districts := country.Districts
|
||||
// for _, province := range districts { // 省
|
||||
// for _, city := range province.Districts { // 市
|
||||
// // globals.SugarLogger.Debug(utils.Format4Output(city.Name, false))
|
||||
// cityCenter := &CityCenter{
|
||||
// Lng: city.Lng,
|
||||
// Lat: city.Lat,
|
||||
// CityName: city.Name,
|
||||
// }
|
||||
// // globals.SugarLogger.Debug(utils.Format4Output(cityCenter, false))
|
||||
// cityCenters = append(cityCenters, cityCenter)
|
||||
// }
|
||||
// }
|
||||
// // globals.SugarLogger.Debug(utils.Format4Output(cityCenters, false))
|
||||
// GetCityStoreInfo(cityCenters)
|
||||
// }
|
||||
// utils.AfterFuncWithRecover(12*time.Hour, func() {
|
||||
// StartGetCityStoreInfo()
|
||||
// })
|
||||
}
|
||||
|
||||
func GetCityStoreInfo(cityCenters []*CityCenter) {
|
||||
@@ -233,63 +210,6 @@ func SaveEbaiStoreInfo(storeId, cityName string) {
|
||||
}
|
||||
}
|
||||
|
||||
// func GetCityStoreInfo(cityCenters []*CityCenter, i int) {
|
||||
// cityCenter := cityCenters[i]
|
||||
// cityPoints := GetCityPoints(cityCenter.lng, cityCenter.lat)
|
||||
// GetJdCityPointsStores(jxcontext.AdminCtx, cityPoints, true, true)
|
||||
// utils.AfterFuncWithRecover(10*time.Minute, func() {
|
||||
// GetEbaiCityPointsStores(jxcontext.AdminCtx, cityPoints, true, true)
|
||||
// utils.AfterFuncWithRecover(10*time.Minute, func() {
|
||||
// i++
|
||||
// if i < len(cityCenters) {
|
||||
// GetCityStoreInfo(cityCenters, i)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
// func GetJdCityPointsStores(ctx *jxcontext.Context, cityPoints [][]string, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
// if len(cityPoints) > 0 {
|
||||
// task := tasksch.NewParallelTask("misc GetJdCityPointsStores", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
// // globals.SugarLogger.Debug(batchItemList)
|
||||
// point := batchItemList[0].([]string)
|
||||
// err2 := jd.OnSaveStoreListInfo(point[0], point[1])
|
||||
// if err = err2; err != nil {
|
||||
// globals.SugarLogger.Infof("GetJdCityPointsStores point:%s,%s failed with error:%v", point[0], point[1], err)
|
||||
// }
|
||||
// return nil, err
|
||||
// }, cityPoints)
|
||||
// // globals.SugarLogger.Debug(utils.Format4Output(task, false))
|
||||
// tasksch.HandleTask(task, nil, true).Run()
|
||||
// hint = task.ID
|
||||
// if !isAsync {
|
||||
// _, err = task.GetResult(0)
|
||||
// }
|
||||
// }
|
||||
// return hint, err
|
||||
// }
|
||||
|
||||
// func GetEbaiCityPointsStores(ctx *jxcontext.Context, cityPoints [][]string, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
// if len(cityPoints) > 0 {
|
||||
// task := tasksch.NewParallelTask("misc GetEbaiCityPointsStores", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
// point := batchItemList[0].([]interface{})
|
||||
// err2 := ebai.OnSaveStoreListInfo(point[0].(string), point[1].(string))
|
||||
// if err = err2; err != nil {
|
||||
// globals.SugarLogger.Infof("GetEbaiCityPointsStores point:%s,%s failed with error:%v", point[0].(string), point[1].(string), err)
|
||||
// }
|
||||
// return nil, err
|
||||
// }, cityPoints)
|
||||
// tasksch.HandleTask(task, nil, true).Run()
|
||||
// hint = task.ID
|
||||
// if !isAsync {
|
||||
// _, err = task.GetResult(0)
|
||||
// }
|
||||
// }
|
||||
// return hint, err
|
||||
// }
|
||||
|
||||
func GetCityPoints(lng float64, lat float64, cityName string) (cityPoints [][]string) {
|
||||
oneDu := 111319.55
|
||||
for a := 0; a <= 80; a++ {
|
||||
@@ -309,3 +229,25 @@ func GetCityPoints(lng float64, lat float64, cityName string) (cityPoints [][]st
|
||||
}
|
||||
return cityPoints
|
||||
}
|
||||
func StartDailyWork() {
|
||||
if globals.ReallyCallPlatformAPI {
|
||||
now := time.Now()
|
||||
runTime := time.Date(now.Year(), now.Month(), now.Day(), 21, 0, 0, 0, time.Local) // 凌晨00:25点开始执行
|
||||
waitDuration := runTime.Sub(now)
|
||||
if waitDuration < 5*time.Second {
|
||||
waitDuration += 24 * time.Hour
|
||||
}
|
||||
globals.SugarLogger.Debugf("dailyWork waitDuration:%d minutes", waitDuration/time.Minute)
|
||||
utils.AfterFuncWithRecover(waitDuration, func() {
|
||||
doDailyWork()
|
||||
StartDailyWork()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func doDailyWork() {
|
||||
globals.SugarLogger.Debug("doDailyWork")
|
||||
cms.EnableHaveRestStores(jxcontext.AdminCtx, true, true)
|
||||
// cms.CurVendorSync.FullSyncStoresSkus(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDJD}, nil, true, true)
|
||||
cms.CurVendorSync.SyncStoresSkus(jxcontext.AdminCtx, dao.GetDB(), []int{model.VendorIDJD, model.VendorIDEBAI, model.VendorIDMTWM}, nil, nil, false, true, true)
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ type SkuPrice struct {
|
||||
Price int `json:"price"` // 分,这个不是单价,是这个sku的活动价
|
||||
LimitSkuCount int `json:"limitSkuCount"`
|
||||
IsLock int8 `json:"isLock"`
|
||||
|
||||
EarningPrice int `json:"earningPrice"` // 活动商品设置,结算给门店老板的钱
|
||||
}
|
||||
|
||||
type tPromotionItemInfo struct {
|
||||
@@ -131,7 +133,7 @@ var (
|
||||
type JdPromotionHandler interface {
|
||||
CreatePromotionInfos(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error)
|
||||
CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error)
|
||||
CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error)
|
||||
CreatePromotionSku(infoId int64, outInfoId string, skus []*jdapi.PromotionSku) (skusResult []*jdapi.PromotionSku, err error)
|
||||
ConfirmPromotion(infoId int64, outInfoId string) (err error)
|
||||
CancelPromotion(infoId int64, outInfoId string) (err error)
|
||||
}
|
||||
@@ -140,38 +142,38 @@ type JdDirectDownHandler struct {
|
||||
}
|
||||
|
||||
func (p *JdDirectDownHandler) CreatePromotionInfos(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
|
||||
return api.JdAPI.CreatePromotionInfosSingle(name, beginDate, endDate, outInfoId, advertising)
|
||||
return api.JdAPI.CreatePromotionInfosSingle(name, beginDate, endDate, outInfoId, advertising, "")
|
||||
}
|
||||
func (p *JdDirectDownHandler) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
|
||||
return api.JdAPI.CreatePromotionRules(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily)
|
||||
return api.JdAPI.CreatePromotionRulesSingle(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, "")
|
||||
}
|
||||
func (p *JdDirectDownHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
|
||||
return api.JdAPI.CreatePromotionSkuSingle(infoId, outInfoId, skus)
|
||||
func (p *JdDirectDownHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []*jdapi.PromotionSku) (skusResult []*jdapi.PromotionSku, err error) {
|
||||
return api.JdAPI.CreatePromotionSkuSingle(infoId, outInfoId, skus, "")
|
||||
}
|
||||
func (p *JdDirectDownHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
|
||||
return api.JdAPI.ConfirmPromotionSingle(infoId, outInfoId)
|
||||
return api.JdAPI.ConfirmPromotionSingle(infoId, outInfoId, "")
|
||||
}
|
||||
func (p *JdDirectDownHandler) CancelPromotion(infoId int64, outInfoId string) (err error) {
|
||||
return api.JdAPI.CancelPromotionSingle(infoId, outInfoId)
|
||||
return api.JdAPI.CancelPromotionSingle(infoId, outInfoId, "")
|
||||
}
|
||||
|
||||
type JdLimitedTimeHandler struct {
|
||||
}
|
||||
|
||||
func (p *JdLimitedTimeHandler) CreatePromotionInfos(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
|
||||
return api.JdAPI.CreatePromotionInfosLimitTime(name, beginDate, endDate, outInfoId, advertising)
|
||||
return api.JdAPI.CreatePromotionInfosLimitTime(name, beginDate, endDate, outInfoId, advertising, "")
|
||||
}
|
||||
func (p *JdLimitedTimeHandler) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
|
||||
return api.JdAPI.CreatePromotionRules(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily)
|
||||
return api.JdAPI.CreatePromotionRulesLimitTime(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, "")
|
||||
}
|
||||
func (p *JdLimitedTimeHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
|
||||
return api.JdAPI.CreatePromotionSkuLimitTime(infoId, outInfoId, skus)
|
||||
func (p *JdLimitedTimeHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []*jdapi.PromotionSku) (skusResult []*jdapi.PromotionSku, err error) {
|
||||
return api.JdAPI.CreatePromotionSkuLimitTime(infoId, outInfoId, skus, "")
|
||||
}
|
||||
func (p *JdLimitedTimeHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
|
||||
return api.JdAPI.ConfirmPromotionLimitTime(infoId, outInfoId)
|
||||
return api.JdAPI.ConfirmPromotionLimitTime(infoId, outInfoId, "")
|
||||
}
|
||||
func (p *JdLimitedTimeHandler) CancelPromotion(infoId int64, outInfoId string) (err error) {
|
||||
return api.JdAPI.CancelPromotionLimitTime(infoId, outInfoId)
|
||||
return api.JdAPI.CancelPromotionLimitTime(infoId, outInfoId, "")
|
||||
}
|
||||
|
||||
type JdNullHandler struct {
|
||||
@@ -183,7 +185,7 @@ func (p *JdNullHandler) CreatePromotionInfos(name string, beginDate, endDate tim
|
||||
func (p *JdNullHandler) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
|
||||
return nil
|
||||
}
|
||||
func (p *JdNullHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
|
||||
func (p *JdNullHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []*jdapi.PromotionSku) (skusResult []*jdapi.PromotionSku, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (p *JdNullHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
|
||||
@@ -230,7 +232,10 @@ func Init() {
|
||||
// scheduleRoutine(true)
|
||||
}
|
||||
|
||||
func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueWhenError bool, vendorPromotionID string, params *PromotionParams, mapData map[string]interface{}) (hint string, err error) {
|
||||
func CreateJdPromotion(ctx *jxcontext.Context, vendorID int, isIDJd bool, isAsync, isContinueWhenError bool, vendorPromotionID string, params *PromotionParams, mapData map[string]interface{}) (hint string, err error) {
|
||||
if vendorID != model.VendorIDJD && vendorID != model.VendorIDJX {
|
||||
return "", fmt.Errorf("当前只支持京西与京东活动")
|
||||
}
|
||||
if vendorPromotionID != "" && len(vendorPromotionID) != len("14863853") {
|
||||
return "", fmt.Errorf("%s看起来不像是一个有效的京东活动ID,请仔细检查一下", vendorPromotionID)
|
||||
}
|
||||
@@ -260,12 +265,12 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
userName := ctx.GetUserName()
|
||||
db := dao.GetDB()
|
||||
modifyPricesList := make(map[int][]*jdapi.SkuPriceInfo)
|
||||
promotionPrices := make([]map[string]interface{}, len(params.StoreIDs)*len(params.SkuPrices))
|
||||
promotionPrices := make([]*jdapi.PromotionSku, len(params.StoreIDs)*len(params.SkuPrices))
|
||||
var jxStoreIDs []int
|
||||
promotion := &model.Promotion{
|
||||
Name: params.Name,
|
||||
Advertising: params.Advertising,
|
||||
VendorID: model.VendorIDJD,
|
||||
VendorID: vendorID,
|
||||
Type: params.Type,
|
||||
Status: model.PromotionStatusLocalCreated,
|
||||
LimitDevice: int8(limitDevice),
|
||||
@@ -278,7 +283,7 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
Source: PromotionSourceOpenPlatform,
|
||||
}
|
||||
|
||||
if vendorPromotionID == "" {
|
||||
if vendorPromotionID == "" && vendorID == model.VendorIDJD {
|
||||
skuIDs := make([]int, len(params.SkuPrices))
|
||||
skuPriceMap := make(map[int64]*SkuPrice)
|
||||
for k, v := range params.SkuPrices {
|
||||
@@ -323,7 +328,7 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
if promotionSkuPrice.PriceType == PriceTypePercentage {
|
||||
promotionSkuPrice.Price = skuBind.Price * promotionSkuPrice.Price / 100
|
||||
}
|
||||
if promotionSkuPrice.Price >= skuBind.Price {
|
||||
if vendorID != model.VendorIDJX && promotionSkuPrice.Price >= skuBind.Price {
|
||||
errMsg += fmt.Sprintf("活动价大于等于原价,storeID:%d, skuID:%d\n", skuBind.StoreID, skuBind.SkuID)
|
||||
}
|
||||
if promotionSkuPrice.LimitSkuCount <= 0 {
|
||||
@@ -338,13 +343,11 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
})
|
||||
}
|
||||
}
|
||||
promotionPrices[index] = map[string]interface{}{
|
||||
jdapi.KeyStationNo: utils.Str2Int64(skuBind.VendorStoreID),
|
||||
jdapi.KeySkuId: skuBind.JdSkuID,
|
||||
// jdapi.KeyOutStationNo: utils.Int2Str(skuBind.StoreID),
|
||||
// jdapi.KeyOutSkuId: utils.Int2Str(skuBind.SkuID),
|
||||
jdapi.KeyPromotionPrice: promotionSkuPrice.Price,
|
||||
jdapi.KeyLimitSkuCount: promotionSkuPrice.LimitSkuCount,
|
||||
promotionPrices[index] = &jdapi.PromotionSku{
|
||||
StationNo: utils.Str2Int64(skuBind.VendorStoreID),
|
||||
SkuID: skuBind.JdSkuID,
|
||||
PromotionPrice: int64(promotionSkuPrice.Price),
|
||||
LimitSkuCount: promotionSkuPrice.LimitSkuCount,
|
||||
}
|
||||
index++
|
||||
}
|
||||
@@ -402,6 +405,7 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
Price: skuPrice.Price,
|
||||
LimitSkuCount: skuPrice.LimitSkuCount,
|
||||
IsLock: skuPrice.IsLock,
|
||||
EarningPrice: skuPrice.EarningPrice,
|
||||
}
|
||||
dao.WrapAddIDCULDEntity(promotionSku, ctx.GetUserName())
|
||||
if err = dao.CreateEntity(db, promotionSku); err != nil {
|
||||
@@ -409,7 +413,7 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
}
|
||||
}
|
||||
|
||||
if vendorPromotionID == "" {
|
||||
if vendorID != model.VendorIDJX && vendorPromotionID == "" {
|
||||
promotionHandler := getPromotionHander(params.Type)
|
||||
if promotionHandler == nil {
|
||||
return "", errors.New("非法的活动类型")
|
||||
@@ -436,7 +440,7 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
for k, v := range modifyPrices {
|
||||
modifyPrices2[k] = v.(*jdapi.SkuPriceInfo)
|
||||
}
|
||||
if globals.EnableStoreWrite {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if _, err = api.JdAPI.UpdateVendorStationPrice(utils.Int2Str(storeID), "", modifyPrices2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -451,9 +455,9 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
|
||||
} else if step == 2 {
|
||||
task2 := tasksch.NewParallelTask("CreateJdPromotion CreatePromotionSku", tasksch.NewParallelConfig().SetBatchSize(MaxPromotionSkuCount).SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) {
|
||||
skus := make([]map[string]interface{}, len(batchItemList))
|
||||
skus := make([]*jdapi.PromotionSku, len(batchItemList))
|
||||
for k, v := range batchItemList {
|
||||
skus[k] = v.(map[string]interface{})
|
||||
skus[k] = v.(*jdapi.PromotionSku)
|
||||
}
|
||||
_, err = promotionHandler.CreatePromotionSku(infoId, "", skus)
|
||||
return nil, err
|
||||
@@ -510,7 +514,8 @@ func GetJdPromotions(ctx *jxcontext.Context, keyword string, params map[string]i
|
||||
t1.end_at,
|
||||
t1.advertising,
|
||||
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"storeID":', t2.store_id, ', "name":"', REPLACE(REPLACE(t22.name, '\t', ''), '"', ''), '"}')), "]") store_str,
|
||||
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"skuID":', t3.sku_id, ', "priceType":', t3.price_type, ', "price":', t3.price, ', "limitSkuCount":', t3.limit_sku_count, ', "isLock":', t3.is_lock, '}')), "]") sku_price_str
|
||||
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"skuID":', t3.sku_id, ', "priceType":', t3.price_type, ', "price":', t3.price,
|
||||
', "limitSkuCount":', t3.limit_sku_count, ', "isLock":', t3.is_lock, ', "earningPrice":', t3.earning_price, '}')), "]") sku_price_str
|
||||
FROM promotion t1
|
||||
JOIN promotion_store t2 ON t1.id = t2.promotion_id
|
||||
JOIN store t22 ON t2.store_id = t22.id
|
||||
@@ -881,6 +886,34 @@ func LockPromotionSkus(ctx *jxcontext.Context, promotionID int, isLock int, skuI
|
||||
return num, err
|
||||
}
|
||||
|
||||
func UpdatePromotionSkusEarningPrice(ctx *jxcontext.Context, promotionID int, skuPriceList []*SkuPrice) (num int64, err error) {
|
||||
db := dao.GetDB()
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil || err != nil {
|
||||
dao.Rollback(db)
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
for _, v := range skuPriceList {
|
||||
var tmpNum int64
|
||||
if tmpNum, err = dao.UpdateEntityLogically(db, &model.PromotionSku{}, map[string]interface{}{
|
||||
"EarningPrice": v.EarningPrice,
|
||||
}, ctx.GetUserName(), map[string]interface{}{
|
||||
"PromotionID": promotionID,
|
||||
model.FieldSkuID: v.SkuID,
|
||||
model.FieldDeletedAt: utils.DefaultTimeValue,
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
num += tmpNum
|
||||
}
|
||||
dao.Commit(db)
|
||||
return num, err
|
||||
}
|
||||
|
||||
func OnStoreStockMsg(msg *jdapi.CallbackStoreStockMsg) (retVal *jdapi.CallbackResponse) {
|
||||
var err error
|
||||
// globals.SugarLogger.Debugf("OnStoreStockMsg IsJdStoreSkuLocked:%t", storeskulock.IsJdStoreSkuLocked(msg.StationNo, msg.SkuId))
|
||||
@@ -930,12 +963,12 @@ func createLocalPromotionFromRemote(promotionInfoId int64) (retVal *jdapi.Callba
|
||||
if err = dao.GetEntity(db, promotion, "VendorPromotionID"); dao.IsNoRowsError(err) {
|
||||
storeIDMap := make(map[int64]int)
|
||||
skuIDMap := make(map[int64]int)
|
||||
skuMap := make(map[int64]*jdapi.PromotionSkuResult)
|
||||
skuMap := make(map[int64]*jdapi.PromotionLspQuerySkuResult)
|
||||
// 注意,这样处理可能是有问题,我们假定的是门店信息与SKU信息的叉乘
|
||||
for _, v := range result.SkuResultList {
|
||||
storeIDMap[v.StationNo] = 1
|
||||
skuIDMap[v.SkuId] = 1
|
||||
skuMap[v.SkuId] = v
|
||||
skuIDMap[v.SkuID] = 1
|
||||
skuMap[v.SkuID] = v
|
||||
}
|
||||
jdStoreIDs := make([]string, len(storeIDMap))
|
||||
index := 0
|
||||
@@ -970,7 +1003,7 @@ func createLocalPromotionFromRemote(promotionInfoId int64) (retVal *jdapi.Callba
|
||||
jxStoreIDs[k] = v.StoreID
|
||||
}
|
||||
priceList := make([]*SkuPrice, len(skuList))
|
||||
var skuResult *jdapi.PromotionSkuResult
|
||||
var skuResult *jdapi.PromotionLspQuerySkuResult
|
||||
for k, v := range skuList {
|
||||
skuResult = skuMap[v.JdID]
|
||||
priceList[k] = &SkuPrice{
|
||||
@@ -985,11 +1018,11 @@ func createLocalPromotionFromRemote(promotionInfoId int64) (retVal *jdapi.Callba
|
||||
// globals.SugarLogger.Debugf("priceList:%s", utils.Format4Output(priceList, false))
|
||||
source := strings.Trim(result.Source, "来源")
|
||||
promotionParams := &PromotionParams{
|
||||
Name: source + "-" + utils.Int64ToStr(result.PromotionInfoId),
|
||||
Name: source + "-" + utils.Int64ToStr(result.PromotionInfoID),
|
||||
Advertising: "",
|
||||
Type: result.PromotionType,
|
||||
BeginAt: result.BeginTime,
|
||||
EndAt: result.EndTime,
|
||||
BeginAt: result.BeginTime.GoTime(),
|
||||
EndAt: result.EndTime.GoTime(),
|
||||
StoreIDs: jxStoreIDs,
|
||||
SkuPrices: priceList,
|
||||
}
|
||||
@@ -1002,7 +1035,7 @@ func createLocalPromotionFromRemote(promotionInfoId int64) (retVal *jdapi.Callba
|
||||
mapData[keyLimitDevice] = skuResult.LimitDevice
|
||||
mapData[keyLimitPin] = skuResult.LimitPin
|
||||
}
|
||||
_, err = CreateJdPromotion(jxcontext.AdminCtx, false, true, false, utils.Int64ToStr(promotionInfoId), promotionParams, mapData)
|
||||
_, err = CreateJdPromotion(jxcontext.AdminCtx, model.VendorIDJD, false, true, false, utils.Int64ToStr(promotionInfoId), promotionParams, mapData)
|
||||
if dao.IsDuplicateError(err) || err == ErrLimitDeviceIsInvalid {
|
||||
err = nil
|
||||
}
|
||||
@@ -1048,7 +1081,7 @@ func getPromotionHander(promotionType int) JdPromotionHandler {
|
||||
// panic(fmt.Sprintf("unknown promotion type:%d", promotionType))
|
||||
return nil
|
||||
}
|
||||
if !globals.EnableStoreWrite {
|
||||
if !globals.EnableJdStoreWrite {
|
||||
promotionHandler = &JdNullHandler{}
|
||||
}
|
||||
return promotionHandler
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/partner/delivery"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
@@ -102,7 +104,7 @@ func Convert2JDSPU(ctx *jxcontext.Context, count int, isAsync, isContinueWhenErr
|
||||
skuNew2 := *sku
|
||||
skuNew := &skuNew2
|
||||
dao.WrapAddIDCULEntity(skuNew, ctx.GetUserName())
|
||||
skuNew.JdID = 0 //jxutils.GenFakeID()
|
||||
skuNew.JdID = 0
|
||||
skuNew.LinkID = sku.ID
|
||||
skuNew.NameID = skuNameNew.ID
|
||||
skuNew.JdSyncStatus = model.SyncFlagNewMask
|
||||
@@ -277,7 +279,7 @@ func Change2JDSPU4Store(ctx *jxcontext.Context, storeIDs []int, step int, isAsyn
|
||||
if err = dao.GetRows(db, &skuIDs, sql, sqlParams...); err != nil {
|
||||
return "", err
|
||||
}
|
||||
hint, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, storeIDs, skuIDs, isAsync, isContinueWhenError)
|
||||
hint, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, storeIDs, skuIDs, false, isAsync, isContinueWhenError)
|
||||
return hint, err
|
||||
}
|
||||
|
||||
@@ -706,7 +708,7 @@ func TransformJdSpu2Sku(ctx *jxcontext.Context, skuNameIDs []int, count int, isA
|
||||
subTask := tasksch.NewParallelTask(fmt.Sprintf("TransformJdSpu2Sku:%d", step), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(subTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
skuName := batchItemList[0].(*model.SkuName)
|
||||
if !jxutils.IsFakeID(skuName.JdID) {
|
||||
if !jxutils.IsEmptyID(skuName.JdID) {
|
||||
sql = `
|
||||
SELECT *
|
||||
FROM sku
|
||||
@@ -727,8 +729,8 @@ func TransformJdSpu2Sku(ctx *jxcontext.Context, skuNameIDs []int, count int, isA
|
||||
locker.Lock()
|
||||
skuIDs = append(skuIDs, sku.ID)
|
||||
locker.Unlock()
|
||||
if !jxutils.IsFakeID(sku.JdID) {
|
||||
if globals.EnableStoreWrite {
|
||||
if !jxutils.IsEmptyID(sku.JdID) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if err = api.JdAPI.UpdateSkuBaseInfo(utils.Int2Str(skuName.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)); err != nil {
|
||||
if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 11004 {
|
||||
err = nil
|
||||
@@ -740,7 +742,7 @@ func TransformJdSpu2Sku(ctx *jxcontext.Context, skuNameIDs []int, count int, isA
|
||||
}
|
||||
}
|
||||
}
|
||||
if err == nil && globals.EnableStoreWrite {
|
||||
if err == nil && globals.EnableJdStoreWrite {
|
||||
if err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil {
|
||||
err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
|
||||
} else if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 11035 {
|
||||
@@ -777,7 +779,7 @@ func TransformJdSpu2Sku(ctx *jxcontext.Context, skuNameIDs []int, count int, isA
|
||||
rootTask.AddChild(subTask).Run()
|
||||
if _, err = subTask.GetResult(0); err == nil {
|
||||
if len(skuIDs) > 0 {
|
||||
if _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, -1, skuIDs, model.SyncFlagModifiedMask|model.SyncFlagPriceMask|model.SyncFlagSaleMask); err == nil {
|
||||
if _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, nil, skuIDs, model.SyncFlagStoreSkuModifiedMask); err == nil {
|
||||
// time.Sleep(20 * time.Second)
|
||||
// _, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, nil, skuIDs, false, isContinueWhenError)
|
||||
}
|
||||
@@ -960,3 +962,29 @@ func RetrieveEbaiShopLicence(ctx *jxcontext.Context, isAsync, isContinueWhenErro
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func RefreshMtpsWaybillFee(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
var waybillList []*model.Waybill
|
||||
db := dao.GetDB()
|
||||
if err = dao.GetRows(db, &waybillList, `
|
||||
SELECT *
|
||||
FROM waybill
|
||||
WHERE status_time > '2019-04-01' AND waybill_vendor_id = 102 AND desired_fee = 0
|
||||
`); err == nil {
|
||||
globals.SugarLogger.Debugf("RefreshMtpsWaybillFee, count:%d", len(waybillList))
|
||||
rootTask := tasksch.NewParallelTask("RefreshMtpsWaybillFee", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
bill := batchItemList[0].(*model.Waybill)
|
||||
bill.DesiredFee, _ = delivery.CalculateBillDeliveryFee(bill)
|
||||
_, err = dao.UpdateEntity(db, bill, "DesiredFee")
|
||||
return nil, err
|
||||
}, waybillList)
|
||||
tasksch.ManageTask(rootTask).Run()
|
||||
if !isAsync {
|
||||
_, err = rootTask.GetResult(0)
|
||||
} else {
|
||||
hint = rootTask.ID
|
||||
}
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user