Merge branch 'master' into get-store

This commit is contained in:
gazebo
2019-06-24 10:17:56 +08:00
127 changed files with 9409 additions and 2126 deletions

355
business/jxstore/act/act.go Normal file
View 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
}

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

View File

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

View File

@@ -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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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,

View File

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

View File

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

View File

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

View File

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