- jd.FullSyncStoreSkus

- refactor mtwm.SyncLocalStoreCategory
This commit is contained in:
gazebo
2018-12-07 11:34:49 +08:00
parent 2210e1020b
commit bf5d9ed219
9 changed files with 213 additions and 70 deletions

View File

@@ -89,6 +89,9 @@ type IPurchasePlatformHandler interface {
SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error)
RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error)
// !!!注意,此操作会先清除门店已有的商品,一般用于初始化,小心使用
FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error)
GetVendorID() int
}
@@ -114,13 +117,8 @@ type IMultipleStoresHandler interface {
type ISingleStoreHandler interface {
IPurchasePlatformHandler
SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error)
ReadStoreCategories(storeID int) (cats []*model.SkuCategory, err error)
ReadStoreSku(storeID, skuID int) (skuNameExt *model.SkuNameExt, err error)
RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error)
// !!!注意,此操作会先清除门店已有的商品,一般用于初始化,小心使用
FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error)
}
type IDeliveryPlatformHandler interface {

View File

@@ -243,14 +243,6 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
return rootTask.ID, err
}
func (p *PurchaseHandler) ReadStoreCategories(storeID int) (cats []*model.SkuCategory, err error) {
return nil, err
}
func (p *PurchaseHandler) ReadStoreSku(storeID, skuID int) (skuNameExt *model.SkuNameExt, err error) {
return skuNameExt, err
}
func (p *PurchaseHandler) GetAllRemoteSkus(storeID int) (skus []map[string]interface{}, err error) {
page1, err := api.EbaiAPI.SkuList(utils.Int2Str(storeID), utils.Params2Map("pagesize", MaxPageSize))
if err == nil {

View File

@@ -3,19 +3,11 @@ package elm
import (
"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"
)
func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) {
return "", nil
}
func (p *PurchaseHandler) ReadStoreCategories(storeID int) (cats []*model.SkuCategory, err error) {
return nil, nil
}
func (p *PurchaseHandler) ReadStoreSku(storeID, skuID int) (skuNameExt *model.SkuNameExt, err error) {
return nil, nil
}
func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
return hint, err

View File

@@ -132,3 +132,111 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
}
return task.ID, err
}
func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) {
globals.SugarLogger.Debugf("jd FullSyncStoreSkus, storeID:%d", storeID)
db := dao.GetDB()
_, err = dao.SetStoreSkuSyncStatus(ctx, db, model.VendorIDJD, storeID, nil, model.SyncFlagModifiedMask|model.SyncFlagPriceMask|model.SyncFlagSaleMask)
if err != nil {
return "", err
}
skus, err := dao.GetFullStoreSkus(db, model.VendorIDJD, storeID)
if err != nil {
return "", err
}
return p.syncStoreSkus(ctx, parentTask, db, storeID, skus, isAsync, isContinueWhenError)
}
// todo 之后应该与SyncStoreSkus合并
func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, storeID int, skus []*dao.StoreSkuSyncInfo, isAsync, isContinueWhenError bool) (hint string, err error) {
globals.SugarLogger.Debugf("jd syncStoreSkus, storeID:%d, len(skus):%d", storeID, len(skus))
if len(skus) == 0 {
return "", nil
}
storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD)
if err != nil {
return "", err
}
stationNo := storeDetail.VendorStoreID
task := tasksch.NewParallelTask("SyncStoresSkus京东", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
var skuPriceInfoList []*jdapi.SkuPriceInfo
var skuVendibilityList []*jdapi.StockVendibility
var skuStockList []*jdapi.SkuStock
var batchSkuIDs []int
for _, v := range batchItemList {
storeSku := v.(*dao.StoreSkuSyncInfo)
alreadyAddStock := false
if storeSku.SkuSyncStatus&model.SyncFlagChangedMask != 0 || storeSku.BindID == 0 {
if storeSku.BindID != 0 {
batchSkuIDs = append(batchSkuIDs, storeSku.BindID)
}
if storeSku.SkuSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 || storeSku.BindID == 0 { // 关注或取消关注
stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.ID),
StockQty: model.MaxStoreSkuStockQty,
}
if storeSku.DeletedAt != utils.DefaultTimeValue || storeSku.BindID == 0 {
stock.StockQty = 0
} else {
alreadyAddStock = true
}
if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuStockList = append(skuStockList, stock)
}
}
if storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(storeSku.ID),
Price: jxutils.CaculateSkuVendorPrice(int(storeSku.Price), int(storeDetail.PricePercentage)),
})
}
if storeSku.SkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
vendibility := &jdapi.StockVendibility{
OutSkuId: utils.Int2Str(storeSku.ID),
DoSale: true,
}
if storeSku.Status != model.StoreSkuBindStatusNormal {
vendibility.DoSale = false
} else if !alreadyAddStock { // 如果是设置可售则自动将库存加满
stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.ID),
StockQty: model.MaxStoreSkuStockQty,
}
skuStockList = append(skuStockList, stock)
}
if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuVendibilityList = append(skuVendibilityList, vendibility)
}
}
}
}
// globals.SugarLogger.Debug(utils.Format4Output(skuVendibilityList, false), utils.Format4Output(skuPriceInfoList, false), utils.Format4Output(skuStockList, false))
if globals.EnableStoreWrite {
// todo 以下可以优化为并行操作
if len(skuVendibilityList) > 0 {
_, err = api.JdAPI.BatchUpdateVendibility("", stationNo, skuVendibilityList, ctx.GetUserName())
}
if err == nil && len(skuPriceInfoList) > 0 {
_, err = api.JdAPI.UpdateVendorStationPrice("", stationNo, skuPriceInfoList)
}
if err == nil && len(skuStockList) > 0 {
_, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, skuStockList, ctx.GetUserName())
}
}
if err == nil && len(batchSkuIDs) > 0 {
db := dao.GetDB() // 多线程问题
sql := `
UPDATE store_sku_bind t1
SET t1.jd_sync_status = 0
WHERE t1.id IN (` + dao.GenQuestionMarks(len(batchSkuIDs)) + ")"
_, err = dao.ExecuteSQL(db, sql, batchSkuIDs)
}
return nil, err
}, skus)
ctx.SetTaskOrAddChild(task, parentTask)
task.Run()
if !isAsync {
_, err = task.GetResult(0)
}
return task.ID, err
}

