diff --git a/business/jxstore/act/act.go b/business/jxstore/act/act.go index bc4595fc3..b5a4ca2b7 100644 --- a/business/jxstore/act/act.go +++ b/business/jxstore/act/act.go @@ -151,6 +151,8 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac storeIDMap := make(map[int]int) skuIDMap := make(map[int]int) storeSkuParamMap := make(map[int][]*ActStoreSkuParam) + + actStoreSkuMap := make(map[int64]bool) var wrongSkuList []*ActStoreSkuParam for _, v := range actStoreSku { if act.Type == model.ActSkuFake && v.EarningPrice == 0 { @@ -159,6 +161,8 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac storeIDMap[v.StoreID] = 1 skuIDMap[v.SkuID] = 1 storeSkuParamMap[v.StoreID] = append(storeSkuParamMap[v.StoreID], v) + + actStoreSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = true } } if len(wrongSkuList) > 0 { @@ -166,7 +170,7 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac } storeIDs := jxutils.IntMap2List(storeIDMap) skuIDs := jxutils.IntMap2List(skuIDMap) - // 判断活动是否重叠的检查,当前忽略京东平台及所有结算信息 + if act.OverlapRule == model.OverlapRuleNormal { effectActStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, act.Type, storeIDs, skuIDs, act.BeginAt, act.EndAt) if err != nil { @@ -174,7 +178,15 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac return nil, nil, nil, err } if len(effectActStoreSkuList) > 0 { - return nil, nil, nil, jsonerr.New(effectActStoreSkuList, model.ErrCodeJsonActSkuConflict) + var realEffectActStoreSkuList []*model.ActStoreSku2 + for _, v := range effectActStoreSkuList { + if actStoreSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] { + realEffectActStoreSkuList = append(realEffectActStoreSkuList, v) + } + } + if len(realEffectActStoreSkuList) > 0 { + return nil, nil, nil, jsonerr.New(realEffectActStoreSkuList, model.ErrCodeJsonActSkuConflict) + } } } diff --git a/business/jxstore/cms/store_sku_check.go b/business/jxstore/cms/store_sku_check.go index 1a3153812..6268288ef 100644 --- a/business/jxstore/cms/store_sku_check.go +++ b/business/jxstore/cms/store_sku_check.go @@ -548,6 +548,7 @@ func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, } else { filterStoreList := GetFilterStoreList(jxStoreInfoList.Stores, vendorMap, storeIDMap) diffData.InitData() + //循环门店store taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { jxStoreInfoListValue := batchItemList[0].(*StoreExt) storeID := jxStoreInfoListValue.ID @@ -556,22 +557,23 @@ func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, jxSkuInfoDataSingle := &dao.StoreSkuNamesInfo{} jxSkuInfoDataMulti := &dao.StoreSkuNamesInfo{} if jxStoreInfoListValue.StoreMaps != nil { + var multiFlag = false + var singleFlag = false var filterJxSkuInfoMapSingle map[int]*dao.StoreSkuNameExt var filterJxSkuInfoMapMulti map[int]*dao.StoreSkuNameExt for _, vendorListValue := range jxStoreInfoListValue.StoreMaps { vendorID := vendorListValue.VendorID - var flag = false if partner.IsMultiStore(vendorID) { - if flag == false { + if multiFlag == false { jxSkuInfoDataMulti, _ = GetStoreSkus(ctx, storeID, filterJxDepotUnSaleSkuIds, true, "", true, false, map[string]interface{}{}, 0, -1) filterJxSkuInfoMapMulti = GetFilterJxSkuInfoMap(jxSkuInfoDataMulti.SkuNames) //map[京西商品ID:StoreSkuNameExt] - flag = true + multiFlag = true } } else { - if flag == false { + if singleFlag == false { jxSkuInfoDataSingle, _ = GetStoreSkus(ctx, storeID, []int{}, true, "", true, false, map[string]interface{}{}, 0, -1) filterJxSkuInfoMapSingle = GetFilterJxSkuInfoMap(jxSkuInfoDataSingle.SkuNames) //map[京西商品ID:StoreSkuNameExt] - flag = true + singleFlag = true } } diff --git a/business/jxstore/cms/sync.go b/business/jxstore/cms/sync.go index 609d1b26e..bbd964ee1 100644 --- a/business/jxstore/cms/sync.go +++ b/business/jxstore/cms/sync.go @@ -3,9 +3,15 @@ package cms import ( "errors" "fmt" + "sync" + "time" + "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/platformapi/dingdingapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" + "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/tasksch" "git.rosy.net.cn/jx-callback/business/model" @@ -14,6 +20,23 @@ import ( "git.rosy.net.cn/jx-callback/globals" ) +type SyncErrResult struct { + SkuID int `json:"商品ID"` + CategoryName string `json:"分类名"` + StoreID int `json:"门店ID"` + VendorID int `json:"平台ID"` + VendorSkuID string `json:"平台商品ID"` + NameID int `json:"商品nameID"` + VendorPrice int64 `json:"平台价"` + SyncType string `json:"同步类型"` + ErrMsg string `json:"错误信息"` +} + +type SyncErrResultLock struct { + syncErrResult []SyncErrResult + locker sync.RWMutex +} + type LoopStoreMapInfo struct { VendorID int StoreMapList []*model.StoreMap @@ -44,6 +67,18 @@ var ( var ( ErrHaveNotImplementedYet = errors.New("还没有实现") ErrEntityNotExist = errors.New("找不到相应实体") + SyncErrResultTitle = []string{ + "商品ID", + "分类名", + "门店ID", + "平台ID", + "平台商品ID", + "商品nameID", + "平台价", + "同步类型", + "错误信息", + } + syncErrResultLock SyncErrResultLock ) // func (p *MultiStoreHandlerWrapper) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) { @@ -592,9 +627,28 @@ func (v *VendorSync) LoopStoresMap2(ctx *jxcontext.Context, db *dao.DaoDB, taskN taskName = fmt.Sprintf("%s,处理平台%s", taskName, model.VendorChineseNames[loopInfoList[0].VendorID]) } task = tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, handler, loopInfoList) + if isAsync { + task.SetFinishHook(func(task tasksch.ITask) { + var noticeMsg string + if len(task.GetFailedList()) > 10 { + downloadURL, _, _ := WirteToExcelBySyncFailed(task) + noticeMsg = fmt.Sprintf("[详情点我]path1=%s\n", downloadURL) + } else { + if err != nil { + noticeMsg = utils.Format4Output(buildErrMsgJson(task), true) + } + } + if authInfo, err := ctx.GetV2AuthInfo(); err == nil { + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, authInfo.UserID, "同步错误返回", noticeMsg) + } + }) + } tasksch.HandleTask(task, nil, isManageIt).Run() if !isAsync { resultList, err2 := task.GetResult(0) + if err2 != nil { + err2 = buildErrMsg(task) + } if err = err2; err == nil { if len(resultList) == 0 { hint = "1" // todo 暂时这样 @@ -608,6 +662,38 @@ func (v *VendorSync) LoopStoresMap2(ctx *jxcontext.Context, db *dao.DaoDB, taskN return task, hint, err } +func buildErrMsg(task tasksch.ITask) (err error) { + err = fmt.Errorf(utils.Format4Output(buildErrMsgJson(task), true)) + return makeSyncError(err) +} + +func buildErrMsgJson(task tasksch.ITask) (resultL []*SyncErrResult) { + failedList := task.GetFailedList() + for _, v := range failedList { + for _, vv := range v.([]*partner.StoreSkuInfoWithErr) { + result := &SyncErrResult{ + SkuID: 0, + StoreID: vv.StoreID, + CategoryName: vv.CategoryName, + VendorID: vv.VendoreID, + VendorSkuID: "", + NameID: 0, + VendorPrice: 0, + SyncType: vv.SyncType, + ErrMsg: vv.ErrMsg, + } + if vv.StoreSkuInfo != nil { + result.SkuID = vv.StoreSkuInfo.SkuID + result.VendorSkuID = vv.StoreSkuInfo.VendorSkuID + result.NameID = vv.StoreSkuInfo.NameID + result.VendorPrice = vv.StoreSkuInfo.VendorPrice + } + resultL = append(resultL, result) + } + } + return resultL +} + 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, false, handler, isContinueWhenError) return hint, err @@ -739,3 +825,36 @@ func GetTimeMixByInt(begin1, end1, begin2, end2 int16) (beginAt, endAt int16) { } return beginAt, endAt } + +func WirteToExcelBySyncFailed(task tasksch.ITask) (downloadURL, fileName string, err error) { + var ( + sheetList1 []*excel.Obj2ExcelSheetConfig + ) + syncErrResultLock.syncErrResult = syncErrResultLock.syncErrResult[0:0] + list := buildErrMsgJson(task) + for _, v := range list { + syncErrResultLock.AppendData(*v) + } + excelConf1 := &excel.Obj2ExcelSheetConfig{ + Title: "同步错误", + Data: syncErrResultLock.syncErrResult, + CaptionList: SyncErrResultTitle, + } + sheetList1 = append(sheetList1, excelConf1) + if excelConf1 != nil { + downloadURL, fileName, err = jxutils.UploadExeclAndPushMsg(sheetList1, time.Now().Format("200601021504")+"同步错误返回") + baseapi.SugarLogger.Debug("WriteToExcel: download is [%v]", downloadURL) + } else { + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!") + } + if err != nil { + baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName, err) + } + return downloadURL, fileName, err +} + +func (d *SyncErrResultLock) AppendData(syncErrResult SyncErrResult) { + d.locker.Lock() + defer d.locker.Unlock() + d.syncErrResult = append(d.syncErrResult, syncErrResult) +} diff --git a/business/jxstore/cms/sync_store_sku.go b/business/jxstore/cms/sync_store_sku.go index 1da235d7c..a92c5c45f 100644 --- a/business/jxstore/cms/sync_store_sku.go +++ b/business/jxstore/cms/sync_store_sku.go @@ -69,7 +69,7 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo rootTask := tasksch.NewSeqTask(fmt.Sprintf("%s SyncStoreCategory step1", model.VendorChineseNames[vendorID]), ctx, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { level := step + 1 - catList, err := dao.GetDirtyStoreCategories(db, vendorID, storeID, level) + catList, err := dao.GetDirtyStoreCategories(db, vendorID, storeID, level, skuIDs) if len(catList) > 0 { num += len(catList) task := tasksch.NewParallelTask(fmt.Sprintf("%s SyncStoreCategory step2, level=%d", model.VendorChineseNames[vendorID], level), @@ -80,11 +80,14 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo catInfo := batchItemList[0].(*dao.SkuStoreCatInfo) storeCatMap := &model.StoreSkuCategoryMap{} storeCatMap.ID = catInfo.MapID + var failedList []*partner.StoreSkuInfoWithErr if model.IsSyncStatusDelete(catInfo.CatSyncStatus) { // 删除 if model.IsSyncStatusDelete(catInfo.CatSyncStatus) && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { err = handler.DeleteStoreCategory(ctx, storeID, vendorStoreID, catInfo.VendorCatID, level) if err != nil && handler.IsErrCategoryNotExist(err) { err = nil + } else if err != nil && !handler.IsErrCategoryNotExist(err) { + failedList = putils.GetErrMsg2FailedSingleList(nil, err, storeID, vendorID, "删除分类") } } } else if model.IsSyncStatusNew(catInfo.CatSyncStatus) { // 新增 @@ -93,6 +96,8 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo if cat, err2 := handler.GetStoreCategory(ctx, storeID, vendorStoreID, catInfo.Name); err2 == nil { catInfo.VendorCatID = cat.VendorCatID err = nil + } else if err != nil && !handler.IsErrCategoryExist(err) { + failedList = putils.GetErrMsg2FailedSingleList(nil, err, storeID, vendorID, "新增分类") } } if err == nil { @@ -103,10 +108,19 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo } } } else if model.IsSyncStatusUpdate(catInfo.CatSyncStatus) { // 修改 - if err = handler.UpdateStoreCategory(ctx, storeID, vendorStoreID, catInfo); err == nil { + err = handler.UpdateStoreCategory(ctx, storeID, vendorStoreID, catInfo) + if err == nil { updateFields = append(updateFields, idFieldName) + } else { + failedList = putils.GetErrMsg2FailedSingleList(nil, err, storeID, vendorID, "修改分类") } } + if len(failedList) > 0 { + for _, v := range failedList { + v.CategoryName = catInfo.Name + } + task.AddFailedList(failedList) + } if err == nil { if vendorID == model.VendorIDMTWM { refutil.SetObjFieldByName(storeCatMap, idFieldName, catInfo.VendorCatID) @@ -318,7 +332,6 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo return err } vendorStoreID := storeDetail.VendorStoreID - var skus []*dao.StoreSkuSyncInfo if isFull { skus, err = dao.GetFullStoreSkus(db, vendorID, storeID) @@ -477,15 +490,18 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 0: if len(deleteList) > 0 { _, err = putils.FreeBatchStoreSkuInfo("删除门店商品", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { - var successList []*partner.StoreSkuInfo - if successList, err = singleStoreHandler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); singleStoreHandler.IsErrSkuNotExist(err) { + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = singleStoreHandler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) + if len(failedList) > 0 { + task.AddFailedList(failedList) + } + if singleStoreHandler.IsErrSkuNotExist(err) { err = nil } - if err == nil { - successList = batchedStoreSkuList - } else { + if err != nil { offlineList = append(offlineList, batchedStoreSkuList...) } + successList := putils.UnselectStoreSkuListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) if len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagDeletedMask) } @@ -495,29 +511,33 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 1: if len(createList) > 0 { _, err = putils.FreeBatchStoreSkuSyncInfo("创建门店商品", func(task tasksch.ITask, batchedStoreSkuList []*dao.StoreSkuSyncInfo) (result interface{}, successCount int, err error) { - var successList []*dao.StoreSkuSyncInfo - if successList, err = singleStoreHandler.CreateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); singleStoreHandler.IsErrSkuExist(err) { - if skuNameList, err2 := singleStoreHandler.GetStoreSkusFullInfo(ctx, task, storeID, vendorStoreID, []*partner.StoreSkuInfo{ - &partner.StoreSkuInfo{ - SkuID: batchedStoreSkuList[0].SkuID, - }, - }); err2 == nil && len(skuNameList) > 0 { - batchedStoreSkuList[0].VendorNameID = skuNameList[0].VendorNameID - batchedStoreSkuList[0].VendorSkuID = skuNameList[0].SkuList[0].VendorSkuID + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = singleStoreHandler.CreateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) + singleStoreHandler.IsErrSkuExist(err) + if skuNameList, err2 := singleStoreHandler.GetStoreSkusFullInfo(ctx, task, storeID, vendorStoreID, []*partner.StoreSkuInfo{ + &partner.StoreSkuInfo{ + SkuID: batchedStoreSkuList[0].SkuID, + }, + }); err2 == nil && len(skuNameList) > 0 { + batchedStoreSkuList[0].VendorNameID = skuNameList[0].VendorNameID + batchedStoreSkuList[0].VendorSkuID = skuNameList[0].SkuList[0].VendorSkuID - // 如果创建商品时已经存在,需要更新 - updateList = append(updateList, calVendorPrice4StoreSku(batchedStoreSkuList[0], storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage))) - err = nil - } - } - if err == nil { - successList = batchedStoreSkuList + // 如果创建商品时已经存在,需要更新 + updateList = append(updateList, calVendorPrice4StoreSku(batchedStoreSkuList[0], storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage))) + err = nil } else { + failedList = append(failedList, putils.GetErrMsg2FailedSingleList(batchedStoreSkuList, err2, storeID, vendorID, "查询是否有该商品")...) + } + if len(failedList) > 0 { + task.AddFailedList(failedList) + } + if err != nil { //handle error for sensitive words, if find, then insert to table sensitive_words if sensitiveWord := GetSensitiveWord(singleStoreHandler, err.Error()); sensitiveWord != "" { dao.InsertSensitiveWord(sensitiveWord, vendorID, ctx.GetUserName()) } } + successList := putils.UnselectStoreSkuSyncListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) if len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, successList, model.SyncFlagNewMask) } @@ -527,10 +547,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 2: if len(updateList) > 0 { _, err = putils.FreeBatchStoreSkuSyncInfo("更新门店商品基础信息", func(task tasksch.ITask, batchedStoreSkuList []*dao.StoreSkuSyncInfo) (result interface{}, successCount int, err error) { - var successList []*dao.StoreSkuSyncInfo - if successList, err = singleStoreHandler.UpdateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err == nil { - successList = batchedStoreSkuList + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = singleStoreHandler.UpdateStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) + if len(failedList) > 0 { + task.AddFailedList(failedList) } + successList := putils.UnselectStoreSkuSyncListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) if len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, successList, model.SyncFlagModifiedMask) } @@ -541,10 +563,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo for k, list := range [][]*partner.StoreSkuInfo{stockList /*, onlineList*/} { if len(list) > 0 { _, err = putils.FreeBatchStoreSkuInfo("更新门店商品库存", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { - var successList []*partner.StoreSkuInfo - if successList, err = storeSkuHandler.UpdateStoreSkusStock(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList); err == nil { - successList = batchedStoreSkuList + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = storeSkuHandler.UpdateStoreSkusStock(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList) + if len(failedList) > 0 { + task.AddFailedList(failedList) } + successList := putils.UnselectStoreSkuListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) if k == 0 && len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagStockMask) } @@ -563,10 +587,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo } if len(statusList) > 0 { _, err = putils.FreeBatchStoreSkuInfo(name, func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { - var successList []*partner.StoreSkuInfo - if successList, err = storeSkuHandler.UpdateStoreSkusStatus(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList, status); err == nil { - successList = batchedStoreSkuList + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = storeSkuHandler.UpdateStoreSkusStatus(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList, status) + if len(failedList) > 0 { + task.AddFailedList(failedList) } + successList := putils.UnselectStoreSkuListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) if len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagSaleMask) } @@ -576,10 +602,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo case 6: if len(priceList) > 0 { _, err = putils.FreeBatchStoreSkuInfo("更新门店商品价格", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { - var successList []*partner.StoreSkuInfo - if successList, err = storeSkuHandler.UpdateStoreSkusPrice(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList); err == nil { - successList = batchedStoreSkuList + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = storeSkuHandler.UpdateStoreSkusPrice(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList) + if len(failedList) > 0 { + task.AddFailedList(failedList) } + successList := putils.UnselectStoreSkuListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) if len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagPriceMask) } @@ -726,7 +754,7 @@ func amendAndPruneStoreStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, v } sku2Delete = nil case 2: - localCatList, err := dao.GetStoreCategories(db, vendorID, storeID, 0, false) + localCatList, err := dao.GetStoreCategories(db, vendorID, storeID, nil, 0, false) if err != nil { return nil, err } @@ -889,3 +917,13 @@ func MergeSkuSaleStatusWithStoreOpTime(sku *dao.StoreSkuSyncInfo, storeDetail *d } return sku.MergedStatus } + +func GetVendorSkuIDList(l []*partner.StoreSkuInfoWithErr) (vendorSkuIDs []string) { + vendorSkuIDs2 := make([]string, len(l)) + if len(l) > 0 { + for k, v := range l { + vendorSkuIDs2[k] = v.StoreSkuInfo.VendorSkuID + } + } + return vendorSkuIDs2 +} diff --git a/business/jxutils/tasksch/task.go b/business/jxutils/tasksch/task.go index 6cd7fce63..4f10d3f8f 100644 --- a/business/jxutils/tasksch/task.go +++ b/business/jxutils/tasksch/task.go @@ -63,7 +63,9 @@ type ITask interface { // GetDetailErrList() []error GetLeafResult() (finishedItemCount, failedItemCount int) AddBatchErr(err error) - + AddFailedList(failedList ...interface{}) + GetFailedList() (failedList []interface{}) + SetFinishHook(func(task ITask)) json.Marshaler } @@ -128,6 +130,8 @@ type BaseTask struct { ctx *jxcontext.Context isGetResultCalled bool + FailedList []interface{} + finishHook func(task ITask) } func (s TaskList) Len() int { @@ -169,6 +173,9 @@ func (t *BaseTask) GetID() string { return t.ID } +func (t *BaseTask) Run() { +} + // 此函数成功返回结果后,结果在任务中会被删除(以免被管理的任务不必要的HOLD住对象) func (t *BaseTask) GetResult(duration time.Duration) (retVal []interface{}, err error) { if t.GetStatus() >= TaskStatusEndBegin { @@ -355,6 +362,29 @@ func (t *BaseTask) Error() (errMsg string) { return errMsg } +func (t *BaseTask) SetFinishHook(hook func(task ITask)) { + t.locker.RLock() + defer t.locker.RUnlock() + t.finishHook = hook +} + +func (t *BaseTask) GetFailedList() (failedList []interface{}) { + t.locker.RLock() + failedList = append(failedList, t.FailedList...) + t.locker.RUnlock() + + for _, v := range t.Children { + failedList = append(failedList, v.GetFailedList()...) + } + return failedList +} + +func (t *BaseTask) AddFailedList(failedList ...interface{}) { + t.locker.Lock() + defer t.locker.Unlock() + t.FailedList = append(t.FailedList, failedList...) +} + // func (t *BaseTask) GetDetailErrList() []error { // t.locker.RLock() // defer t.locker.RUnlock() @@ -405,7 +435,6 @@ func (t *BaseTask) run(taskHandler func()) { task.TerminatedAt = time.Now() task.locker.Unlock() task.Error() - globals.SugarLogger.Debugf("Task:%s, mainErr:%v, batchErrList:%v", task.Name, task.mainErr, task.batchErrList) select { @@ -419,30 +448,37 @@ func (t *BaseTask) run(taskHandler func()) { globals.SugarLogger.Infof("BaseTask run, failed with error:%v", err) } } - close(t.finishChan) - time.Sleep(10 * time.Millisecond) // 等待GetResult中的isGetResultCalled赋值 - globals.SugarLogger.Debugf("BaseTask task ID:%s, name:%s finished, isGetResultCalled:%t", t.ID, t.Name, t.isGetResultCalled) - if !t.isGetResultCalled && t.parent == nil && len(GetTasks(t.ID, TaskStatusBegin, TaskStatusEnd, 24, "")) > 0 { - if authInfo, err := t.ctx.GetV2AuthInfo(); err == nil { // 这里应该是不管登录类型,直接以可能的方式发消息 - var content string - taskDesc := fmt.Sprintf("你的异步任务[%s],ID[%s],开始于:%s,结束于:%s,", t.Name, t.ID, utils.Time2Str(t.CreatedAt), utils.Time2Str(t.TerminatedAt)) - content = fmt.Sprintf("%s执行%s", taskDesc, TaskStatusName[t.Status]) - if t.Error() == "" { - noticeMsg := t.GetNoticeMsg() - if noticeMsg != "" { - content += ",通知消息:" + noticeMsg - } - } else { - content += ",\n" + t.Error() - } - ddmsg.SendUserMessage(dingdingapi.MsgTyeText, authInfo.UserID, "异步任务完成", content) - } + if t.finishHook != nil { + t.finishHook(t) + } else { + SendMessage(t) } }) } } +func SendMessage(t *BaseTask) { + time.Sleep(10 * time.Millisecond) // 等待GetResult中的isGetResultCalled赋值 + globals.SugarLogger.Debugf("BaseTask task ID:%s, name:%s finished, isGetResultCalled:%t", t.ID, t.Name, t.isGetResultCalled) + if !t.isGetResultCalled && t.parent == nil && len(GetTasks(t.ID, TaskStatusBegin, TaskStatusEnd, 24, "")) > 0 { + if authInfo, err := t.ctx.GetV2AuthInfo(); err == nil { // 这里应该是不管登录类型,直接以可能的方式发消息 + var content string + taskDesc := fmt.Sprintf("你的异步任务[%s],ID[%s],开始于:%s,结束于:%s,", t.Name, t.ID, utils.Time2Str(t.CreatedAt), utils.Time2Str(t.TerminatedAt)) + content = fmt.Sprintf("%s执行%s", taskDesc, TaskStatusName[t.Status]) + if t.Error() == "" { + noticeMsg := t.GetNoticeMsg() + if noticeMsg != "" { + content += ",通知消息:" + noticeMsg + } + } else { + content += ",\n" + t.Error() + } + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, authInfo.UserID, "异步任务完成", content) + } + } +} + // successCount表示在返回错误的情况下,(部分)成功的个数,如果没有返回错误,则successCount无意义 func (t *BaseTask) finishedOneJob(itemCount, successCount int, err error) { t.locker.Lock() diff --git a/business/model/dao/store_sku.go b/business/model/dao/store_sku.go index fba24eaad..3b94744b0 100644 --- a/business/model/dao/store_sku.go +++ b/business/model/dao/store_sku.go @@ -282,7 +282,7 @@ func GetSkusCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int // 单门店模式厂商适用 // 单纯的从已经创建的store_sku_category_map中,得到相关的同步信息 -func GetStoreCategories(db *DaoDB, vendorID, storeID int, level int, mustDirty bool) (cats []*SkuStoreCatInfo, err error) { +func GetStoreCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int, mustDirty bool) (cats []*SkuStoreCatInfo, err error) { fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := ` SELECT t4.*, @@ -291,16 +291,28 @@ func GetStoreCategories(db *DaoDB, vendorID, storeID int, level int, mustDirty b t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status FROM store_sku_category_map t5 JOIN sku_category t4 ON t5.category_id = t4.id AND t4.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + fieldPrefixParams := []interface{}{fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix} + if len(skuIDs) > 0 { + sql += ` + JOIN ( + SELECT DISTINCT b.category_id + FROM sku a + JOIN sku_name b ON a.name_id = b.id AND b.deleted_at = ? + WHERE a.id IN (` + GenQuestionMarks(len(skuIDs)) + `) + AND a.deleted_at = ? + ) t6 ON t6.category_id = t4.id + ` + sqlParams = append(sqlParams, utils.DefaultTimeValue, skuIDs, utils.DefaultTimeValue) + } + sql += ` LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5.store_id = t5p.store_id AND t5p.deleted_at = ? WHERE t5.store_id = ? AND t5.deleted_at = ?` - fieldPrefixParams := []interface{}{fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix} - sqlParams := []interface{}{ - utils.DefaultTimeValue, - utils.DefaultTimeValue, - storeID, - utils.DefaultTimeValue, - } + sqlParams = append(sqlParams, utils.DefaultTimeValue, storeID, utils.DefaultTimeValue) if mustDirty { sql += " AND t5.%s_sync_status <> 0" fieldPrefixParams = append(fieldPrefixParams, fieldPrefix) @@ -315,8 +327,8 @@ func GetStoreCategories(db *DaoDB, vendorID, storeID int, level int, mustDirty b return cats, err } -func GetDirtyStoreCategories(db *DaoDB, vendorID, storeID int, level int) (cats []*SkuStoreCatInfo, err error) { - return GetStoreCategories(db, vendorID, storeID, level, true) +func GetDirtyStoreCategories(db *DaoDB, vendorID, storeID int, level int, skuIDs []int) (cats []*SkuStoreCatInfo, err error) { + return GetStoreCategories(db, vendorID, storeID, skuIDs, level, true) } // 以store_sku_bind为基础来做同步,正常情况下使用 diff --git a/business/partner/partner_store_sku.go b/business/partner/partner_store_sku.go index aeb6969c6..d873e93ac 100644 --- a/business/partner/partner_store_sku.go +++ b/business/partner/partner_store_sku.go @@ -43,6 +43,15 @@ type StoreSkuInfo struct { Seq int `json:"seq,omitempty"` } +type StoreSkuInfoWithErr struct { + StoreSkuInfo *StoreSkuInfo + CategoryName string + VendoreID int + StoreID int + SyncType string + ErrMsg string +} + type SkuInfo struct { StoreSkuInfo SkuName string @@ -129,18 +138,18 @@ type IPurchasePlatformStoreSkuHandler interface { // 此接口要求实现为不限制批处理大小的 GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*StoreSkuInfo) (outStoreSkuList []*StoreSkuInfo, err error) - UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (successList []*StoreSkuInfo, err error) - UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo, status int) (successList []*StoreSkuInfo, err error) - UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (successList []*StoreSkuInfo, err error) + UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) + UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo, status int) (failedList []*StoreSkuInfoWithErr, err error) + UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, 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) (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) + CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*StoreSkuInfoWithErr, err error) + UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*StoreSkuInfoWithErr, err error) + DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*StoreSkuInfo) (failedList []*StoreSkuInfoWithErr, err error) DeleteStoreAllSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) IsErrSkuExist(err error) (isExist bool) IsErrSkuNotExist(err error) (isNotExist bool) diff --git a/business/partner/purchase/ebai/store_sku2.go b/business/partner/purchase/ebai/store_sku2.go index afaa0132a..8681bcd29 100644 --- a/business/partner/purchase/ebai/store_sku2.go +++ b/business/partner/purchase/ebai/store_sku2.go @@ -113,27 +113,30 @@ func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { return ebaiapi.IsErrSkuNotExist(err) } -func (p *PurchaseHandler) updateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isNeedMapCat bool) (successList []*dao.StoreSkuSyncInfo, err error) { +func (p *PurchaseHandler) updateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isNeedMapCat bool) (failedList []*partner.StoreSkuInfoWithErr, err error) { storeSku := storeSkuList[0] strStoreID := utils.Int2Str(storeID) params := genSkuParamsFromStoreSkuInfo2(storeSku, false) if globals.EnableEbaiStoreWrite { _, err = api.EbaiAPI.SkuUpdate(ctx.GetTrackInfo(), strStoreID, utils.Str2Int64(storeSku.VendorSkuID), params) + if err != nil { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "更新商品基础信息") + } if isNeedMapCat { utils.CallFuncAsync(func() { api.EbaiAPI.SkuShopCategoryMap(strStoreID, utils.Str2Int64(storeSku.VendorSkuID), "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku)) }) } } - return nil, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { return p.updateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true) } // 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 -func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { storeSku := storeSkuList[0] var vendorSkuID int64 params := genSkuParamsFromStoreSkuInfo2(storeSku, true) @@ -146,12 +149,14 @@ func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, v // 比如门店:100887, skuID:33805,订单:1577176719141226065 p.updateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false) }) + } else { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "创建商品") } } else { vendorSkuID = jxutils.GenFakeID() } storeSku.VendorSkuID = utils.Int64ToStr(vendorSkuID) - return nil, err + return failedList, err } func getFailedVendorSkuIDsFromOpResult(opResult *ebaiapi.BatchOpResult) (skuIDs []string) { @@ -163,19 +168,20 @@ func getFailedVendorSkuIDsFromOpResult(opResult *ebaiapi.BatchOpResult) (skuIDs return skuIDs } -func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableEbaiStoreWrite { opResult, err2 := api.EbaiAPI.SkuDelete(ctx.GetTrackInfo(), utils.Int2Str(storeID), partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList(), nil) if err = err2; err2 != nil && opResult != nil { - if len(storeSkuList) > len(opResult.FailedList) { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) - } + // if len(storeSkuList) > len(opResult.FailedList) { + failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorIDEBAI, "删除商品") + // successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) + // } } } - return successList, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { vendorSkuIDs := partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList() if globals.EnableEbaiStoreWrite { var opResult *ebaiapi.BatchOpResult @@ -184,19 +190,24 @@ func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOr opResult, err = api.EbaiAPI.SkuOnline(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs, nil, nil) } else if len(vendorSkuIDs) == 1 { err = api.EbaiAPI.SkuOnlineOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs[0], "", "") + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "更新商品状态") + return failedList, err } } else { if len(vendorSkuIDs) > 1 { opResult, err = api.EbaiAPI.SkuOffline(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs, nil, nil) } else if len(vendorSkuIDs) == 1 { err = api.EbaiAPI.SkuOfflineOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs[0], "", "") + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "更新商品状态") + return failedList, err } } if err != nil && opResult != nil { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) + failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorIDEBAI, "更新商品状态") + // failedList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) } } - return successList, err + return failedList, err } func StoreSkuInfoList2Ebai(storeSkuList []*partner.StoreSkuInfo) (outList ebaiapi.ShopSkuInfoList) { @@ -212,32 +223,37 @@ func StoreSkuInfoList2Ebai(storeSkuList []*partner.StoreSkuInfo) (outList ebaiap return outList } -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableEbaiStoreWrite { if len(storeSkuList) > 1 { opResult, err2 := api.EbaiAPI.SkuPriceUpdateBatch(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID) if err = err2; err != nil && opResult != nil { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) + failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorIDEBAI, "更新商品价格") } } else if len(storeSkuList) == 1 { - _, err = api.EbaiAPI.SkuPriceUpdateOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0]) + opResult2, err := api.EbaiAPI.SkuPriceUpdateOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0]) + if err != nil && opResult2 != nil { + failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult2, storeID, model.VendorIDEBAI, "更新商品价格") + } } } - return successList, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableEbaiStoreWrite { if len(storeSkuList) > 1 { opResult, err2 := api.EbaiAPI.SkuStockUpdateBatch(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID) if err = err2; err != nil && opResult != nil { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) + failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorIDEBAI, "更新商品库存") + // successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) } } else if len(storeSkuList) == 1 { err = api.EbaiAPI.SkuStockUpdateOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0]) + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDEBAI, "更新商品库存") } } - return successList, err + return failedList, err } func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo, isCreate bool) (params map[string]interface{}) { @@ -414,3 +430,26 @@ func vendorSkuList2Jx(vendorSkuList []*ebaiapi.SkuInfo) (skuNameList []*partner. func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { return sensitiveWordRegexp } + +//饿百api返回 +func SelectStoreSkuListByOpResult(storeSkuList []*partner.StoreSkuInfo, opResult *ebaiapi.BatchOpResult, storeID, vendorID int, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) { + opResultMap := make(map[int64]string) + if len(opResult.FailedList) > 0 { + for _, v := range opResult.FailedList { + opResultMap[v.SkuID] = v.ErrorMsg + } + for _, v := range storeSkuList { + if opResultMap[utils.Str2Int64(v.VendorSkuID)] != "" { + opFailed := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: v, + ErrMsg: opResultMap[utils.Str2Int64(v.VendorSkuID)], + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + selectedStoreSkuList = append(selectedStoreSkuList, opFailed) + } + } + } + return selectedStoreSkuList +} diff --git a/business/partner/purchase/jd/store_sku2.go b/business/partner/purchase/jd/store_sku2.go index 89cde63f1..6f9908730 100644 --- a/business/partner/purchase/jd/store_sku2.go +++ b/business/partner/purchase/jd/store_sku2.go @@ -110,7 +110,7 @@ func getStrOutSkuIDs(l []*jdapi.StoreSkuBatchUpdateResponse, isSuccess bool) (ou return outSkuIDs } -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { var skuVendibilityList []*jdapi.StockVendibility jdStatus := jxStoreSkuStatus2Jd(status) for _, v := range storeSkuList { @@ -122,16 +122,18 @@ func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOr if globals.EnableJdStoreWrite { responseList, err2 := getAPI(vendorOrgCode).BatchUpdateVendibility(ctx.GetTrackInfo(), "", vendorStoreID, skuVendibilityList, ctx.GetUserName()) if err = err2; isErrPartialFailed(err) { - successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) + failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorIDJD, "更新商品状态") + // successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) } } - return successList, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if len(storeSkuList) == 1 { if globals.EnableJdStoreWrite { _, err = getAPI(vendorOrgCode).UpdateStationPrice(ctx.GetTrackInfo(), utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), vendorStoreID, int(storeSkuList[0].VendorPrice)) + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDJD, "更新商品价格") } } else { var skuPriceInfoList []*jdapi.SkuPriceInfo @@ -144,17 +146,18 @@ func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrg if globals.EnableJdStoreWrite { responseList, err2 := getAPI(vendorOrgCode).UpdateVendorStationPrice(ctx.GetTrackInfo(), "", vendorStoreID, skuPriceInfoList) if err = err2; isErrPartialFailed(err) { - successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) + failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorIDJD, "更新商品价格") } } } - return successList, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if len(storeSkuList) == 1 { if globals.EnableJdStoreWrite { err = getAPI(vendorOrgCode).UpdateCurrentQty(ctx.GetTrackInfo(), vendorStoreID, utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), storeSkuList[0].Stock) + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDJD, "更新商品库存") } } else { var skuStockList []*jdapi.SkuStock @@ -167,11 +170,12 @@ func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrg if globals.EnableJdStoreWrite { responseList, err2 := getAPI(vendorOrgCode).BatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", vendorStoreID, skuStockList, ctx.GetUserName()) if err = err2; isErrPartialFailed(err) { - successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) + failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorIDJD, "更新商品库存") + // successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false))) } } } - return successList, err + return failedList, err } func (p *PurchaseHandler) SyncStoreProducts(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { @@ -211,3 +215,28 @@ func (p *PurchaseHandler) SyncStoreProducts(ctx *jxcontext.Context, vendorOrgCod } return hint, err } + +//京东api返回 +func SelectStoreSkuListByResponseList(storeSkuList []*partner.StoreSkuInfo, responseList []*jdapi.StoreSkuBatchUpdateResponse, storeID, vendorID int, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) { + responseMap := make(map[string]string) + if len(responseList) > 0 { + for _, v := range responseList { + if v.Code != "0" { + responseMap[v.OutSkuID] = v.Msg + } + } + for _, v := range storeSkuList { + if responseMap[utils.Int2Str(v.SkuID)] != "" { + respFailed := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: v, + ErrMsg: responseMap[utils.Int2Str(v.SkuID)], + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + selectedStoreSkuList = append(selectedStoreSkuList, respFailed) + } + } + } + return selectedStoreSkuList +} diff --git a/business/partner/purchase/mtwm/store_sku2.go b/business/partner/purchase/mtwm/store_sku2.go index ec63fe9ae..054504afc 100644 --- a/business/partner/purchase/mtwm/store_sku2.go +++ b/business/partner/purchase/mtwm/store_sku2.go @@ -1,6 +1,7 @@ package mtwm import ( + "encoding/json" "regexp" "strings" @@ -211,29 +212,35 @@ func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { // return newStoreSkuList // } -func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { - successList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false) +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false) // if err == nil && vendorStoreID == specialStoreID { // for i := 0; i < 2; i++ { // p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true) // } // } - return successList, err + return failedList, err } -func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (successList []*dao.StoreSkuSyncInfo, err error) { - successList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true) +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true) // if err == nil && vendorStoreID == specialStoreID { // for i := 0; i < 2; i++ { // p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true) // } // } - return successList, err + return failedList, err } // 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 -func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isCreate bool) (successList []*dao.StoreSkuSyncInfo, err error) { +func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isCreate bool) (failedList []*partner.StoreSkuInfoWithErr, err error) { + var syncType string foodDataList := make([]map[string]interface{}, len(storeSkuList)) + if isCreate { + syncType = "创建商品" + } else { + syncType = "更新商品" + } for i, storeSku := range storeSkuList { isNeedUpdatePrice := isCreate //storeSku.SkuSyncStatus&( model.SyncFlagPriceMask| model.SyncFlagNewMask) != 0 foodData := make(map[string]interface{}) @@ -295,11 +302,13 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI if len(foodDataList) == 1 { foodDataList[0]["skus"] = string(utils.MustMarshal(foodDataList[0]["skus"])) err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDMTWM, syncType) } else if len(foodDataList) > 0 { failedFoodList, err2 := api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) if err = err2; err == nil { if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { - successList = putils.UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorIDMTWM, syncType) + // successList = putils.UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) } } } @@ -307,7 +316,7 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI for _, storeSku := range storeSkuList { storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) } - return successList, err + return failedList, err } func getAppFoodCodeList(l []*mtwmapi.AppFoodResult) (vendorSkuIDs []string) { @@ -320,16 +329,24 @@ 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) { +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableMtwmStoreWrite { if len(storeSkuList) == 1 { err = api.MtwmAPI.RetailDelete(ctx.GetTrackInfo(), vendorStoreID, storeSkuList[0].VendorSkuID) + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorIDMTWM, "删除商品") } else { // todo 部分失败 err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) + if err != nil { + if errExt, ok := err.(*utils.ErrorWithCode); ok { + myMap := make(map[string][]*mtwmapi.AppFoodResult) + json.Unmarshal([]byte(errExt.ErrMsg()), &myMap) + failedList = SelectStoreSkuListByFoodList(storeSkuList, myMap["retail_error_list"], storeID, model.VendorIDMTWM, "批量删除商品") + } + } } } - return nil, err + return failedList, err } func stockCount2Mtwm(stock int) (mtwmStock string) { @@ -358,44 +375,48 @@ func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (skuLis return skuList } -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { skuList := storeSku2Mtwm(storeSkuList, updateTypeStatus) mtwmStatus := skuStatusJX2Mtwm(status) if globals.EnableMtwmStoreWrite { failedFoodList, err2 := api.MtwmAPI.RetailSellStatus(ctx.GetTrackInfo(), vendorStoreID, skuList, mtwmStatus) if err = err2; err == nil { if len(failedFoodList) > 0 { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorIDMTWM, "更新商品状态") + // successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) } } } - return successList, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { priceList := storeSku2Mtwm(storeSkuList, updateTypePrice) if globals.EnableMtwmStoreWrite { failedFoodList, err2 := api.MtwmAPI.RetailSkuPrice(ctx.GetTrackInfo(), vendorStoreID, priceList) if err = err2; err == nil { - if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + if len(failedFoodList) > 0 { + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorIDMTWM, "更新商品价格") } } } - return successList, err + return failedList, err } -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) { +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { stockList := storeSku2Mtwm(storeSkuList, updateTypeStock) if globals.EnableMtwmStoreWrite { failedFoodList, err2 := api.MtwmAPI.RetailSkuStock(ctx.GetTrackInfo(), vendorStoreID, stockList) if err = err2; err == nil { - if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { - successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + if len(failedFoodList) > 0 { + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorIDMTWM, "更新商品库存") } + //if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { + // successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + // } } } - return successList, err + return failedList, err } func mtwmSkuStatus2Jx(mtwmSkuStatus int) (jxSkuStatus int) { @@ -506,3 +527,50 @@ func vendorSkuList2Jx(appFoodList []*mtwmapi.AppFood) (skuNameList []*partner.Sk func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { return sensitiveWordRegexp } + +//美团api返回 +func SelectStoreSkuListByFoodList(storeSkuList interface{}, foodList []*mtwmapi.AppFoodResult, storeID, vendorID int, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) { + foodMap := make(map[string]string) + if len(foodList) > 0 { + for _, v := range foodList { + foodMap[v.AppFoodCode] = v.ErrorMsg + } + if storeSkuLists, ok := storeSkuList.([]*partner.StoreSkuInfo); ok { + for _, v := range storeSkuLists { + if foodMap[v.VendorSkuID] != "" { + foodFailed := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: v, + ErrMsg: foodMap[v.VendorSkuID], + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + selectedStoreSkuList = append(selectedStoreSkuList, foodFailed) + } + } + } + if storeSkuLists, ok := storeSkuList.([]*dao.StoreSkuSyncInfo); ok { + for _, v := range storeSkuLists { + if foodMap[v.VendorSkuID] != "" { + storeSkuInfo := &partner.StoreSkuInfo{ + SkuID: v.SkuID, + VendorSkuID: v.VendorSkuID, + NameID: v.NameID, + VendorNameID: v.VendorNameID, + VendorPrice: v.VendorPrice, + Status: v.Status, + } + foodFailed := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: storeSkuInfo, + ErrMsg: foodMap[v.VendorSkuID], + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + selectedStoreSkuList = append(selectedStoreSkuList, foodFailed) + } + } + } + } + return selectedStoreSkuList +} diff --git a/business/partner/putils/store_sku.go b/business/partner/putils/store_sku.go index ba5ebf3fe..0b4743c8d 100644 --- a/business/partner/putils/store_sku.go +++ b/business/partner/putils/store_sku.go @@ -58,7 +58,8 @@ func (p *DefSingleStorePlatform) DeleteStoreAllCategories(ctx *jxcontext.Context vendorCatIDs[k] = v.VendorCatID } err = FreeBatchCategoryIDOp(func(vendorCatID string) (err error) { - return p.DeleteStoreCategory(ctx, storeID, vendorStoreID, vendorCatID, step) + err2 := p.DeleteStoreCategory(ctx, storeID, vendorStoreID, vendorCatID, step) + return err2 }, ctx, task, vendorCatIDs, isContinueWhenError) return nil, err }, len(levelList)) @@ -230,6 +231,49 @@ func UnselectStoreSkuListByVendorSkuIDs(storeSkuList []*partner.StoreSkuInfo, ve return selectedStoreSkuList } +func GetErrMsg2FailedSingleList(storeSkuList interface{}, err error, storeID, vendorID int, syncType string) (failedList []*partner.StoreSkuInfoWithErr) { + if err != nil { + if errExt, ok := err.(*utils.ErrorWithCode); ok { + if storeSkuLists, ok := storeSkuList.([]*partner.StoreSkuInfo); ok { + storeSkuInfoWithErr := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: storeSkuLists[0], + ErrMsg: errExt.ErrMsg(), + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + failedList = append(failedList, storeSkuInfoWithErr) + } else if storeSkuLists, ok := storeSkuList.([]*dao.StoreSkuSyncInfo); ok { + storeSkuInfo := &partner.StoreSkuInfo{ + SkuID: storeSkuLists[0].SkuID, + VendorSkuID: storeSkuLists[0].VendorSkuID, + NameID: storeSkuLists[0].NameID, + VendorNameID: storeSkuLists[0].VendorNameID, + VendorPrice: storeSkuLists[0].VendorPrice, + Status: storeSkuLists[0].Status, + } + storeSkuInfoWithErr := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: storeSkuInfo, + ErrMsg: errExt.ErrMsg(), + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + failedList = append(failedList, storeSkuInfoWithErr) + } else { + storeSkuInfoWithErr := &partner.StoreSkuInfoWithErr{ + ErrMsg: errExt.ErrMsg(), + StoreID: storeID, + VendoreID: vendorID, + SyncType: syncType, + } + failedList = append(failedList, storeSkuInfoWithErr) + } + } + } + return failedList +} + func UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList []*dao.StoreSkuSyncInfo, vendorSkuIDs []string) (selectedStoreSkuList []*dao.StoreSkuSyncInfo) { if len(vendorSkuIDs) > 0 { vendorSkuIDMap := jxutils.StringList2Map(vendorSkuIDs)