Files
jx-callback/business/partner/purchase/tiktok_store/store_sku2.go
邹宗楠 7f8d7c0ff3 1
2022-10-09 23:00:00 +08:00

780 lines
30 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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) {
globals.SugarLogger.Debug("==============vendorStoreID", vendorStoreID)
var syncType string
storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDDD, "")
api := getAPI(storeDetail.VendorOrgCode, storeID, vendorStoreID)
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,
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",
}
// param.AccountTemplateId = ""
// 获取上传图,商品轮播图
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, 0, 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))
// 获取品牌
brandID, err := api.GetSkuBrand(param.CategoryLeafId)
if err != nil {
return nil, err
}
param.StandardBrandId = brandID
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
}
globals.SugarLogger.Debugf("tiktokResult main ===%s", utils.Format4Output(tiktokResult, false))
// 创建子商品
param.FreightId = freightId
param.MainProductId = tiktokResult.ProductId
param.SpecPrices = GetSpecPrices(param.Specs, vendorStoreID, tiktokResult.ProductId, storeSku)
// 获取门店限售模板
saleLimitId, err := CreateSaleTemp(utils.Str2Int64(vendorStoreID), api)
globals.SugarLogger.Debug("==22213123131231231", saleLimitId)
if err != nil {
return nil, err
}
param.SaleLimitId = saleLimitId
param.StoreId = utils.Str2Int64(vendorStoreID)
// 抖店创建商品
globals.SugarLogger.Debugf("zishangping=============%s", utils.Format4Output(param, false))
tiktokResultChildren, 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(tiktokResultChildren.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, 0, 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{},
}
tradeLimitRuleRequestList := make([]trade_createTradeLimitTemplate_request.TradeLimitRuleRequestListItem, 0)
tradeLimitRuleRequest := trade_createTradeLimitTemplate_request.TradeLimitRuleRequestListItem{
TradeLimitModel: 1, // 限购模型 1-重量2-数量3-地区4-金额
TradeLimitResource: 2, // 限购资源类别1-抖店2-门店3-商品ID4-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
}