603 lines
23 KiB
Go
603 lines
23 KiB
Go
package ebai
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"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"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||
"git.rosy.net.cn/jx-callback/business/model"
|
||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
"git.rosy.net.cn/jx-callback/globals/api"
|
||
)
|
||
|
||
const (
|
||
MaxPageSize = 100
|
||
)
|
||
|
||
type tStoreSkuFullInfo struct {
|
||
model.StoreSkuBind
|
||
|
||
SpecQuality float32 `json:"specQuality"`
|
||
SpecUnit string `orm:"size(8)" json:"specUnit"` // 质量或容量
|
||
Weight int `json:"weight"` // 重量/质量,单位为克,当相应的SkuName的SpecUnit为g或kg时,必须等于SpecQuality
|
||
SkuStatus int
|
||
|
||
Prefix string `orm:"size(255)" json:"prefix"`
|
||
Name string `orm:"size(255);index" json:"name"`
|
||
Comment string `orm:"size(255)" json:"comment"`
|
||
IsGlobal int8 `orm:"default(1)" json:"isGlobal"` // 是否是全部(全国)可见,如果否的话,可见性由SkuPlace决定
|
||
Unit string `orm:"size(8)" json:"unit"`
|
||
Img string `orm:"size(255)" json:"img"`
|
||
PlaceStr string
|
||
Upc string
|
||
|
||
CatName string `orm:"size(255)"`
|
||
|
||
CatID int `orm:"column(cat_id)"`
|
||
CatEbaiID int64 `orm:"column(cat_ebai_id)"`
|
||
CatEbaiSyncStatus int
|
||
CatLevel int
|
||
|
||
ParentCatID int `orm:"column(parent_cat_id)"`
|
||
ParentCatEbaiID int64 `orm:"column(parent_cat_ebai_id)"`
|
||
|
||
EbaiCat1ID int64 `orm:"column(ebai_cat1_id)"`
|
||
EbaiCat2ID int64 `orm:"column(ebai_cat2_id)"`
|
||
EbaiCat3ID int64 `orm:"column(ebai_cat3_id)"`
|
||
|
||
PricePercentage int
|
||
}
|
||
|
||
type tStoreCatInfo struct {
|
||
model.StoreSkuCategoryMap
|
||
CatID int `orm:"column(cat_id)"`
|
||
Name string
|
||
ParentID int `orm:"column(parent_id)"`
|
||
Level int
|
||
Type int
|
||
Seq int
|
||
|
||
ParentEbaiID int64 `orm:"column(parent_ebai_id)"`
|
||
Children map[string]*tStoreCatInfo `orm:"-"`
|
||
}
|
||
|
||
var (
|
||
defCatMap = map[int]int64{
|
||
1: 151301831158987,
|
||
2: 15347484581335,
|
||
3: 15347484581339,
|
||
}
|
||
)
|
||
|
||
func (p *PurchaseHandler) getDirtyStoreSkus(db *dao.DaoDB, storeID int, skuIDs []int) (storeSkuInfoList []*tStoreSkuFullInfo, err error) {
|
||
sql := `
|
||
SELECT t8.price_percentage, t1.*, t2.spec_quality, t2.spec_unit, t2.weight, t2.status sku_status,
|
||
t3.prefix, t3.name, t2.comment, t3.is_global, t3.unit, IF(t3.img_ebai <> '', t3.img_ebai, t3.img) img, t3.upc,
|
||
t4.name cat_name,
|
||
t4.id cat_id, t4.level cat_level, t5.ebai_id cat_ebai_id,
|
||
t4p.id parent_cat_id, t5p.ebai_id parent_cat_ebai_id, t5p.ebai_sync_status parent_cat_ebai_sync_status,
|
||
cat1.vendor_category_id ebai_cat3_id, cat2.vendor_category_id ebai_cat2_id, cat2.parent_id ebai_cat1_id
|
||
FROM store_sku_bind t1
|
||
JOIN sku t2 ON t1.sku_id = t2.id/* AND t2.status = ?*/
|
||
JOIN sku_name t3 ON t2.name_id = t3.id
|
||
JOIN sku_category t4 ON t3.category_id = t4.id
|
||
LEFT JOIN sku_category t4p ON t4p.id = t4.parent_id
|
||
LEFT JOIN store_sku_category_map t5 ON t5.store_id = t1.store_id AND t5.category_id = t4.id AND t5.deleted_at = ?
|
||
LEFT JOIN store_sku_category_map t5p ON t5p.store_id = t1.store_id AND t5p.category_id = t4p.id AND t5p.deleted_at = ?
|
||
LEFT JOIN sku_vendor_category cat1 ON t4.ebai_category_id = cat1.vendor_category_id AND cat1.vendor_id = ?
|
||
LEFT JOIN sku_vendor_category cat2 ON cat1.parent_id = cat2.vendor_category_id AND cat1.vendor_id = ?
|
||
JOIN store_map t8 ON t8.store_id = t1.store_id AND t8.vendor_id = ? AND t8.deleted_at = ?
|
||
WHERE t1.store_id = ? AND (t1.ebai_sync_status <> 0)
|
||
`
|
||
sqlParams := []interface{}{
|
||
// model.SkuStatusNormal,
|
||
utils.DefaultTimeValue,
|
||
utils.DefaultTimeValue,
|
||
model.VendorIDEBAI,
|
||
model.VendorIDEBAI,
|
||
model.VendorIDEBAI,
|
||
utils.DefaultTimeValue,
|
||
storeID,
|
||
}
|
||
if len(skuIDs) > 0 {
|
||
sql += " AND t1.sku_id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")"
|
||
sqlParams = append(sqlParams, skuIDs)
|
||
}
|
||
sql += " ORDER BY t1.price"
|
||
err = dao.GetRows(db, &storeSkuInfoList, sql, sqlParams...)
|
||
return storeSkuInfoList, err
|
||
}
|
||
|
||
func (p *PurchaseHandler) createCatByStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, storeID int, storeSkuInfoList []*tStoreSkuFullInfo) (num int64, err error) {
|
||
catList2Add := make(map[int]int)
|
||
for _, storeSku := range storeSkuInfoList {
|
||
if storeSku.EbaiSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 {
|
||
if storeSku.ParentCatEbaiID == 0 && storeSku.ParentCatID != 0 {
|
||
catList2Add[storeSku.ParentCatID] = 1
|
||
}
|
||
if storeSku.CatEbaiID == 0 {
|
||
catList2Add[storeSku.CatID] = 1
|
||
}
|
||
}
|
||
}
|
||
num = int64(len(catList2Add))
|
||
if num > 0 {
|
||
for k := range catList2Add {
|
||
if err = dao.AddStoreCategoryMap(db, storeID, k, model.VendorIDEBAI, "", model.SyncFlagNewMask, ctx.GetUserName()); err != nil {
|
||
return 0, err
|
||
}
|
||
}
|
||
if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil {
|
||
return 0, err
|
||
}
|
||
}
|
||
return num, nil
|
||
}
|
||
|
||
func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||
userName := ctx.GetUserName()
|
||
globals.SugarLogger.Debugf("ebai FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName)
|
||
|
||
db := dao.GetDB()
|
||
rootTask := tasksch.NewSeqTask("FullSyncStoreSkus", ctx,
|
||
func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||
switch step {
|
||
case 0:
|
||
err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil)
|
||
// 强制忽略删除SKU错误
|
||
if isContinueWhenError {
|
||
err = nil
|
||
}
|
||
case 1:
|
||
_, err = p.setStoreSkuSyncStatus(ctx, db, storeID, nil, model.SyncFlagNewMask)
|
||
case 2:
|
||
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
|
||
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, storeID, nil, model.SyncFlagNewMask)
|
||
}
|
||
case 3:
|
||
err = p.SyncLocalStoreCategory(db, storeID, userName)
|
||
case 4:
|
||
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
|
||
case 5:
|
||
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError)
|
||
}
|
||
return nil, err
|
||
}, 6)
|
||
tasksch.AddChild(parentTask, rootTask).Run()
|
||
if !isAsync {
|
||
_, err = rootTask.GetResult(0)
|
||
}
|
||
return rootTask.ID, err
|
||
}
|
||
|
||
func (p *PurchaseHandler) DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||
userName := ctx.GetUserName()
|
||
globals.SugarLogger.Debugf("ebai DeleteRemoteStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName)
|
||
|
||
db := dao.GetDB()
|
||
var errDeleteSku error
|
||
rootTask := tasksch.NewSeqTask("DeleteRemoteStoreSkus", ctx,
|
||
func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||
switch step {
|
||
case 0:
|
||
err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil)
|
||
errDeleteSku = err
|
||
// 强制忽略删除SKU错误
|
||
if isContinueWhenError {
|
||
err = nil
|
||
}
|
||
case 1:
|
||
_, err = p.setStoreSkuSyncStatus(ctx, db, storeID, nil, model.SyncFlagNewMask)
|
||
case 2:
|
||
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
|
||
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, storeID, nil, model.SyncFlagNewMask)
|
||
}
|
||
}
|
||
return nil, err
|
||
}, 3)
|
||
tasksch.AddChild(parentTask, rootTask).Run()
|
||
if !isAsync {
|
||
_, err = rootTask.GetResult(0)
|
||
}
|
||
if err == nil {
|
||
err = errDeleteSku
|
||
}
|
||
return rootTask.ID, err
|
||
}
|
||
|
||
func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||
userName := ctx.GetUserName()
|
||
globals.SugarLogger.Debugf("ebai SyncStoreSkus storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName)
|
||
|
||
var storeSkuInfoList []*tStoreSkuFullInfo
|
||
var num int64
|
||
strStoreID := utils.Int2Str(storeID)
|
||
rootTask := tasksch.NewSeqTask("SyncStoreSkus饿百1", ctx,
|
||
func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||
if step == 0 {
|
||
db := dao.GetDB()
|
||
for i := 0; i < 3; i++ {
|
||
if storeSkuInfoList, err = p.getDirtyStoreSkus(db, storeID, skuIDs); err != nil {
|
||
return nil, err
|
||
}
|
||
if num, err = p.createCatByStoreSkus(ctx, rootTask, db, storeID, storeSkuInfoList); err != nil {
|
||
return nil, err
|
||
}
|
||
if num == 0 {
|
||
break
|
||
}
|
||
}
|
||
if num != 0 {
|
||
globals.SugarLogger.Infof("SyncStoreSkus 不能创建商品所需的类别, storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName)
|
||
return nil, errors.New("不能创建商品所需的类别")
|
||
}
|
||
} else if step == 1 {
|
||
task := tasksch.NewParallelTask("SyncStoreSkus饿百2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
storeSku := batchItemList[0].(*tStoreSkuFullInfo)
|
||
updateFields := []string{model.FieldEbaiSyncStatus}
|
||
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
|
||
if storeSku.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 {
|
||
if storeSku.EbaiSyncStatus&model.SyncFlagNewMask == 0 {
|
||
err = api.EbaiAPI.SkuDelete(strStoreID, utils.Int64ToStr(storeSku.EbaiID))
|
||
}
|
||
} else if storeSku.EbaiSyncStatus&model.SyncFlagNewMask != 0 {
|
||
// globals.SugarLogger.Debug(utils.Format4Output(genSkuParamsFromStoreSkuInfo(storeSku), false))
|
||
// todo 适当处理重复(即已经创建)的情况
|
||
if storeSku.EbaiID, err = api.EbaiAPI.SkuCreate(strStoreID, storeSku.SkuID, genSkuParamsFromStoreSkuInfo(storeSku)); err == nil {
|
||
updateFields = append(updateFields, model.FieldEbaiID)
|
||
}
|
||
} else if storeSku.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 {
|
||
if jxutils.IsFakeID(storeSku.EbaiID) {
|
||
err = fmt.Errorf("京西数据异常,修改一个没有创建的饿百商品:%d, store:%s", storeSku.SkuID, strStoreID)
|
||
} else {
|
||
if _, err = api.EbaiAPI.SkuUpdate(strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(storeSku)); err == nil {
|
||
// err = api.EbaiAPI.SkuShopCategoryMap(strStoreID, storeSku.EbaiID, utils.Int64ToStr(storeSku.CatEbaiID))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if err == nil {
|
||
storeSku.EbaiSyncStatus = 0
|
||
_, err = dao.UpdateEntity(nil, &storeSku.StoreSkuBind, updateFields...)
|
||
}
|
||
return nil, err
|
||
}, storeSkuInfoList)
|
||
tasksch.AddChild(rootTask, task).Run()
|
||
_, err = task.GetResult(0)
|
||
}
|
||
return nil, err
|
||
}, 2)
|
||
tasksch.AddChild(parentTask, rootTask).Run()
|
||
if !isAsync {
|
||
_, err = rootTask.GetResult(0)
|
||
}
|
||
return rootTask.ID, err
|
||
}
|
||
|
||
func (p *PurchaseHandler) GetAllRemoteSkus(ctx *jxcontext.Context, storeID int, parentTask tasksch.ITask) (skus []map[string]interface{}, err error) {
|
||
globals.SugarLogger.Debugf("ebai GetAllRemoteSkus storeID:%d, userName:%s", storeID, ctx.GetUserName())
|
||
page1, err := api.EbaiAPI.SkuList(utils.Int2Str(storeID), utils.Params2Map("pagesize", MaxPageSize))
|
||
if err == nil {
|
||
skus = append(skus, page1.List...)
|
||
if page1.Pages > 1 {
|
||
pages := make([]int, page1.Pages-1)
|
||
for i := 2; i <= page1.Pages; i++ {
|
||
pages[i-2] = i
|
||
}
|
||
task := tasksch.NewParallelTask("GetAllRemoteSkus", nil, ctx,
|
||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
callParams := map[string]interface{}{
|
||
"pagesize": MaxPageSize,
|
||
"page": batchItemList[0],
|
||
}
|
||
pageSku, err2 := api.EbaiAPI.SkuList(utils.Int2Str(storeID), callParams)
|
||
if err2 == nil {
|
||
return pageSku.List, err2
|
||
}
|
||
globals.SugarLogger.Debug(utils.Format4Output(callParams, false))
|
||
return nil, err2
|
||
}, pages)
|
||
tasksch.HandleTask(task, parentTask, false).Run()
|
||
result, err2 := task.GetResult(0)
|
||
if err = err2; err == nil {
|
||
for _, v := range result {
|
||
skus = append(skus, v.(map[string]interface{}))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return skus, err
|
||
}
|
||
|
||
func (p *PurchaseHandler) DeleteRemoteSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorSkuIDs []string) (err error) {
|
||
globals.SugarLogger.Debugf("ebai DeleteRemoteSkus storeID:%d, userName:%s", storeID, ctx.GetUserName())
|
||
|
||
if vendorSkuIDs == nil {
|
||
result, err2 := p.GetAllRemoteSkus(ctx, storeID, parentTask)
|
||
if err = err2; err == nil {
|
||
vendorSkuIDs = make([]string, len(result))
|
||
for k, v := range result {
|
||
vendorSkuIDs[k] = utils.Interface2String(v[ebaiapi.KeySkuID])
|
||
}
|
||
}
|
||
}
|
||
task := tasksch.NewParallelTask("DeleteRemoteSkus", tasksch.NewParallelConfig().SetBatchSize(100).SetIsContinueWhenError(true), ctx,
|
||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
strList := make([]string, len(batchItemList))
|
||
for k, v := range batchItemList {
|
||
strList[k] = v.(string)
|
||
}
|
||
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
|
||
err = api.EbaiAPI.SkuDelete(utils.Int2Str(storeID), strings.Join(strList, ","))
|
||
}
|
||
return nil, err
|
||
}, vendorSkuIDs)
|
||
tasksch.AddChild(parentTask, task).Run()
|
||
_, err = task.GetResult(0)
|
||
return err
|
||
}
|
||
|
||
func (p *PurchaseHandler) DeleteRemoteCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorCatIDs []int64) (err error) {
|
||
globals.SugarLogger.Debugf("ebai DeleteRemoteCategories storeID:%d, userName:%s", storeID, ctx.GetUserName())
|
||
|
||
strStoreID := utils.Int2Str(storeID)
|
||
if vendorCatIDs == nil {
|
||
result, err2 := api.EbaiAPI.ShopCategoryGet(strStoreID)
|
||
if err = err2; err == nil {
|
||
vendorCatIDs = make([]int64, len(result))
|
||
for k, v := range result {
|
||
vendorCatIDs[k] = v.CategoryID
|
||
}
|
||
}
|
||
}
|
||
task := tasksch.NewParallelTask("DeleteRemoteCategories", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
|
||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
|
||
err = api.EbaiAPI.ShopCategoryDelete(strStoreID, batchItemList[0].(int64))
|
||
}
|
||
return nil, err
|
||
}, vendorCatIDs)
|
||
tasksch.AddChild(parentTask, task).Run()
|
||
_, err = task.GetResult(0)
|
||
return err
|
||
}
|
||
|
||
func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) {
|
||
return hint, err
|
||
}
|
||
|
||
///////////
|
||
func genSkuParamsFromStoreSkuInfo(storeSku *tStoreSkuFullInfo) (params map[string]interface{}) {
|
||
price := jxutils.CaculateSkuVendorPrice(storeSku.Price, storeSku.PricePercentage)
|
||
params = map[string]interface{}{
|
||
"name": jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0),
|
||
"status": jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status)),
|
||
"left_num": model.MaxStoreSkuStockQty,
|
||
"sale_price": price,
|
||
"market_price": price,
|
||
"category_id": storeSku.CatEbaiID,
|
||
"cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1),
|
||
"cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2),
|
||
"cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3),
|
||
"weight": storeSku.Weight,
|
||
"photos": []map[string]interface{}{
|
||
map[string]interface{}{
|
||
"is_master": true,
|
||
"url": storeSku.Img,
|
||
},
|
||
},
|
||
}
|
||
// todo 饿百如果给的UPC是空要报错,但如果我要删除UPC怎么弄?
|
||
if storeSku.Upc != "" {
|
||
params["upc"] = storeSku.Upc
|
||
}
|
||
return params
|
||
}
|
||
|
||
func jxSkuStatus2Ebai(status int) int {
|
||
if status <= 0 {
|
||
return ebaiapi.SkuStatusOffline
|
||
}
|
||
return ebaiapi.SkuStatusOnline
|
||
}
|
||
|
||
func getEbaiCat(catID int64, level int) int64 {
|
||
if catID == 0 {
|
||
return defCatMap[level]
|
||
}
|
||
return catID
|
||
}
|
||
|
||
// 从饿百同步分类信息到本地
|
||
// 些函数执行后:
|
||
// 远程有与本地有的条目会关联(并置标记,下次同步会刷新远程)
|
||
// 远程没有本地有的条目会标记新增
|
||
// 远程有本地没有的条目不做处理
|
||
func (p *PurchaseHandler) SyncLocalStoreCategory(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||
globals.SugarLogger.Debugf("ebai SyncLocalStoreCategory storeID:%d, userName:%s", storeID, userName)
|
||
|
||
sql := `
|
||
SELECT t2.*, t1.id cat_id, t1.name, t1.parent_id, t1.level, t1.type, t1.seq
|
||
FROM sku_category t1
|
||
LEFT JOIN store_sku_category_map t2 ON t1.id = t2.category_id AND t2.store_id = ? AND (t2.deleted_at = ?)
|
||
WHERE t1.deleted_at = ?
|
||
ORDER BY t1.level
|
||
`
|
||
var catList []*tStoreCatInfo
|
||
if err = dao.GetRows(db, &catList, sql, storeID, utils.DefaultTimeValue, utils.DefaultTimeValue); err == nil {
|
||
cat1Map := map[string]*tStoreCatInfo{}
|
||
for _, v := range catList {
|
||
v.Name = formatName(v.Name)
|
||
if v.Level == 1 {
|
||
cat1 := cat1Map[v.Name]
|
||
if cat1 == nil {
|
||
cat1Map[v.Name] = v
|
||
cat1Map[utils.Int2Str(v.CatID)] = v
|
||
v.Children = make(map[string]*tStoreCatInfo)
|
||
}
|
||
} else {
|
||
cat1 := cat1Map[utils.Int2Str(v.ParentID)]
|
||
if cat1 == nil {
|
||
panic(fmt.Sprintf("can not find category, id:%d", v.ParentID))
|
||
}
|
||
cat1.Children[v.Name] = v
|
||
}
|
||
v.EbaiSyncStatus |= model.SyncFlagNewMask
|
||
}
|
||
result, err2 := api.EbaiAPI.ShopCategoryGet(utils.Int2Str(storeID))
|
||
if err = err2; err == nil {
|
||
dao.Begin(db)
|
||
defer func() {
|
||
dao.Rollback(db)
|
||
}()
|
||
// globals.SugarLogger.Debug(utils.Format4Output(cat1Map, false))
|
||
if err = p.processLocalCatByRemote(db, storeID, cat1Map, result, userName); err == nil {
|
||
err = p.updateLocalCatAsNew(db, cat1Map, userName)
|
||
}
|
||
if err == nil {
|
||
dao.Commit(db)
|
||
}
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 从本地同步分类信息到饿百
|
||
// 测试过程中出现过,父分类创建成功后马上创建子分类会报没有父分类错
|
||
func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) {
|
||
userName := ctx.GetUserName()
|
||
globals.SugarLogger.Debugf("ebai SyncStoreCategory storeID:%d, userName:%s", storeID, userName)
|
||
|
||
db := dao.GetDB()
|
||
rootTask := tasksch.NewSeqTask("ebai SyncStoreCategory", ctx,
|
||
func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||
level := step + 1
|
||
sql := `
|
||
SELECT t2.*, t1.name, t1.parent_id, t1.level, t1.type, t1.seq, t2p.ebai_id parent_ebai_id
|
||
FROM sku_category t1
|
||
LEFT JOIN sku_category t1p ON t1.parent_id = t1p.id
|
||
JOIN store_sku_category_map t2 ON t1.id = t2.category_id AND t2.store_id = ? AND t2.ebai_sync_status <> 0
|
||
LEFT JOIN store_sku_category_map t2p ON t1p.id = t2p.category_id AND t2p.store_id = ? AND t2p.deleted_at = ?
|
||
WHERE t1.level = ? AND t1.deleted_at = ?
|
||
`
|
||
var catList []*tStoreCatInfo
|
||
sqlParams := []interface{}{
|
||
storeID,
|
||
storeID,
|
||
utils.DefaultTimeValue,
|
||
level,
|
||
utils.DefaultTimeValue,
|
||
}
|
||
if err = dao.GetRows(db, &catList, sql, sqlParams...); err == nil {
|
||
strStoreID := utils.Int2Str(storeID)
|
||
task := tasksch.NewParallelTask("SyncStoreCategory", nil, ctx,
|
||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
updateFields := []string{model.FieldEbaiSyncStatus}
|
||
catInfo := batchItemList[0].(*tStoreCatInfo)
|
||
// globals.SugarLogger.Debug(utils.Format4Output(catInfo, false))
|
||
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
|
||
if catInfo.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除
|
||
if catInfo.EbaiSyncStatus&model.SyncFlagNewMask == 0 {
|
||
err = api.EbaiAPI.ShopCategoryDelete(strStoreID, catInfo.EbaiID)
|
||
}
|
||
} else if catInfo.EbaiSyncStatus&model.SyncFlagNewMask != 0 { // 新增
|
||
ebaiID, err2 := api.EbaiAPI.ShopCategoryCreate(strStoreID, catInfo.ParentEbaiID, formatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq))
|
||
if err = err2; err == nil {
|
||
catInfo.EbaiID = ebaiID
|
||
updateFields = append(updateFields, model.FieldEbaiID)
|
||
}
|
||
} else if catInfo.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改
|
||
err = api.EbaiAPI.ShopCategoryUpdate(strStoreID, catInfo.EbaiID, formatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq))
|
||
}
|
||
}
|
||
if err == nil {
|
||
db2 := dao.GetDB()
|
||
catInfo.EbaiSyncStatus = 0
|
||
_, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...)
|
||
}
|
||
return nil, err
|
||
}, catList)
|
||
rootTask.AddChild(task).Run()
|
||
_, err = task.GetResult(0)
|
||
}
|
||
return nil, err
|
||
}, 2)
|
||
tasksch.AddChild(parentTask, rootTask).Run()
|
||
if !isAsync {
|
||
_, err = rootTask.GetResult(0)
|
||
}
|
||
return rootTask.ID, err
|
||
}
|
||
|
||
func (p *PurchaseHandler) processLocalCatByRemote(db *dao.DaoDB, storeID int, localCatMap map[string]*tStoreCatInfo, remoteCatList []*ebaiapi.CategoryInfo, userName string) (err error) {
|
||
if localCatMap == nil || remoteCatList == nil {
|
||
return nil
|
||
}
|
||
for _, v := range remoteCatList {
|
||
jxCat := localCatMap[v.Name]
|
||
if jxCat == nil { // 远程有,本地没有,非法类别
|
||
// globals.SugarLogger.Debug(v.Name)
|
||
// globals.SugarLogger.Debug(utils.Format4Output(localCatMap, false))
|
||
} else {
|
||
if jxCat.EbaiID != v.CategoryID {
|
||
if jxCat.ID == 0 { // 远程有,本门店没有
|
||
globals.SugarLogger.Debug(jxCat.CatID)
|
||
err = dao.AddStoreCategoryMap(db, storeID, jxCat.CatID, model.VendorIDEBAI, utils.Int64ToStr(v.CategoryID), model.SyncFlagModifiedMask, userName)
|
||
} else { // 远程有,本门店有,但ID信息不一致
|
||
_, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, &jxCat.StoreSkuCategoryMap, map[string]interface{}{
|
||
model.FieldEbaiID: v.CategoryID,
|
||
}, userName, nil, model.FieldEbaiSyncStatus, model.SyncFlagModifiedMask)
|
||
}
|
||
} else { // 两边都有,且信息一致
|
||
}
|
||
jxCat.EbaiSyncStatus = 0
|
||
if err = p.processLocalCatByRemote(db, storeID, jxCat.Children, v.Children, userName); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (p *PurchaseHandler) updateLocalCatAsNew(db *dao.DaoDB, localCatMap map[string]*tStoreCatInfo, userName string) (err error) {
|
||
if localCatMap == nil {
|
||
return nil
|
||
}
|
||
for _, v := range localCatMap {
|
||
if v.EbaiSyncStatus&model.SyncFlagNewMask != 0 {
|
||
dao.WrapUpdateULEntity(&v.StoreSkuCategoryMap, userName)
|
||
if _, err = dao.UpdateEntity(db, &v.StoreSkuCategoryMap); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
if err = p.updateLocalCatAsNew(db, v.Children, userName); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (p *PurchaseHandler) setStoreSkuSyncStatus(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, skuIDs []int, syncStatus int) (num int64, err error) {
|
||
globals.SugarLogger.Debugf("ebai setStoreSkuSyncStatus storeID:%d, userName:%s", storeID, ctx.GetUserName())
|
||
return dao.SetStoreSkuSyncStatus(db, model.VendorIDEBAI, storeID, skuIDs, syncStatus)
|
||
}
|
||
|
||
func formatName(name string) string {
|
||
return utils.TrimBlankChar(utils.FilterMb4(name))
|
||
}
|
||
|
||
// 饿百的排序是从大到小
|
||
func jxCatSeq2Ebai(seq int) int {
|
||
return 10000 - seq
|
||
}
|