diff --git a/business/jxstore/cms/sync_store_sku.go b/business/jxstore/cms/sync_store_sku.go index e1e3afab8..36b6c1956 100644 --- a/business/jxstore/cms/sync_store_sku.go +++ b/business/jxstore/cms/sync_store_sku.go @@ -67,9 +67,19 @@ func SyncStorCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendor if model.IsSyncStatusDelete(catInfo.StoreCatSyncStatus) { // 删除 if model.IsSyncStatusDelete(catInfo.StoreCatSyncStatus) && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { err = handler.DeleteStoreCategory(ctx, storeID, vendorStoreID, catInfo.VendorCatID) + if err != nil && handler.IsErrCategoryNotExist(err) { + err = nil + } } } else if model.IsSyncStatusNew(catInfo.StoreCatSyncStatus) { // 新增 - if err = handler.CreateStoreCategory(ctx, storeID, vendorStoreID, catInfo); err == nil { + err = handler.CreateStoreCategory(ctx, storeID, vendorStoreID, catInfo) + if err != nil && handler.IsErrCategoryExist(err) { + if cat, err2 := handler.GetStoreCategory(ctx, storeID, vendorStoreID, catInfo.Name); err2 == nil { + catInfo.VendorCatID = cat.VendorCatID + err = nil + } + } + if err == nil { updateFields = append(updateFields, syncStatusFieldName) } } else if model.IsSyncStatusUpdate(catInfo.StoreCatSyncStatus) { // 修改 @@ -248,9 +258,9 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo storeSkuHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler) var ( - createList, updateList []*dao.StoreSkuSyncInfo - deleteList, stockList, statusList, priceList []*partner.StoreSkuInfo - updateItems []*dao.KVUpdateItem + createList, updateList []*dao.StoreSkuSyncInfo + deleteList, stockList, onlineList, offlineList, priceList []*partner.StoreSkuInfo + updateItems []*dao.KVUpdateItem ) skuMap := make(map[*partner.StoreSkuInfo]*dao.StoreSkuSyncInfo) @@ -291,7 +301,11 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo if bareSku == nil { bareSku = storeSkuSyncInfo2Bare(sku) } - statusList = append(statusList, bareSku) + if sku.MergedStatus == model.SkuStatusNormal { + onlineList = append(onlineList, bareSku) + } else { + offlineList = append(offlineList, bareSku) + } } } } @@ -319,8 +333,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 0: if len(deleteList) > 0 { _, err = putils.FreeBatchStoreSkuInfo(func(batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, err error) { - if err = singleStoreHandler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { - _, err = updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(batchedStoreSkuList), model.SyncFlagDeletedMask) + var successList []*partner.StoreSkuInfo + if successList, err = singleStoreHandler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + successList = batchedStoreSkuList + } + if len(successList) > 0 { + _, err = updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagDeletedMask) } return nil, err }, ctx, task, deleteList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus), isContinueWhenError) @@ -328,8 +346,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 1: if len(createList) > 0 { _, err = putils.FreeBatchStoreSkuSyncInfo(func(batchedStoreSkuList []*dao.StoreSkuSyncInfo) (result interface{}, err error) { - if err = singleStoreHandler.CreateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { - _, err = updateStoreSku(dao.GetDB(), vendorID, batchedStoreSkuList, model.SyncFlagNewMask) + var successList []*dao.StoreSkuSyncInfo + if successList, err = singleStoreHandler.CreateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + successList = batchedStoreSkuList + } + if len(successList) > 0 { + _, err = updateStoreSku(dao.GetDB(), vendorID, successList, model.SyncFlagNewMask) } return nil, err }, ctx, task, createList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncCreateStoreSkus), isContinueWhenError) @@ -337,8 +359,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 2: if len(updateList) > 0 { _, err = putils.FreeBatchStoreSkuSyncInfo(func(batchedStoreSkuList []*dao.StoreSkuSyncInfo) (result interface{}, err error) { - if err = singleStoreHandler.UpdateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { - _, err = updateStoreSku(dao.GetDB(), vendorID, batchedStoreSkuList, model.SyncFlagModifiedMask) + var successList []*dao.StoreSkuSyncInfo + if successList, err = singleStoreHandler.UpdateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + successList = batchedStoreSkuList + } + if len(successList) > 0 { + _, err = updateStoreSku(dao.GetDB(), vendorID, successList, model.SyncFlagModifiedMask) } return nil, err }, ctx, task, updateList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkus), isContinueWhenError) @@ -346,25 +372,43 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 3: if len(stockList) > 0 { _, err = putils.FreeBatchStoreSkuInfo(func(batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, err error) { - if err = storeSkuHandler.UpdateStoreSkusStock(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + var successList []*partner.StoreSkuInfo + if successList, err = storeSkuHandler.UpdateStoreSkusStock(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + successList = batchedStoreSkuList + } + if len(successList) > 0 { _, err = updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(batchedStoreSkuList), model.SyncFlagModifiedMask) // ? } return nil, err }, ctx, task, stockList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStock), isContinueWhenError) } - case 4: + case 4, 5: + statusList := onlineList + status := model.SkuStatusNormal + if step == 5 { + statusList = offlineList + status = model.SkuStatusDontSale + } if len(statusList) > 0 { _, err = putils.FreeBatchStoreSkuInfo(func(batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, err error) { - if err = storeSkuHandler.UpdateStoreSkusStatus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + var successList []*partner.StoreSkuInfo + if successList, err = storeSkuHandler.UpdateStoreSkusStatus(ctx, storeID, vendorStoreID, batchedStoreSkuList, status); err == nil { + successList = batchedStoreSkuList + } + if len(successList) > 0 { _, err = updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(batchedStoreSkuList), model.SyncFlagSaleMask) } return nil, err }, ctx, task, statusList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStatus), isContinueWhenError) } - case 5: + case 6: if len(priceList) > 0 { _, err = putils.FreeBatchStoreSkuInfo(func(batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, err error) { - if err = storeSkuHandler.UpdateStoreSkusPrice(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + var successList []*partner.StoreSkuInfo + if successList, err = storeSkuHandler.UpdateStoreSkusPrice(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { + successList = batchedStoreSkuList + } + if len(successList) > 0 { _, err = updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(batchedStoreSkuList), model.SyncFlagPriceMask) } return nil, err @@ -372,7 +416,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo } } return retVal, err - }, []int{0, 1, 2, 3, 4, 5}) + }, []int{0, 1, 2, 3, 4, 5, 6}) tasksch.HandleTask(task, parentTask, true).Run() _, err = task.GetResult(0) return err @@ -411,7 +455,7 @@ func PruneMissingStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, ven case 1: if len(sku2Delete) > 0 { _, err = putils.FreeBatchStoreSkuInfo(func(batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, err error) { - err = handler.DeleteStoreSkus(ctx, storeID, vendorStoreID, sku2Delete) + _, err = handler.DeleteStoreSkus(ctx, storeID, vendorStoreID, sku2Delete) return nil, err }, ctx, parentTask, sku2Delete, handler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus), isContinueWhenError) } diff --git a/business/partner/partner_store_sku.go b/business/partner/partner_store_sku.go index afafe23b3..7764c041d 100644 --- a/business/partner/partner_store_sku.go +++ b/business/partner/partner_store_sku.go @@ -102,24 +102,26 @@ type BareCategoryInfo struct { Children []*BareCategoryInfo `json:"children,omitempty"` } +// 批处理函数,如果是部分失败的情况会返回失败,successedList中会返回成功的列表 + type IPurchasePlatformStoreSkuHandler interface { GetStoreSkusBatchSize(funcID int) int ListOrders(ctx *jxcontext.Context, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) GetStoreSkusBareInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*StoreSkuInfo) (outStoreSkuList []*StoreSkuInfo, err error) - UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (err error) - UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (err error) - UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (err error) + UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (successList []*StoreSkuInfo, err error) + UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo, status int) (successList []*StoreSkuInfo, err error) + UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (successList []*StoreSkuInfo, err error) } type ISingleStoreStoreSkuHandler interface { IPurchasePlatformStoreSkuHandler GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (outSkuNameList []*SkuNameInfo, err error) - CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) - UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) - DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (err error) + CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) + UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) + DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (successList []*StoreSkuInfo, err error) DeleteStoreAllSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*BareCategoryInfo, err error) @@ -128,6 +130,9 @@ type ISingleStoreStoreSkuHandler interface { UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string) (err error) DeleteStoreAllCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) + + IsErrCategoryExist(err error) (isExist bool) + IsErrCategoryNotExist(err error) (isNotExist bool) } func BuildSkuName(skuID int, vendorSkuID string) (skuName *SkuNameInfo) { diff --git a/business/partner/purchase/ebai/store_sku2.go b/business/partner/purchase/ebai/store_sku2.go index 39c680a4c..8e97e7ce6 100644 --- a/business/partner/purchase/ebai/store_sku2.go +++ b/business/partner/purchase/ebai/store_sku2.go @@ -9,6 +9,7 @@ import ( "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/putils" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) @@ -50,6 +51,14 @@ func convertVendorCatList(remoteCats []*ebaiapi.CategoryInfo) (cats []*partner.B return cats } +func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) { + return ebaiapi.IsErrCategoryExist(err) +} + +func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { + return ebaiapi.IsErrCategoryNotExist(err) +} + func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { var vendorCatID int64 if globals.EnableEbaiStoreWrite { @@ -78,16 +87,16 @@ func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID in // 门店商品 // 多门店平台不需要实现这个接口 -func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { storeSku := storeSkuList[0] if globals.EnableEbaiStoreWrite { _, err = api.EbaiAPI.SkuUpdate(utils.Int2Str(storeID), utils.Str2Int64(storeSku.VendorSkuID), genSkuParamsFromStoreSkuInfo2(storeSku)) } - return err + return nil, err } // 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 -func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { storeSku := storeSkuList[0] var vendorSkuID int64 if globals.EnableEbaiStoreWrite { @@ -96,40 +105,45 @@ func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, v vendorSkuID = jxutils.GenFakeID() } storeSku.VendorSkuID = utils.Int64ToStr(vendorSkuID) - return err + return nil, err } -func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { if globals.EnableEbaiStoreWrite { - _, err = api.EbaiAPI.SkuDelete(utils.Int2Str(storeID), partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList(), nil) - } - return err -} - -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { - var validSkus, invalidSkus []int64 - for _, storeSku := range storeSkuList { - if storeSku.Status == model.SkuStatusNormal { - validSkus = append(validSkus, utils.Str2Int64(storeSku.VendorSkuID)) - } else { - invalidSkus = append(invalidSkus, utils.Str2Int64(storeSku.VendorSkuID)) - } - } - if globals.EnableEbaiStoreWrite { - if len(invalidSkus) > 1 { - _, err = api.EbaiAPI.SkuOffline(utils.Int2Str(storeID), invalidSkus, nil, nil) - } else if len(invalidSkus) == 1 { - err = api.EbaiAPI.SkuOfflineOne(utils.Int2Str(storeID), invalidSkus[0], "", "") - } - if err == nil { - if len(validSkus) > 1 { - _, err = api.EbaiAPI.SkuOnline(utils.Int2Str(storeID), validSkus, nil, nil) - } else if len(validSkus) == 1 { - err = api.EbaiAPI.SkuOnlineOne(utils.Int2Str(storeID), validSkus[0], "", "") + failedEbaiSkuIDs, err2 := api.EbaiAPI.SkuDelete(utils.Int2Str(storeID), partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList(), nil) + if err = err2; err == nil { + if err = putils.GenPartialFailedErr(failedEbaiSkuIDs, len(failedEbaiSkuIDs)); err != nil { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, utils.Int64Slice2String(failedEbaiSkuIDs)) } } } - return err + return successList, err +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { + vendorSkuIDs := partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList() + if globals.EnableEbaiStoreWrite { + var failedEbaiSkuIDs []int64 + if status == model.SkuStatusNormal { + if len(vendorSkuIDs) > 1 { + failedEbaiSkuIDs, err = api.EbaiAPI.SkuOnline(utils.Int2Str(storeID), vendorSkuIDs, nil, nil) + } else if len(vendorSkuIDs) == 1 { + err = api.EbaiAPI.SkuOnlineOne(utils.Int2Str(storeID), vendorSkuIDs[0], "", "") + } + } else { + if len(vendorSkuIDs) > 1 { + failedEbaiSkuIDs, err = api.EbaiAPI.SkuOffline(utils.Int2Str(storeID), vendorSkuIDs, nil, nil) + } else if len(vendorSkuIDs) == 1 { + err = api.EbaiAPI.SkuOfflineOne(utils.Int2Str(storeID), vendorSkuIDs[0], "", "") + } + } + if err == nil { + if err = putils.GenPartialFailedErr(failedEbaiSkuIDs, len(failedEbaiSkuIDs)); err != nil { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, utils.Int64Slice2String(failedEbaiSkuIDs)) + } + } + } + return successList, err } func StoreSkuInfoList2Ebai(storeSkuList []*partner.StoreSkuInfo) (outList ebaiapi.ShopSkuInfoList) { @@ -145,26 +159,45 @@ func StoreSkuInfoList2Ebai(storeSkuList []*partner.StoreSkuInfo) (outList ebaiap return outList } -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func getFailedVendorIDs(l []*ebaiapi.ShopSkuPriceUpdateResponseItem) (vendorSkuIDs []string) { + for _, v := range l { + if v.ErrorNo != 0 { + vendorSkuIDs = append(vendorSkuIDs, utils.Int64ToStr(v.SkuID)) + } + } + return vendorSkuIDs +} + +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { if globals.EnableEbaiStoreWrite { if len(storeSkuList) > 1 { - _, err = api.EbaiAPI.SkuPriceUpdateBatch(utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID) + updateResponse, err2 := api.EbaiAPI.SkuPriceUpdateBatch(utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID) + if err = err2; err != nil { + if len(updateResponse.FailedList) > 0 { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorIDs(updateResponse.FailedList)) + } + } } else if len(storeSkuList) == 1 { err = api.EbaiAPI.SkuPriceUpdateOne(utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0]) } } - return err + return successList, err } -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { if globals.EnableEbaiStoreWrite { if len(storeSkuList) > 1 { - _, err = api.EbaiAPI.SkuStockUpdateBatch(utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID) + failedEbaiSkuIDs, err2 := api.EbaiAPI.SkuStockUpdateBatch(utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID) + if err = err2; err == nil { + if err = putils.GenPartialFailedErr(failedEbaiSkuIDs, len(failedEbaiSkuIDs)); err != nil { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, utils.Int64Slice2String(failedEbaiSkuIDs)) + } + } } else if len(storeSkuList) == 1 { err = api.EbaiAPI.SkuStockUpdateOne(utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0]) } } - return err + return successList, err } func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo) (params map[string]interface{}) { @@ -232,7 +265,7 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas for i := 2; i <= page1.Pages; i++ { pages[i-2] = i } - task := tasksch.NewParallelTask("ebai GetStoreAllSkus", nil, ctx, + task := tasksch.NewParallelTask("ebai GetStoreSkusFullInfo", nil, ctx, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { callParams := &ebaiapi.SkuListParams{ PageSize: MaxPageSize, diff --git a/business/partner/purchase/jd/store_sku.go b/business/partner/purchase/jd/store_sku.go index 930260d0b..cb655fc50 100644 --- a/business/partner/purchase/jd/store_sku.go +++ b/business/partner/purchase/jd/store_sku.go @@ -174,13 +174,6 @@ func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasks return task.ID, err } -func isErrPartialFailed(err error) bool { - if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.Code() == jdapi.ResponseInnerCodePartialFailed { - return true - } - return false -} - func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { globals.SugarLogger.Debugf("jd SyncStoresSkus, storeID:%d, skuIDs:%v", storeID, skuIDs) db := dao.GetDB() diff --git a/business/partner/purchase/jd/store_sku2.go b/business/partner/purchase/jd/store_sku2.go index 254c321e9..b55556235 100644 --- a/business/partner/purchase/jd/store_sku2.go +++ b/business/partner/purchase/jd/store_sku2.go @@ -8,6 +8,7 @@ import ( "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/putils" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) @@ -76,21 +77,43 @@ func jxStoreSkuStatus2Jd(jxStoreSkuStatus int) (isSale bool) { return jxStoreSkuStatus == model.SkuStatusNormal } -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func isErrPartialFailed(err error) bool { + if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.Code() == jdapi.ResponseInnerCodePartialFailed { + return true + } + return false +} + +func getStrOutSkuIDs(l []*jdapi.StoreSkuBatchUpdateResponse, isSuccess bool) (outSkuIDs []string) { + for _, v := range l { + if isSuccess && v.Code == 0 { + outSkuIDs = append(outSkuIDs, v.OutSkuID) + } else if !isSuccess && v.Code != 0 { + outSkuIDs = append(outSkuIDs, v.OutSkuID) + } + } + return outSkuIDs +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { var skuVendibilityList []*jdapi.StockVendibility + jdStatus := jxStoreSkuStatus2Jd(status) for _, v := range storeSkuList { skuVendibilityList = append(skuVendibilityList, &jdapi.StockVendibility{ OutSkuId: utils.Int2Str(v.SkuID), - DoSale: jxStoreSkuStatus2Jd(v.Status), + DoSale: jdStatus, }) } if globals.EnableJdStoreWrite { - _, err = api.JdAPI.BatchUpdateVendibility("", vendorStoreID, skuVendibilityList, ctx.GetUserName()) + responseList, err2 := api.JdAPI.BatchUpdateVendibility("", vendorStoreID, skuVendibilityList, ctx.GetUserName()) + if err = err2; isErrPartialFailed(err) { + successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) + } } - return err + return successList, err } -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { if len(storeSkuList) == 1 { if globals.EnableJdStoreWrite { _, err = api.JdAPI.UpdateStationPrice(utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), vendorStoreID, int(storeSkuList[0].VendorPrice)) @@ -104,13 +127,16 @@ func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID i }) } if globals.EnableJdStoreWrite { - _, err = api.JdAPI.UpdateVendorStationPrice("", vendorStoreID, skuPriceInfoList) + responseList, err2 := api.JdAPI.UpdateVendorStationPrice("", vendorStoreID, skuPriceInfoList) + if err = err2; isErrPartialFailed(err) { + successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) + } } } - return err + return successList, err } -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { if len(storeSkuList) == 1 { if globals.EnableJdStoreWrite { err = api.JdAPI.UpdateCurrentQty(vendorStoreID, utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), storeSkuList[0].Stock) @@ -124,8 +150,11 @@ func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID i }) } if globals.EnableJdStoreWrite { - _, err = api.JdAPI.BatchUpdateCurrentQtys("", vendorStoreID, skuStockList, ctx.GetUserName()) + responseList, err2 := api.JdAPI.BatchUpdateCurrentQtys("", vendorStoreID, skuStockList, ctx.GetUserName()) + if err = err2; isErrPartialFailed(err) { + successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) + } } } - return err + return successList, err } diff --git a/business/partner/purchase/mtwm/store_sku2.go b/business/partner/purchase/mtwm/store_sku2.go index ca797a8c7..f1206e1c4 100644 --- a/business/partner/purchase/mtwm/store_sku2.go +++ b/business/partner/purchase/mtwm/store_sku2.go @@ -9,6 +9,7 @@ import ( "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/putils" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) @@ -58,6 +59,14 @@ func convertVendorCatList(remoteCats []*mtwmapi.RetailCategoryInfo) (cats []*par return cats } +func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) { + return mtwmapi.IsErrCategoryExist(err) +} + +func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { + return mtwmapi.IsErrCategoryNotExist(err) +} + func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { level := 1 if storeCat.ParentCatName != "" { @@ -106,12 +115,12 @@ func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID in // 门店商品 // 多门店平台不需要实现这个接口 -func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { return p.CreateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList) } // 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 -func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { foodDataList := make([]map[string]interface{}, len(storeSkuList)) for i, storeSku := range storeSkuList { foodData := make(map[string]interface{}) @@ -155,32 +164,40 @@ func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, v foodDataList[0]["skus"] = string(utils.MustMarshal(foodDataList[0]["skus"])) err = api.MtwmAPI.RetailInitData(vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) } else if len(foodDataList) > 0 { - _, err = api.MtwmAPI.RetailBatchInitData(vendorStoreID, foodDataList) + failedFoodList, err2 := api.MtwmAPI.RetailBatchInitData(vendorStoreID, foodDataList) + if err = err2; err == nil { + if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { + successList = putils.UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + } + } } } - if err == nil { - for _, storeSku := range storeSkuList { - storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) - } + for _, storeSku := range storeSkuList { + storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) } - return err + return successList, err } -func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +func getAppFoodCodeList(l []*mtwmapi.AppFoodResult) (vendorSkuIDs []string) { + return vendorSkuIDs +} + +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { if globals.EnableMtwmStoreWrite { if len(storeSkuList) == 1 { err = api.MtwmAPI.RetailDelete(vendorStoreID, storeSkuList[0].VendorSkuID) } else { + // todo 部分失败 err = api.MtwmAPI.RetailCatSkuBatchDelete(vendorStoreID, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) } if mtwmapi.IsErrSkuNotExist(err) { err = nil } } - return err + return nil, err } -func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (validSkus, invalidSkus []*mtwmapi.BareStoreFoodInfo) { +func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (skuList []*mtwmapi.BareStoreFoodInfo) { for _, storeSku := range storeSkuList { skuInfo := &mtwmapi.BareStoreFoodInfo{ AppFoodCode: storeSku.VendorSkuID, @@ -199,42 +216,49 @@ func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (validS } else if updateType == updateTypePrice { skuInfo.Skus[0].Price = jxutils.IntPrice2StandardString(storeSku.VendorPrice) } - if updateType != updateTypeStatus || storeSku.Status == model.SkuStatusNormal { - validSkus = append(validSkus, skuInfo) - } else { - invalidSkus = append(invalidSkus, skuInfo) - } + skuList = append(skuList, skuInfo) } - return validSkus, invalidSkus + return skuList } -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { - validSkus, invalidSkus := storeSku2Mtwm(storeSkuList, updateTypeStatus) +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { + skuList := storeSku2Mtwm(storeSkuList, updateTypeStatus) + mtwmStatus := skuStatusJX2Mtwm(status) if globals.EnableMtwmStoreWrite { - if len(invalidSkus) > 0 { - _, err = api.MtwmAPI.RetailSkuSellStatus(vendorStoreID, invalidSkus, mtwmapi.SellStatusOffline) - } - if err == nil && len(validSkus) > 0 { - _, err = api.MtwmAPI.RetailSkuSellStatus(vendorStoreID, validSkus, mtwmapi.SellStatusOnline) + failedFoodList, err2 := api.MtwmAPI.RetailSkuSellStatus(vendorStoreID, skuList, mtwmStatus) + if err = err2; err == nil { + if len(failedFoodList) > 0 { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + } } } - return err + return successList, err } -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { - priceList, _ := storeSku2Mtwm(storeSkuList, updateTypePrice) +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { + priceList := storeSku2Mtwm(storeSkuList, updateTypePrice) if globals.EnableMtwmStoreWrite { - _, err = api.MtwmAPI.RetailSkuPrice(vendorStoreID, priceList) + failedFoodList, err2 := api.MtwmAPI.RetailSkuPrice(vendorStoreID, priceList) + if err = err2; err == nil { + if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + } + } } - return err + return successList, err } -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { - stockList, _ := storeSku2Mtwm(storeSkuList, updateTypeStock) +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { + stockList := storeSku2Mtwm(storeSkuList, updateTypeStock) if globals.EnableMtwmStoreWrite { - _, err = api.MtwmAPI.RetailSkuStock(vendorStoreID, stockList) + failedFoodList, err2 := api.MtwmAPI.RetailSkuStock(vendorStoreID, stockList) + if err = err2; err == nil { + if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { + successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + } + } } - return err + return successList, err } func mtwmSkuStatus2Jx(mtwmSkuStatus int) (jxSkuStatus int) { @@ -254,12 +278,25 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas } skuNameList = append(skuNameList, vendorSku2Jx(skuInfo)) } else { + var storeSkuMap map[string]*partner.StoreSkuInfo + if storeSkuList != nil { + storeSkuMap = putils.StoreSkuList2MapByVendorSkuID(storeSkuList) + } for { + // todo 待优化获取速度 result, err := api.MtwmAPI.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit) if err != nil { return nil, err } - skuNameList = append(skuNameList, vendorSkuList2Jx(result)...) + if storeSkuMap == nil { + skuNameList = append(skuNameList, vendorSkuList2Jx(result)...) + } else { + for _, v := range result { + if storeSkuMap[v.AppFoodCode] != nil { + skuNameList = append(skuNameList, vendorSku2Jx(v)) + } + } + } if len(result) < mtwmapi.GeneralMaxLimit { break } diff --git a/business/partner/putils/store_sku.go b/business/partner/putils/store_sku.go index c0295946e..fec0a472d 100644 --- a/business/partner/putils/store_sku.go +++ b/business/partner/putils/store_sku.go @@ -28,7 +28,7 @@ func (p *DefSingleStorePlatform) DeleteStoreAllSkus(ctx *jxcontext.Context, pare } } _, err = FreeBatchStoreSkuInfo(func(batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, err error) { - err = p.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) + _, err = p.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) return nil, err }, ctx, parentTask, storeStoreList, p.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus), isContinueWhenError) return err @@ -184,3 +184,65 @@ func FreeBatchCategoryIDOp(handler func(vendorCatID string) (err error), ctx *jx } return err } + +func StoreSkuList2MapByVendorSkuID(storeSkuList []*partner.StoreSkuInfo) (storeSkuMap map[string]*partner.StoreSkuInfo) { + storeSkuMap = make(map[string]*partner.StoreSkuInfo) + for _, v := range storeSkuList { + storeSkuMap[v.VendorSkuID] = v + } + return storeSkuMap +} + +func StoreSkuList2MapBySkuID(storeSkuList []*partner.StoreSkuInfo) (storeSkuMap map[int]*partner.StoreSkuInfo) { + storeSkuMap = make(map[int]*partner.StoreSkuInfo) + for _, v := range storeSkuList { + storeSkuMap[v.SkuID] = v + } + return storeSkuMap +} + +func UnselectStoreSkuListByVendorSkuIDs(storeSkuList []*partner.StoreSkuInfo, vendorSkuIDs []string) (selectedStoreSkuList []*partner.StoreSkuInfo) { + if len(vendorSkuIDs) > 0 { + storeSkuMap := StoreSkuList2MapByVendorSkuID(storeSkuList) + for _, v := range vendorSkuIDs { + if storeSkuMap[v] != nil { + selectedStoreSkuList = append(selectedStoreSkuList, storeSkuMap[v]) + } + } + } + return selectedStoreSkuList +} + +func UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList []*dao.StoreSkuSyncInfo, vendorSkuIDs []string) (selectedStoreSkuList []*dao.StoreSkuSyncInfo) { + if len(vendorSkuIDs) > 0 { + storeSkuMap := make(map[string]*dao.StoreSkuSyncInfo) + for _, v := range storeSkuList { + storeSkuMap[v.VendorSkuID] = v + } + for _, v := range vendorSkuIDs { + if storeSkuMap[v] != nil { + selectedStoreSkuList = append(selectedStoreSkuList, storeSkuMap[v]) + } + } + } + return selectedStoreSkuList +} + +func UnselectStoreSkuListBySkuIDs(storeSkuList []*partner.StoreSkuInfo, skuIDs []int) (selectedStoreSkuList []*partner.StoreSkuInfo) { + if len(skuIDs) > 0 { + storeSkuMap := StoreSkuList2MapBySkuID(storeSkuList) + for _, v := range skuIDs { + if storeSkuMap[v] != nil { + selectedStoreSkuList = append(selectedStoreSkuList, storeSkuMap[v]) + } + } + } + return selectedStoreSkuList +} + +func GenPartialFailedErr(failedInfo interface{}, failedCount int) (err error) { + if failedCount > 0 { + err = fmt.Errorf("部分失败了%d个:%s", failedCount, utils.Format4Output(failedInfo, true)) + } + return err +}