package tiktok_store import ( "errors" "fmt" "git.rosy.net.cn/baseapi/platformapi/mtwmapi" freightTemplate_create_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/freightTemplate_create/request" product_addV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_addV2/request" product_detail_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_detail/response" product_editV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_editV2/request" shop_bindStoreFreight_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/shop_bindStoreFreight/request" shop_bindStoreSaleLimit_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/shop_bindStoreSaleLimit/request" sku_editPrice_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/sku_editPrice/request" trade_createTradeLimitTemplate_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/trade_createTradeLimitTemplate/request" tiktokShop "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner/putils" "git.rosy.net.cn/jx-callback/globals" "math/rand" "regexp" ) const ( updateTypeStock = iota updateTypeStatus updateTypePrice ) const ( defVendorCatID = 200001903 // 生菜 specialStoreID = "8171010" // specialStoreID = "2523687" ) var ( sensitiveWordRegexp = regexp.MustCompile(`包含敏感词:(\[.*\])`) ) // GetStoreSkusBatchSize 当前任务最大更新条数 func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { switch funcID { case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice: batchSize = tiktokShop.MaxStoreSkuBatchSize case partner.FuncDeleteStoreSkus: batchSize = tiktokShop.MaxBatchDeleteSize case partner.FuncCreateStoreSkus: batchSize = 1 // 可考虑用批量操作 case partner.FuncUpdateStoreSkus: batchSize = 1 // mtwmapi.MaxStoreSkuBatchSize case partner.FuncGetStoreSkusFullInfo: batchSize = 1 case partner.FuncCreateActs: batchSize = tiktokShop.MaxRetailDiscountCreateBatchSize case partner.FuncCancelActs: batchSize = tiktokShop.MaxRetailDiscountDeleteBatchSize } return batchSize } func getStoreVendorOrgCode(storeID int) (vendorOrgCode string) { if storeMap, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDDD, ""); storeMap != nil { return storeMap.VendorOrgCode } return vendorOrgCode } // GetStoreAllCategories 门店分类 func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { remoteCats, err := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).GetShopCategory(0) if err == nil { cats = convertVendorCatList(remoteCats) } return cats, err } func convertVendorCatList(remoteCats []*tiktokShop.RetailCategoryInfo) (cats []*partner.BareCategoryInfo) { for _, rCat := range remoteCats { cat := &partner.BareCategoryInfo{ VendorCatID: utils.Int64ToStr(rCat.Id), Name: rCat.Name, Level: int(rCat.Level), Seq: 0, Children: convertVendorCatList(rCat.Children), } if cat.VendorCatID == "" { cat.VendorCatID = rCat.Name } cats = append(cats, cat) } 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 catCode2Str(catCode int) (catCodeStr string) { if catCode > 0 { catCodeStr = utils.Int2Str(catCode) } return catCodeStr } func tryCatName2Code(originName string) (catCodeStr string) { if intValue := utils.Str2Int64WithDefault(originName, 0); intValue > 0 { catCodeStr = utils.Int64ToStr(intValue) if catCodeStr != originName { catCodeStr = "" } } return catCodeStr } func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { //level := 1 //if storeCat.ParentCatName != "" { // level = 2 //} //originName := "" //catName := storeCat.Name //catCode := storeCat.ID // //subCatName := "" //subCatCode := 0 //if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 { // // 修改一级分类 // originName = storeCat.VendorCatID //} //if level == 2 { // 二级分类 // // 创建二级分类 // originName = storeCat.ParentVendorCatID // catName = storeCat.ParentCatName // catCode = storeCat.ParentID // subCatName = storeCat.Name // subCatCode = storeCat.ID // if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 { // // 修改二级分类 // originName = storeCat.VendorCatID // catName = storeCat.Name // catCode = storeCat.ID // subCatName = "" // subCatCode = 0 // } //} //if catName == "" { // panic("catName is empty") //} //catName = utils.FilterEmoji(catName) //subCatName = utils.FilterEmoji(subCatName) //globals.SugarLogger.Debugf("mtwm CreateStoreCategory vendorStoreID:%s, originName:%s, catCode:%d, catName:%s, subCatCode:%d, subCatName:%s, seq:%d", // vendorStoreID, originName, catCode, catName, subCatCode, subCatName, storeCat.Seq) //if globals.EnableMtwmStoreWrite { // // err = api.MtwmAPI.RetailCatUpdate2(vendorStoreID, tryCatName2Code(originName), originName, catCode2Str(catCode), catName, catCode2Str(subCatCode), subCatName, storeCat.Seq) // param4Update := &mtwmapi.Param4UpdateCat{ // CategoryCodeOrigin: tryCatName2Code(originName), // CategoryNameOrigin: originName, // CategoryCode: catCode2Str(catCode), // SecondaryCategoryCode: catCode2Str(subCatCode), // SecondaryCategoryName: subCatName, // Sequence: storeCat.Seq, // } // err = getAPI(storeCat.VendorOrgCode, storeID, vendorStoreID).RetailCatUpdate(vendorStoreID, catName, param4Update) // if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 && p.IsErrCategoryNotExist(err) && originName != "" { // 修改分类名,但分类不存在 // storeCat.CatSyncStatus |= model.SyncFlagNewMask // err = p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat) // } //} //if err == nil { // // storeCat.VendorCatID = utils.FilterEmoji(storeCat.Name) // storeCat.VendorCatID = utils.Int2Str(storeCat.ID) //} return err } func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { return p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat) } func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { //if false { // if globals.EnableMtwmStoreWrite { // err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatDelete(vendorStoreID, tryCatName2Code(vendorCatID), vendorCatID) // } //} else { // var catCodes []string // if catCode := tryCatName2Code(vendorCatID); catCode != "" { // catCodes = []string{catCode} // } // if globals.EnableMtwmStoreWrite { // if level == 1 { // err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, catCodes, []string{vendorCatID}, nil, nil, nil) // } else { // err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, catCodes, []string{vendorCatID}, nil) // } // } //} return err } // 门店商品 // 多门店平台不需要实现这个接口 func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) { return false } func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { return mtwmapi.IsErrSkuNotExist(err) } // func duplicateStoreSkuList(storeSkuList []*dao.StoreSkuSyncInfo, index int) (newStoreSkuList []*dao.StoreSkuSyncInfo) { // newStoreSkuList = make([]*dao.StoreSkuSyncInfo, len(storeSkuList)) // for k, v := range storeSkuList { // tmp := *v // tmp.SkuName = fmt.Sprintf("%s.%d", tmp.SkuName, index) // tmp.SkuID = index*1000000 + tmp.SkuID // newStoreSkuList[k] = &tmp // } // return newStoreSkuList // } 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 failedList, err } // CreateStoreSkus 门店创建商品 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) // } //} globals.SugarLogger.Debugf("============CreateStoreSkus===============%s", utils.Format4Output(failedList, false)) globals.SugarLogger.Debugf("============CreateStoreSkus===============%s", err) return failedList, err } // 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 // 抖店的商品只管创建,创建接口会返回成功,但是审核的时候不一定成功.当前系统无法判定此商品是否已经创建过了! func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isCreate bool) (failedList []*partner.StoreSkuInfoWithErr, err error) { var syncType string storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDDD, "") api := getAPI(storeDetail.VendorOrgCode, storeID, vendorStoreID) globals.SugarLogger.Debug("=============", storeDetail.VendorOrgCode) globals.SugarLogger.Debugf("api===============%v", utils.Format4Output(api, false)) freightId, _ := api.GetStoreBindTemp(utils.Str2Int64(vendorStoreID)) if freightId == 0 { // 创建门店运费模板 temp, err := api.FreightTemplateCreate(&freightTemplate_create_request.FreightTemplateCreateParam{ Template: &freightTemplate_create_request.Template{ TemplateName: storeDetail.Name + "_" + utils.Int64ToStr(rand.Int63n(int64(storeID))) + "_系统模板", ProductProvince: utils.Str2Int64(utils.Int2Str(storeDetail.ProvinceCode)[0:2]), ProductCity: int64(storeDetail.CityCode), CalculateType: 2, TransferType: 1, // 快递 RuleType: 1, FixedAmount: 500, }, Columns: nil, }) if err != nil { return nil, err } // 绑定门店运费模板 err = api.BindFreightTemplate(&shop_bindStoreFreight_request.ShopBindStoreFreightParam{ StoreId: utils.Str2Int64(vendorStoreID), FreightId: temp.TemplateId, }) if err != nil { return nil, err } freightId = temp.TemplateId } if isCreate { syncType = "创建商品" for _, storeSku := range storeSkuList { // 创建商品 param := &product_addV2_request.ProductAddV2Param{ CategoryLeafId: utils.Str2Int64(storeSku.SkuVendorMapCatID), Name: storeSku.Name, PayType: tiktokShop.TiktokPayType1, ReduceType: tiktokShop.SkuReduceTypePayMakeOrder, FreightId: freightId, Weight: utils.Int2Float64(storeSku.Weight), DeliveryDelayDay: tiktokShop.DeliveryDelayDayToDay, PresellType: tiktokShop.SendGoodsTypeNow, Supply7dayReturn: 0, Mobile: storeDetail.Tel1, Commit: true, Specs: "净重|" + fmt.Sprintf("%f", storeSku.SpecQuality) + storeSku.SpecUnit, NeedRechargeMode: false, SellChannel: []int64{0}, StartSaleType: 0, PickupMethod: "0", StoreId: utils.Str2Int64(vendorStoreID), MainProductId: int64(storeSku.NameID), } // 获取上传图,商品轮播图 img, err := GetTiktokImgList(utils.Int2Str(storeSku.StoreID), storeDetail.VendorOrgCode, storeSku.ImgOrigin, storeSku.Img2, storeSku.Img3, storeSku.Img4, storeSku.Img5) if err != nil { return nil, err } param.Pic = img // 商品详情图 img2, err := GetTiktokImgList(utils.Int2Str(storeSku.StoreID), storeDetail.VendorOrgCode, storeSku.DescImg) if err != nil { return nil, err } param.Description = img2 // weight_unit 目前抖音只支持g和kg两种 switch storeSku.Unit { case "g", "ml", "G", "ML": param.WeightUnit = tiktokShop.WeightUint_G case "kg", "l", "L", "KG": param.WeightUnit = tiktokShop.WeightUint_G } // spec_prices param.SpecPrices = GetSpecPrices(param.Specs, vendorStoreID, storeSku) // ProductFormatNew productFormatNew, err := GetProductFormatNew(param.CategoryLeafId, storeDetail.VendorOrgCode) globals.SugarLogger.Debug("创建=============productFormatNew", productFormatNew) globals.SugarLogger.Debug("创建=============productFormatNew err", err) if err != nil { return nil, err } param.ProductFormatNew = productFormatNew globals.SugarLogger.Debug("创建=============param", utils.Format4Output(param, false)) // 获取门店限售模板 saleLimitId, err := CreateSaleTemp(param.StoreId, api) globals.SugarLogger.Debug("==22213123131231231", saleLimitId) if err != nil { return nil, err } param.SaleLimitId = saleLimitId // 抖店创建商品 tiktokResult, err := api.CreateStoreCommodity(param) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDDD], syncType) storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) continue } storeSku.VendorSkuID = utils.Int64ToStr(tiktokResult.ProductId) } } else { syncType = "更新商品" for _, storeSku := range storeSkuList { param := &product_editV2_request.ProductEditV2Param{ ProductId: utils.Str2Int64(storeSku.VendorSkuID), CategoryLeafId: utils.Str2Int64(storeSku.VendorCatID), Name: storeSku.Name, PayType: tiktokShop.TiktokPayType1, ReduceType: tiktokShop.SkuReduceTypePayMakeOrder, FreightId: freightId, Weight: utils.Int2Float64(storeSku.Weight), DeliveryDelayDay: tiktokShop.DeliveryDelayDayToDay, PresellType: tiktokShop.SendGoodsTypeNow, Supply7dayReturn: 0, Mobile: storeDetail.Tel1, Commit: true, Specs: "净重|" + fmt.Sprintf("%f", storeSku.SpecQuality) + storeSku.SpecUnit, NeedRechargeMode: false, SellChannel: []int64{0}, StartSaleType: 0, PickupMethod: "0", StoreId: int64(storeSku.StoreID), MainProductId: int64(storeSku.NameID), } // 获取上传图,商品轮播图 img, err := GetTiktokImgList(utils.Int2Str(storeSku.StoreID), storeDetail.VendorOrgCode, storeSku.ImgOrigin, storeSku.Img2, storeSku.Img3, storeSku.Img4, storeSku.Img5) if err != nil { return nil, err } param.Pic = img // 商品详情图 img2, err := GetTiktokImgList(utils.Int2Str(storeSku.StoreID), storeDetail.VendorOrgCode, storeSku.DescImg) if err != nil { return nil, err } param.Description = img2 // weight_unit 目前抖音只支持g和kg两种 switch storeSku.Unit { case "g", "ml", "G", "ML": param.WeightUnit = tiktokShop.WeightUint_G case "kg", "l", "L", "KG": param.WeightUnit = tiktokShop.WeightUint_G } // spec_prices param.SpecPrices = GetSpecPrices(param.Specs, vendorStoreID, storeSku) // ProductFormatNew productFormatNew, err := GetProductFormatNew(param.CategoryLeafId, storeDetail.VendorOrgCode) globals.SugarLogger.Debug("更新=============productFormatNew", productFormatNew) globals.SugarLogger.Debug("更新=============productFormatNew err", err) if err != nil { return nil, err } param.ProductFormatNew = productFormatNew // 抖店更新商品 if err := api.EditStoreCommodity(param); err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDDD], syncType) storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) continue } } return } if len(failedList) > 0 { err = nil } return failedList, err } // CreateSaleTemp 创建限售模板 func CreateSaleTemp(storeId int64, api *tiktokShop.API) (int64, error) { // 获取限售模板 saleLimitId, _ := api.StoreQuerySaleLimitTemp(storeId) globals.SugarLogger.Debug("==========saleLimitId1", saleLimitId) if saleLimitId != 0 { return saleLimitId, nil } // 创建限售模板 param := &trade_createTradeLimitTemplate_request.TradeCreateTradeLimitTemplateParam{ StoreId: storeId, TradeLimitRuleRequestList: []trade_createTradeLimitTemplate_request.TradeLimitRuleRequestListItem{}, } param.StoreId = storeId tradeLimitRuleRequestList := make([]trade_createTradeLimitTemplate_request.TradeLimitRuleRequestListItem, 0) tradeLimitRuleRequest := trade_createTradeLimitTemplate_request.TradeLimitRuleRequestListItem{ TradeLimitModel: 1, // 限购模型 1-重量,2-数量,3-地区,4-金额 TradeLimitResource: 2, // 限购资源类别1-抖店,2-门店,3-商品ID,4-sku,5-类目,6-活动,7-商品标 TradeLimitResourceObject: nil, TradeLimitPattern: &trade_createTradeLimitTemplate_request.TradeLimitPattern{ Minimum: 1, // 1毫克 Maximum: 500 * 1000 * 1000, //500千克 CumulativeMax: 99999, }, TimePeriod: nil, TradeLimitSubjectList: []int32{1}, } tradeLimitRuleRequestList = append(tradeLimitRuleRequestList, tradeLimitRuleRequest) result, err := api.CreateTradeLimitTemplate(param) globals.SugarLogger.Debug("==========err2222", err) globals.SugarLogger.Debug("==========result222", utils.Format4Output(result, false)) if err != nil { return 0, err } if result.TradeLimitId == 0 { return 0, errors.New("限售模板创建错误,联系管理员") } // 绑定限售模板 if err := api.BindStoreSaleLimit(&shop_bindStoreSaleLimit_request.ShopBindStoreSaleLimitParam{ StoreId: storeId, SaleLimitId: result.TradeLimitId, }); err != nil { globals.SugarLogger.Debug("==========BindStoreSaleLimit", err) return 0, err } return result.TradeLimitId, nil } func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableDdStoreWrite { for _, v := range storeSkuList { if err = getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID).DeleteStoreCommodity(utils.Str2Int64(v.VendorSkuID)); err != nil { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "删除商品")...) } } } if len(failedList) > 0 { err = nil } return failedList, err } func stockCount2Mtwm(stock int) (mtwmStock string) { return utils.Int2Str(stock) } func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (skuList []*mtwmapi.BareStoreFoodInfo) { for _, storeSku := range storeSkuList { skuInfo := &mtwmapi.BareStoreFoodInfo{ AppFoodCode: storeSku.VendorSkuID, Skus: []*mtwmapi.BareStoreSkuInfo{ &mtwmapi.BareStoreSkuInfo{ SkuID: storeSku.VendorSkuID, }, }, } if updateType == updateTypeStock { skuInfo.Skus[0].Stock = stockCount2Mtwm(storeSku.Stock) } else if updateType == updateTypePrice { skuInfo.Skus[0].Price = jxutils.IntPrice2StandardString(storeSku.VendorPrice) } else { skuInfo.Skus = nil } skuList = append(skuList, skuInfo) } return skuList } // UpdateStoreSkusStatus 批量更新商品上下架 func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { api := getAPI(vendorOrgCode, storeID, vendorStoreID) if status == model.SkuStatusNormal { // 上架 for _, v := range storeSkuList { if err := api.EditStoreCommodity(&product_editV2_request.ProductEditV2Param{ ProductId: utils.Str2Int64(v.VendorSkuID), Commit: true, }); err != nil { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "上架商品正常")...) } else { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "上架商品异常")...) } } } else { // 下架 for _, v := range storeSkuList { err := api.ProductSetOffline(utils.Str2Int64(v.VendorSkuID)) if err == nil { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "下架商品正常")...) } else { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "下架商品异常")...) } } } if len(failedList) > 0 { err = nil } return failedList, err } // UpdateStoreSkusPrice 更新商品价格 func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { api := getAPI(vendorOrgCode, storeID, vendorStoreID) for _, v := range storeSkuList { //param := &product_editV2_request.ProductEditV2Param{} //param.ProductId = utils.Str2Int64(v.VendorSkuID) //param.Specs = "净重|" + fmt.Sprintf("%f", v.SpecQuality) + v.SpecUnit // //skuSize := make([]*tiktokShop.SpecDetailList, 0, 0) //detail1 := strings.Split(param.Specs, "^") //name1 := strings.Split(strings.Split(detail1[0], "|")[1], ",") //for i := 0; i < len(name1); i++ { // sku := &tiktokShop.SpecDetailList{ // SpecDetailName1: name1[i], // StockNum: v.Stock, // Price: int(v.VendorPrice), // Code: utils.Int2Str(v.SkuID), // StepStockNum: 0, // SupplierID: "", // OuterSkuID: utils.Int2Str(v.NameID), // DeliveryInfos: []*tiktokShop.DeliveryInfos{ // {InfoType: "weight", InfoUnit: v.SpecUnit, InfoValue: fmt.Sprintf("%f", v.SpecQuality)}, // }, // } // skuSize = append(skuSize, sku) //} //data, _ := json.Marshal(skuSize) //param.SpecPrices = string(data) param := &sku_editPrice_request.SkuEditPriceParam{ Price: v.VendorPrice, Code: "", SkuId: 0, OutSkuId: int64(v.SkuID), ProductId: utils.Str2Int64(v.VendorSkuID), //OutProductId: int64(v.SkuID), } err := api.EditPrice(param) if err != nil { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "更新价格异常")...) } else { failedList = append(failedList, putils.GetErrMsg2FailedSingleList(v, err, storeID, model.VendorChineseNames[model.VendorIDDD], "更新价格正常")...) } } if len(failedList) > 0 { err = nil } return failedList, err } func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableDdStoreWrite { return p.UpdateStoreSkusPrice(ctx, vendorOrgCode, storeID, vendorStoreID, storeSkuList) } return nil, err } func tiktokSkuStatus2Jx(skuStatus int64) (jxSkuStatus int) { if skuStatus == mtwmapi.SellStatusOnline { jxSkuStatus = model.SkuStatusNormal } else { jxSkuStatus = model.SkuStatusDontSale } return jxSkuStatus } func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) { // 查询单个门店商品 tiktokApi := getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID) for _, v := range storeSkuList { skuInfo, err := tiktokApi.GetSkuDetail(v.VendorSkuID, utils.Int2Str(v.SkuID)) if err != nil { return nil, err } if skuName := vendorSku2Jx(skuInfo); skuName != nil { skuNameList = append(skuNameList, skuName) } } //switch len(storeSkuList) { //case 1: // //default: // // 列表查询门店商品 // //var storeSkuMap map[string]*partner.StoreSkuInfo // //if storeSkuList != nil { // // storeSkuMap = putils.StoreSkuList2MapByVendorSkuID(storeSkuList) // //} // //for { // // result, err := mtapi.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit) // // if err != nil { // // return nil, err // // } // // if storeSkuMap == nil { // // skuNameList = append(skuNameList, vendorSkuList2Jx(result)...) // // } else { // // for _, v := range result { // // if storeSkuMap[v.AppFoodCode] != nil { // // if skuName := vendorSku2Jx(v); skuName != nil { // // skuNameList = append(skuNameList, skuName) // // } // // } // // } // // } // // if len(result) < mtwmapi.GeneralMaxLimit { // // break // // } // //} //} return skuNameList, err } func vendorSku2Jx(tiktokSku *product_detail_response.ProductDetailData) (skuName *partner.SkuNameInfo) { if len(tiktokSku.SpecPrices) == 0 { globals.SugarLogger.Warnf("vendorSku2Jx, strange tiktokSku:%s", utils.Format4Output(tiktokSku, true)) return nil } prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(tiktokSku.Name) vendorSku := tiktokSku.SpecPrices[0] weight := jxutils.FormatSkuWeight(specQuality, specUnit) skuName = &partner.SkuNameInfo{ NameID: utils.Str2Int(vendorSku.OuterSkuId), VendorNameID: utils.Int64ToStr(tiktokSku.MainProductId), UPC: tiktokSku.ProductIdStr, Prefix: prefix, Name: name, Unit: unit, Status: tiktokSkuStatus2Jx(tiktokSku.Status), //此处为之前一个bug 如果吧状态放到切片内层 对于内层函数中映射无法关联 永远获取到的初始值为0 SkuList: []*partner.SkuInfo{ &partner.SkuInfo{ StoreSkuInfo: partner.StoreSkuInfo{ VendorSkuID: utils.Int64ToStr(vendorSku.SkuId), SkuID: int(vendorSku.OutSkuId), IsSpecialty: 0, Stock: int(vendorSku.StockNum), VendorPrice: vendorSku.Price, Status: tiktokSkuStatus2Jx(tiktokSku.Status), }, SkuName: tiktokSku.Name, Comment: comment, SpecQuality: float64(specQuality), SpecUnit: specUnit, Weight: weight, }, }, PictureList: tiktokSku.Pic, } if tiktokSku.CategoryDetail != nil { // todo, 因为当前我们用的是分类名操作这种方式,所以要返回分类名(而不是分类code) skuName.VendorCatIDList = []string{tiktokSku.CategoryDetail.FirstCname, tiktokSku.CategoryDetail.SecondCname, tiktokSku.CategoryDetail.ThirdCname, tiktokSku.CategoryDetail.FourthCname} } return skuName } func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { return sensitiveWordRegexp } // CreateStoreSkusAct 创建商品活动 func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { //actStoreSkuList := putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, storeSkuList) //failedList, err = createOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, actStoreSkuList) //storeSkuMap := putils.StoreSkuList2MapBySkuID(storeSkuList) //for _, v := range actStoreSkuList { // storeSkuMap[v.SkuID].VendorActID = v.VendorActID //} //if len(failedList) > 0 { // err = nil //} return failedList, err } func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { return nil, err // return cancelOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, putils.StoreSku2ActStoreSku(model.SyncFlagDeletedMask, vendorStoreID, storeSkuList)) } func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { //var foodDataList []map[string]interface{} //for _, v := range storeSkuList { // var foodData = make(map[string]interface{}) // if v.IsSpecialty != 0 && v.IsSpecialty == -1 { // v.IsSpecialty = 0 // } // foodData["is_specialty"] = v.IsSpecialty // foodData["app_food_code"] = v.SkuID // foodDataList = append(foodDataList, foodData) //} //if globals.EnableMtwmStoreWrite { // if len(foodDataList) == 1 { // err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) // } else if len(foodDataList) > 0 { // _, err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) // } //} return err }