View File

@@ -86,10 +86,6 @@ func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask t
return hint, err
}
func (p *PurchaseHandler) ReadStoreCategories(storeID int) (cats []*model.SkuCategory, err error) {
return nil, nil
}
// 此函数根据门店商品信息重建分类信息
// 远程有,本地无, --> 删除远程
// 远程有,本地有,映射无, --> 添加关联
@@ -110,17 +106,10 @@ func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao
return "", err
}
for _, cat := range localCats {
catID := cat.VendorCatID
if catID == "" {
catID = cat.Name
}
parentCatID := cat.ParentVendorCatID
if parentCatID == "" {
parentCatID = cat.ParentCatName
}
catMap[i][parentCatID+"/"+catID] = cat
catMap[i][cat.ParentCatName+"/"+cat.Name] = cat
}
}
identityCatMap := make(map[int]int) // 这里面表示远程有,本地有,且完全相同,可擦掉本地的修改标记
if isCheckRemote {
strStoreID := utils.Int2Str(storeID)
remoteCats, err := api.MtwmAPI.RetailCatList(utils.Int2Str(storeID))
@@ -141,7 +130,7 @@ func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao
if localCat.MapID == 0 { // 本地映射没有
localCat.MapID = -1 // 表示远程有同名的
} else { // 本地映射有
localCat.MapID = -2 // 表示不处理
identityCatMap[localCat.MapID] = 1
}
}
return nil
@@ -174,13 +163,24 @@ func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao
if err = dao.CreateEntity(db, catMap); err != nil {
return "", err
}
} else if v.MapID != -2 {
} else if isCheckRemote {
catMap := &model.StoreSkuCategoryMap{
MtwmSyncStatus: model.SyncFlagNewMask,
}
updateFields := []string{
model.FieldUpdatedAt,
model.FieldLastOperator,
model.FieldMtwmSyncStatus,
}
if identityCatMap[v.MapID] == 1 { // 如果一样则要刷新ID对于MTWM其实就是名字
catMap.MtwmID = v.Name
catMap.MtwmSyncStatus = 0
updateFields = append(updateFields, model.FieldMtwmID)
}
catMap.ID = v.MapID
num++
if _, err = dao.UpdateEntity(db, catMap, "MtwmSyncStatus"); err != nil {
dao.WrapUpdateULEntity(catMap, ctx.GetUserName())
if _, err = dao.UpdateEntity(db, catMap, updateFields...); err != nil {
return "", err
}
}
@@ -201,10 +201,6 @@ func TranverseRemoteCatList(parentCatName string, remoteCats []*mtwmapi.RetailCa
return nil
}
func (p *PurchaseHandler) ReadStoreSku(storeID, skuID int) (skuNameExt *model.SkuNameExt, err error) {
return nil, nil
}
// hint如果是异步返回的是任务ID如果是同步返回是本次需要同步的目录数
func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
@@ -224,8 +220,14 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
if hint != "0" {
return "", errors.New("同步门店商品所需目录失败")
}
storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM)
if err != nil {
return "", err
}
skus, err := dao.GetStoreSkus(db, model.VendorIDMTWM, storeID, skuIDs)
if err != nil {
return "", err
}
// globals.SugarLogger.Debug(utils.Format4Output(skus, false))
strStoreID := utils.Int2Str(storeID)
rootTask := tasksch.NewParallelTask("美团外卖SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
@@ -241,7 +243,7 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(skuItem.ID)
foodData["name"] = jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30)
foodData["description"] = skuItem.Comment
foodData["price"] = jxutils.IntPrice2Standard(skuItem.Price)
foodData["price"] = jxutils.CaculateSkuVendorPrice(int(skuItem.Price), int(storeDetail.PricePercentage))
foodData["min_order_count"] = 1
foodData["unit"] = skuItem.Unit
foodData["box_num"] = 0
@@ -307,7 +309,7 @@ func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask t
case 3:
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
case 4:
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, true, isContinueWhenError)
// _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, true, isContinueWhenError)
}
return nil, err
}, 5)