添加美团个各个平台相互复制
This commit is contained in:
@@ -4,14 +4,19 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
product_addV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_addV2/request"
|
||||
"git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"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/purchase/mtwm"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/tiktok_store"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
beego "github.com/astaxie/beego/server/web"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
@@ -50,6 +55,14 @@ func CopyOnStoreSkuToOther(ctx *jxcontext.Context, fromStoreId, toStoreId string
|
||||
_, copySkuErr, err = CopyMtToMT(ctx, fromStore, toStore, isAsync, offSet)
|
||||
case model.VendorIDEBAI:
|
||||
_, copySkuErr, err = CopyEBaiToEBai(ctx, fromStore, toStore, isAsync, offSet)
|
||||
case 114: // 美团到抖音
|
||||
_, copySkuErr, err = CopyMtToTiktok(ctx, fromStore, toStore, isAsync, offSet)
|
||||
case 13: // 美团到饿了么
|
||||
_, copySkuErr, err = CopyMtToEBai(ctx, fromStore, toStore, isAsync, offSet)
|
||||
case 31: // 饿了么到美团
|
||||
_, copySkuErr, err = CopyEBaiToMt(ctx, fromStore, toStore, isAsync, offSet)
|
||||
case 10: // 美团到京东
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("暂时还不支持")
|
||||
}
|
||||
@@ -64,7 +77,7 @@ func CopyOnStoreSkuToOther(ctx *jxcontext.Context, fromStoreId, toStoreId string
|
||||
return copySkuErr, err
|
||||
}
|
||||
|
||||
//#region 同步商品
|
||||
//#region 饿百同步商品
|
||||
|
||||
// CopyEBaiToEBai 饿了么商品复制到饿了么
|
||||
func CopyEBaiToEBai(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail, isAsync bool, offset int) (hint string, errList []string, err error) {
|
||||
@@ -180,10 +193,14 @@ func BatchInitSkuEBai2EBai(ctx *jxcontext.Context, fromSku []*ebaiapi.SkuInfo, t
|
||||
return errList
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 美团同步商品
|
||||
|
||||
// CopyMtToMT 美团商品复制到美团
|
||||
func CopyMtToMT(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail, isAsync bool, offSet int) (hint string, data []string, err error) {
|
||||
var fromApi *mtwmapi.API //= mtwm.GetAPI(fromStore.VendorOrgCode, fromStore.ID, fromStore.VendorStoreID)
|
||||
var toApi *mtwmapi.API // = mtwm.GetAPI(toStore.VendorOrgCode, toStore.ID, toStore.VendorStoreID)
|
||||
var fromApi *mtwmapi.API
|
||||
var toApi *mtwmapi.API
|
||||
var errList = make([]*mtwmapi.AppFoodResult, 0, 0)
|
||||
var errData = make([]string, 0, 0)
|
||||
|
||||
@@ -207,35 +224,35 @@ func CopyMtToMT(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail, isA
|
||||
switch step {
|
||||
case 1:
|
||||
// 同步分类
|
||||
//fromCategoryList, err := fromApi.RetailCatList(fromStore.VendorStoreID)
|
||||
//if len(fromCategoryList) == model.NO {
|
||||
fromCategoryList, err := fromApi.RetailCatList(fromStore.VendorStoreID)
|
||||
if len(fromCategoryList) == model.NO {
|
||||
return nil, err
|
||||
}
|
||||
//toCategoryList, err := toApi.RetailCatList(toStore.VendorStoreID)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
////toCategoryList, err := toApi.RetailCatList(toStore.VendorStoreID)
|
||||
////if err != nil {
|
||||
//// return nil, err
|
||||
////}
|
||||
//for _, v := range fromCategoryList {
|
||||
// categoryErr := toApi.RetailCatUpdate(toStore.VendorStoreID, v.Name, &mtwmapi.Param4UpdateCat{
|
||||
// CategoryCode: v.Code,
|
||||
// Sequence: v.Sequence,
|
||||
// })
|
||||
// if categoryErr != nil {
|
||||
// globals.SugarLogger.Debugf("err := RetailCatUpdate : %v", categoryErr)
|
||||
// }
|
||||
// if v.Children != nil && len(v.Children) != 0 {
|
||||
// for _, c := range v.Children {
|
||||
// if err3 := toApi.RetailCatUpdate(toStore.VendorStoreID, v.Name, &mtwmapi.Param4UpdateCat{
|
||||
// CategoryNameOrigin: v.Name,
|
||||
// SecondaryCategoryCode: c.Code,
|
||||
// SecondaryCategoryName: c.Name,
|
||||
// Sequence: c.Sequence,
|
||||
// }); err3 != nil {
|
||||
// globals.SugarLogger.Debugf("err := RetailCatUpdate Children : %v", err3)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
for _, v := range fromCategoryList {
|
||||
categoryErr := toApi.RetailCatUpdate(toStore.VendorStoreID, v.Name, &mtwmapi.Param4UpdateCat{
|
||||
CategoryCode: v.Code,
|
||||
Sequence: v.Sequence,
|
||||
})
|
||||
if categoryErr != nil {
|
||||
globals.SugarLogger.Debugf("err := RetailCatUpdate : %v", categoryErr)
|
||||
}
|
||||
if v.Children != nil && len(v.Children) != 0 {
|
||||
for _, c := range v.Children {
|
||||
if err3 := toApi.RetailCatUpdate(toStore.VendorStoreID, v.Name, &mtwmapi.Param4UpdateCat{
|
||||
CategoryNameOrigin: v.Name,
|
||||
SecondaryCategoryCode: c.Code,
|
||||
SecondaryCategoryName: c.Name,
|
||||
Sequence: c.Sequence,
|
||||
}); err3 != nil {
|
||||
globals.SugarLogger.Debugf("err := RetailCatUpdate Children : %v", err3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
i := offSet
|
||||
@@ -462,6 +479,743 @@ func createCommonAttrValue(apiObj *mtwmapi.API, tempCatID int64, name string) (s
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 美团同步到抖音商品
|
||||
|
||||
// CopyMtToTiktok 复制美团商品到抖音
|
||||
func CopyMtToTiktok(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail, isAsync bool, offSet int) (hint string, data []string, err error) {
|
||||
var fromApi *mtwmapi.API //= mtwm.GetAPI(fromStore.VendorOrgCode, fromStore.ID, fromStore.VendorStoreID)
|
||||
var toApi = partner.CurAPIManager.GetAPI(model.VendorIDDD, toStore.VendorOrgCode).(*tiktok_api.API)
|
||||
var errList = make([]*mtwmapi.AppFoodResult, 0, 0)
|
||||
var errData = make([]string, 0, 0)
|
||||
|
||||
if fromStore.VendorOrgCode == globals.Mtwm2Code {
|
||||
fromApi = mtwmapi.New(beego.AppConfig.DefaultString("mtwmAppID2", ""), beego.AppConfig.DefaultString("mtwmSecret2", ""), beego.AppConfig.DefaultString("mtwmCallbackURL2", ""), "")
|
||||
fromApi.SetToken(fromStore.MtwmToken)
|
||||
} else {
|
||||
fromApi = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, fromStore.VendorOrgCode).(*mtwmapi.API)
|
||||
}
|
||||
|
||||
taskName := fmt.Sprintf("将美团平台门店[%s],分类和商品复制到抖音[%s]", fromStore.VendorStoreID, toStore.VendorStoreID)
|
||||
config := tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(false)
|
||||
work := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
step := batchItemList[0].(int)
|
||||
switch step {
|
||||
case 1:
|
||||
|
||||
case 2:
|
||||
i := offSet
|
||||
for {
|
||||
// 同步商品
|
||||
fromFoodList, err1 := fromApi.RetailListAll(fromStore.VendorStoreID, i)
|
||||
if len(fromFoodList) == 0 || fromFoodList == nil {
|
||||
return nil, fmt.Errorf("fromFoodList 为空 %s ,i:= %d", utils.Format4Output(err1, false), i)
|
||||
}
|
||||
|
||||
errDataList, err := BatchInitSkuMT2TT(ctx, fromFoodList, fromStore.VendorStoreID, toApi, toStore, i)
|
||||
if err != nil {
|
||||
globals.SugarLogger.Debugf("BatchInitData : %v", err)
|
||||
}
|
||||
if len(errDataList) > model.NO {
|
||||
globals.SugarLogger.Debugf("errListData %d:= %s", i, utils.Format4Output(errDataList, false))
|
||||
errList = append(errList, errDataList...)
|
||||
}
|
||||
globals.SugarLogger.Debugf("==========页数[%d],数据长度[%d]", i, len(fromFoodList))
|
||||
if len(fromFoodList) < 100 {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
task := tasksch.NewParallelTask(taskName, config, ctx, work, []int{1, 2})
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
hint = "1"
|
||||
} else {
|
||||
hint = task.ID
|
||||
}
|
||||
|
||||
globals.SugarLogger.Debugf("======errrList := %s", utils.Format4Output(errList, false))
|
||||
for _, v := range errList {
|
||||
errData = append(errData, fmt.Sprintf("food_id:%s,错误:%s", v.AppFoodCode, v.ErrorMsg))
|
||||
}
|
||||
|
||||
return hint, errData, err
|
||||
}
|
||||
|
||||
var StoreTemp = make(map[string]string, 0)
|
||||
|
||||
// BatchInitSkuMT2TT 批量创建商品美团->抖音
|
||||
func BatchInitSkuMT2TT(ctx *jxcontext.Context, fromSku []*mtwmapi.AppFood, fromStoreId string, toApi *tiktok_api.API, toStoreDetail *dao.StoreDetail, offset int) ([]*mtwmapi.AppFoodResult, error) {
|
||||
errList := make([]*mtwmapi.AppFoodResult, 0, 0)
|
||||
db := dao.GetDB()
|
||||
|
||||
copyMap, _ := dao.GetCopyInfo(fromStoreId, model.VendorIDMTWM, toStoreDetail.VendorStoreID, model.VendorIDDD)
|
||||
for k, storeSku := range fromSku {
|
||||
if storeSku.AppFoodCode == "" {
|
||||
storeSku.AppFoodCode = fmt.Sprintf("%d_%d", storeSku.Ctime, k)
|
||||
}
|
||||
// 没查询到主品创建记录,创建主品
|
||||
if copyMap[storeSku.AppFoodCode] == nil || copyMap[storeSku.AppFoodCode].MainSkuId == "" {
|
||||
param := &product_addV2_request.ProductAddV2Param{
|
||||
Name: utils.LimitUTF8StringLen(storeSku.Name, 90),
|
||||
PayType: tiktok_api.TiktokPayType1,
|
||||
ReduceType: tiktok_api.SkuReduceTypePayMakeOrder,
|
||||
DeliveryDelayDay: tiktok_api.DeliveryDelayDayToDay,
|
||||
PresellType: tiktok_api.SendGoodsTypeNow,
|
||||
Supply7dayReturn: 0, // 是否支持7天无理由,0不支持,1支持,2支持(拆封后不支持)
|
||||
Mobile: toStoreDetail.Tel1,
|
||||
Commit: true,
|
||||
//Specs: "重量|" + utils.Float64ToStr(float64(storeSku.SpecQuality)) + storeSku.SpecUnit,
|
||||
NeedRechargeMode: false,
|
||||
SellChannel: []int64{0},
|
||||
StartSaleType: 0,
|
||||
PickupMethod: "0",
|
||||
OuterProductId: storeSku.AppFoodCode, // 本地skuId为外部商品id
|
||||
}
|
||||
specs := "重量|"
|
||||
specsList := make([]string, 0, 0)
|
||||
upc := ""
|
||||
for _, sl := range storeSku.SkuList {
|
||||
specsList = append(specsList, strings.Split(sl.Spec, "*")[0])
|
||||
param.Weight = utils.Str2Float64(sl.Weight)
|
||||
upc = sl.Upc
|
||||
}
|
||||
param.Specs = specs + strings.Join(specsList, ",")
|
||||
// 获取上传图,商品轮播图
|
||||
imgs := make([]tiktok_api.Imgs, 0, 0)
|
||||
for spk, spl := range storeSku.PictureList {
|
||||
switch spk {
|
||||
case 0:
|
||||
imgs = append(imgs, tiktok_api.Imgs{
|
||||
Name: "white_" + utils.Int2Str(toStoreDetail.ID) + "_" + spl[21:54],
|
||||
Url: spl,
|
||||
})
|
||||
case len(storeSku.PictureList) - 1:
|
||||
imgs = append(imgs, tiktok_api.Imgs{
|
||||
Name: "detail_" + utils.Int2Str(toStoreDetail.ID) + "_" + spl[21:54],
|
||||
Url: spl,
|
||||
})
|
||||
default:
|
||||
imgs = append(imgs, tiktok_api.Imgs{
|
||||
Name: utils.Int2Str(toStoreDetail.ID) + "_" + spl[21:54],
|
||||
Url: spl,
|
||||
})
|
||||
}
|
||||
}
|
||||
tiktokImgList, err := toApi.BatchUploadImages(imgs)
|
||||
if err != nil {
|
||||
errList = append(errList, &mtwmapi.AppFoodResult{
|
||||
AppFoodCode: storeSku.AppFoodCode,
|
||||
ErrorMsg: fmt.Sprintf("%s:%s,图片上传错误", storeSku.Name, err.Error()),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
picList := make([]string, 0, 0)
|
||||
for til, v := range tiktokImgList {
|
||||
if strings.Contains(til, "detail_") {
|
||||
param.Description = v.ByteUrl
|
||||
continue
|
||||
}
|
||||
if strings.Contains(til, "white_") {
|
||||
param.WhiteBackGroundPicUrl = v.ByteUrl
|
||||
}
|
||||
picList = append(picList, v.ByteUrl)
|
||||
}
|
||||
param.Pic = strings.Join(picList, "|")
|
||||
|
||||
// 自动推导分类id
|
||||
if len(param.Pic) != 0 {
|
||||
var vendorCategoryId int64 = 0
|
||||
// 根据图片推导分类
|
||||
picList = append(picList, param.WhiteBackGroundPicUrl, param.Description)
|
||||
vendorCategoryId, _ = toApi.GetRecommendCategory(picList)
|
||||
// 根据名字推导分类
|
||||
if vendorCategoryId == 0 {
|
||||
vendorCategoryId, _ = toApi.GetRecommendCategoryByName(param.Name)
|
||||
}
|
||||
if vendorCategoryId == 0 || err != nil {
|
||||
errList = append(errList, &mtwmapi.AppFoodResult{
|
||||
AppFoodCode: storeSku.AppFoodCode,
|
||||
ErrorMsg: fmt.Sprintf("%s:%s,自动推导分类错误", storeSku.Name, err.Error()),
|
||||
})
|
||||
continue
|
||||
}
|
||||
param.CategoryLeafId = vendorCategoryId
|
||||
}
|
||||
|
||||
// 是否支持七天无理由
|
||||
if toApi.GetProductUpdateRule(param.CategoryLeafId) {
|
||||
param.Supply7dayReturn = 1
|
||||
} else {
|
||||
param.Supply7dayReturn = 0
|
||||
}
|
||||
|
||||
// weight_unit 目前抖音只支持g和kg两种
|
||||
param.WeightUnit = tiktok_api.WeightUint_G
|
||||
|
||||
// spec_prices
|
||||
//param.SpecPrices = GetSpecPrices(param.Specs, vendorStoreID, 0, storeSku)
|
||||
skuSize := make([]*tiktok_api.SpecDetailList, 0, 0)
|
||||
name1 := strings.Split(strings.Split(param.Specs, "|")[1], ",")
|
||||
for _, sl := range storeSku.SkuList {
|
||||
for i := 0; i < len(name1); i++ {
|
||||
if name1[i] == strings.Split(sl.Spec, "*")[0] {
|
||||
sku := &tiktok_api.SpecDetailList{
|
||||
SpecDetailName1: name1[i],
|
||||
Price: utils.Float64TwoInt(utils.Str2Float64(sl.Price)),
|
||||
Code: storeSku.AppFoodCode + fmt.Sprintf("_%d", i),
|
||||
StepStockNum: 0,
|
||||
SupplierID: "",
|
||||
OuterSkuID: storeSku.AppFoodCode + fmt.Sprintf("_%d", i),
|
||||
}
|
||||
|
||||
sku.DeliveryInfos = []*tiktok_api.DeliveryInfos{
|
||||
{InfoType: "weight", InfoUnit: name1[i][len(name1[i])-1:], InfoValue: name1[i]},
|
||||
}
|
||||
sku.StockNum = utils.Str2Int(sl.Stock)
|
||||
sku.SkuType = 1
|
||||
sku.StockNumMap = map[string]int64{toStoreDetail.VendorStoreID: int64(sku.StockNum)}
|
||||
skuSize = append(skuSize, sku)
|
||||
}
|
||||
}
|
||||
}
|
||||
data, _ := json.Marshal(skuSize)
|
||||
param.SpecPrices = string(data)
|
||||
|
||||
// 获取商品的属性
|
||||
//param.ProductFormatNew, param.StandardBrandId, err = MakeProductFormatNew(api, int64(storeSku.NameID), param.CategoryLeafId, storeSku.Upc, storeSku.UpcBrandName, storeSku.UpcTiktokBrandId)
|
||||
if upc == "" {
|
||||
param.StandardBrandId = 596120136
|
||||
} else {
|
||||
brandName, err := tiktok_store.GetBrandByBrandName(upc)
|
||||
if err != nil {
|
||||
param.StandardBrandId = 596120136
|
||||
} else {
|
||||
if strings.Contains(brandName, "/") || strings.Contains(brandName, "(") || strings.Contains(brandName, "(") {
|
||||
brandName = strings.Split(brandName, "/")[0]
|
||||
}
|
||||
if strings.Contains(brandName, "(") {
|
||||
brandName = strings.Split(brandName, "(")[0]
|
||||
}
|
||||
if strings.Contains(brandName, "(") {
|
||||
brandName = strings.Split(brandName, "(")[0]
|
||||
}
|
||||
standardBrandId, err := toApi.GetSkuBrand(param.CategoryLeafId, brandName)
|
||||
if err != nil {
|
||||
param.StandardBrandId = 596120136
|
||||
} else {
|
||||
param.StandardBrandId = standardBrandId
|
||||
}
|
||||
}
|
||||
}
|
||||
if param.StandardBrandId == 0 {
|
||||
param.StandardBrandId = 596120136
|
||||
}
|
||||
categoryList, err := toApi.GetCatePropertyV2(param.CategoryLeafId)
|
||||
if err != nil {
|
||||
errList = append(errList, &mtwmapi.AppFoodResult{
|
||||
AppFoodCode: storeSku.AppFoodCode,
|
||||
ErrorMsg: fmt.Sprintf("%s:%s,根据商品分类推导属性错误", storeSku.Name, err.Error()),
|
||||
})
|
||||
continue
|
||||
}
|
||||
categoryMap := make(map[string][]map[string]interface{})
|
||||
for _, v := range categoryList.Data.Data {
|
||||
if v.Required != model.YES {
|
||||
continue
|
||||
}
|
||||
options := make([]map[string]interface{}, 0)
|
||||
if v.PropertyName == "品牌" {
|
||||
options = append(options, map[string]interface{}{"name": v.PropertyName, "value": param.StandardBrandId, "diy_type": v.DiyType})
|
||||
categoryMap[utils.Int64ToStr(v.PropertyId)] = options
|
||||
} else if v.PropertyName == "产地" {
|
||||
options = append(options, map[string]interface{}{"name": v.PropertyName, "value": 13850, "diy_type": v.DiyType})
|
||||
categoryMap[utils.Int64ToStr(v.PropertyId)] = options
|
||||
} else if len(options) == 0 {
|
||||
options = append(options, map[string]interface{}{"name": v.PropertyName, "value": 0, "diy_type": v.DiyType})
|
||||
categoryMap[utils.Int64ToStr(v.PropertyId)] = options
|
||||
} else {
|
||||
options = append(options, map[string]interface{}{"name": v.PropertyName, "value": v.Options[0].Value, "diy_type": v.DiyType})
|
||||
categoryMap[utils.Int64ToStr(v.PropertyId)] = options
|
||||
}
|
||||
}
|
||||
|
||||
param.ProductFormatNew = utils.Format4Output(categoryMap, false)
|
||||
//param.ProductFormatNew, err = MakeProductFormatNew(api, int64(storeSku.NameID), param.CategoryLeafId)
|
||||
if StoreTemp[toStoreDetail.VendorStoreID] != "" {
|
||||
idList := strings.Split(StoreTemp[toStoreDetail.VendorStoreID], "_")
|
||||
param.FreightId, param.SaleLimitId = utils.Str2Int64(idList[0]), utils.Str2Int64(idList[1])
|
||||
} else {
|
||||
// 运费模板
|
||||
param.FreightId, err = tiktok_store.GetDeliveryTemp(toApi, toStoreDetail.VendorStoreID, toStoreDetail)
|
||||
if err != nil {
|
||||
errList = append(errList, &mtwmapi.AppFoodResult{
|
||||
AppFoodCode: storeSku.AppFoodCode,
|
||||
ErrorMsg: fmt.Sprintf("%s:%s,运费模版获取错误", storeSku.Name, err.Error()),
|
||||
})
|
||||
return errList, nil
|
||||
}
|
||||
// 获取门店限售模板
|
||||
param.SaleLimitId, err = tiktok_store.CreateSaleTemp(utils.Str2Int64(toStoreDetail.VendorStoreID), toApi)
|
||||
if err != nil {
|
||||
errList = append(errList, &mtwmapi.AppFoodResult{
|
||||
AppFoodCode: storeSku.AppFoodCode,
|
||||
ErrorMsg: fmt.Sprintf("%s:%s,限售模版获取错误", storeSku.Name, err.Error()),
|
||||
})
|
||||
return errList, nil
|
||||
}
|
||||
StoreTemp[toStoreDetail.VendorStoreID] = fmt.Sprintf("%d_%d", param.FreightId, param.SaleLimitId)
|
||||
}
|
||||
|
||||
tiktokResult, errCreate := toApi.CreateStoreCommodity(param) // 创建主商品,同步主商品
|
||||
copyData := &model.CopyVendorSku{
|
||||
FromSkuID: storeSku.AppPoiCode,
|
||||
FromSkuName: storeSku.Name,
|
||||
FromStoreId: fromStoreId,
|
||||
FromVendorId: model.VendorIDMTWM,
|
||||
ToStoreId: toStoreDetail.VendorStoreID,
|
||||
ToVendorId: model.VendorIDDD,
|
||||
MainSkuId: "",
|
||||
ChildrenSkuId: "",
|
||||
ErrMsg: "",
|
||||
}
|
||||
if errCreate != nil {
|
||||
copyData.ErrMsg = errCreate.Error()
|
||||
}
|
||||
if tiktokResult.ProductId != 0 {
|
||||
copyData.MainSkuId = utils.Int64ToStr(tiktokResult.ProductId)
|
||||
}
|
||||
dao.CreateEntity(db, copyData)
|
||||
} else {
|
||||
// 主商品存在,直接同步子商品
|
||||
childrenProductId, err := toApi.CreateSubProduct(utils.Str2Int64(copyMap[storeSku.AppPoiCode].MainSkuId), utils.Str2Int64(toStoreDetail.VendorStoreID))
|
||||
// 2010004:主商品非在线审核通过状态,不允许绑定子商品
|
||||
if err != nil && strings.Contains(err.Error(), "2010004") {
|
||||
// 线上本地都存在,但是线上审核不成功,就去更新主商品
|
||||
copyMap[storeSku.AppPoiCode].ErrMsg = err.Error()
|
||||
dao.UpdateEntity(db, copyMap[storeSku.AppPoiCode], "ErrMsg")
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil && strings.Contains(err.Error(), "2010001") { // 2010001:重复创建渠道商品
|
||||
storeSkuDetail, err := toApi.GetSkuDetailLocalID(toStoreDetail.VendorStoreID, storeSku.AppFoodCode)
|
||||
if err != nil {
|
||||
copyMap[storeSku.AppPoiCode].ErrMsg = err.Error()
|
||||
dao.UpdateEntity(db, copyMap[storeSku.AppPoiCode], "ErrMsg")
|
||||
continue
|
||||
}
|
||||
childrenProductId = storeSkuDetail.ProductId
|
||||
copyMap[storeSku.AppPoiCode].ChildrenSkuId = utils.Int64ToStr(childrenProductId)
|
||||
dao.UpdateEntity(db, copyMap[storeSku.AppPoiCode], "ChildrenSkuId")
|
||||
}
|
||||
|
||||
if childrenProductId != model.NO {
|
||||
// 同步价格,库存,上架
|
||||
//childrenDetail, err := toApi.GetSkuDetail(utils.Int64ToStr(childrenProductId), "")
|
||||
//if err != nil {
|
||||
// copyMap[storeSku.AppPoiCode].ErrMsg = err.Error()
|
||||
// dao.UpdateEntity(db, copyMap[storeSku.AppPoiCode], "ErrMsg")
|
||||
// continue
|
||||
//}
|
||||
//for _, v := range childrenDetail.SpecPrices {
|
||||
// childrenSkuId := v.SkuId
|
||||
// storeSku.VendorSonSkuID = utils.Int64ToStr(childrenSkuId)
|
||||
// return childrenSkuId, nil
|
||||
//}
|
||||
//failedList2 := upDateChildrenPriceStockLaunch(api, storeSku, childrenProductId, vendorStoreID, syncType)
|
||||
if err := toApi.LaunchProduct(childrenProductId); err != nil {
|
||||
copyMap[storeSku.AppPoiCode].ErrMsg = "上架失败" + err.Error()
|
||||
dao.UpdateEntity(db, copyMap[storeSku.AppPoiCode], "ChildrenSkuId")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errList, nil
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 美团同步到饿百
|
||||
|
||||
// CopyMtToEBai 复制美团商品到饿百
|
||||
func CopyMtToEBai(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail, isAsync bool, offSet int) (hint string, data []string, err error) {
|
||||
VendorCategoryIDMap := map[string]int64{}
|
||||
var fromApi *mtwmapi.API //= mtwm.GetAPI(fromStore.VendorOrgCode, fromStore.ID, fromStore.VendorStoreID)
|
||||
var ebaiApi = api.EbaiAPI
|
||||
var errListData = make([]string, 0, 0)
|
||||
if fromStore.VendorOrgCode == globals.Mtwm2Code {
|
||||
fromApi = mtwmapi.New(beego.AppConfig.DefaultString("mtwmAppID2", ""), beego.AppConfig.DefaultString("mtwmSecret2", ""), beego.AppConfig.DefaultString("mtwmCallbackURL2", ""), "")
|
||||
fromApi.SetToken(fromStore.MtwmToken)
|
||||
} else {
|
||||
fromApi = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, fromStore.VendorOrgCode).(*mtwmapi.API)
|
||||
}
|
||||
|
||||
taskName := fmt.Sprintf("将美团平台门店[%s],分类和商品复制到饿百[%s]", fromStore.VendorStoreID, toStore.VendorStoreID)
|
||||
config := tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(false)
|
||||
work := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
step := batchItemList[0].(int)
|
||||
switch step {
|
||||
case 1:
|
||||
// 1.加载门店商品,删除商品.当分类下没有商品时.删除分类
|
||||
//errs := LoadingStoreSkuList(ctx, toApi, toStore.VendorStoreID)
|
||||
// errs := LoadingStoreSkuList(ctx, toApi, toStore.VendorStoreID)
|
||||
//if errs != nil && len(errs) > 0 {
|
||||
// return nil, errs[0]
|
||||
//}
|
||||
case 2:
|
||||
//同步分类
|
||||
fromCategoryList, err := fromApi.RetailCatList(fromStore.VendorStoreID)
|
||||
if len(fromCategoryList) == model.NO {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range fromCategoryList {
|
||||
parentID, categoryErr := ebaiApi.ShopCategoryCreate(utils.Int2Str(toStore.ID), 0, v.Name, len(fromCategoryList)-k)
|
||||
if categoryErr != nil {
|
||||
globals.SugarLogger.Debugf("err := RetailCatUpdate : %v", categoryErr)
|
||||
continue
|
||||
}
|
||||
if v.Code == "" {
|
||||
VendorCategoryIDMap[v.Name] = parentID
|
||||
} else {
|
||||
VendorCategoryIDMap[v.Code] = parentID
|
||||
}
|
||||
if v.Children != nil && len(v.Children) != 0 {
|
||||
for _, c := range v.Children {
|
||||
childrenCateId, err := ebaiApi.ShopCategoryCreate(utils.Int2Str(toStore.ID), parentID, c.Name, len(v.Children)-k)
|
||||
if err != nil {
|
||||
globals.SugarLogger.Debugf("err := RetailCatUpdate Children : %v", err)
|
||||
continue
|
||||
}
|
||||
if c.Code == "" {
|
||||
VendorCategoryIDMap[c.Name] = childrenCateId
|
||||
} else {
|
||||
VendorCategoryIDMap[c.Code] = childrenCateId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
i := offSet
|
||||
for {
|
||||
// 同步商品
|
||||
fromFoodList, err1 := fromApi.RetailListAll(fromStore.VendorStoreID, i)
|
||||
if len(fromFoodList) == 0 || fromFoodList == nil {
|
||||
return nil, fmt.Errorf("fromFoodList 为空 %s ,i:= %d", utils.Format4Output(err1, false), i)
|
||||
}
|
||||
errList := BatchInitSkuMtwm2EBai(ctx, fromFoodList, ebaiApi, utils.Int2Str(toStore.ID), VendorCategoryIDMap)
|
||||
if errList != nil {
|
||||
for _, err2 := range errList {
|
||||
errListData = append(errListData, err2.Error())
|
||||
}
|
||||
globals.SugarLogger.Debugf("BatchInitData : %s", utils.Format4Output(errList, false))
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
task := tasksch.NewParallelTask(taskName, config, ctx, work, []int{1, 2, 3})
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
hint = "1"
|
||||
} else {
|
||||
hint = task.ID
|
||||
}
|
||||
return hint, errListData, err
|
||||
}
|
||||
|
||||
// BatchInitSkuMtwm2EBai 批量创建商品美团到饿百
|
||||
func BatchInitSkuMtwm2EBai(ctx *jxcontext.Context, fromSku []*mtwmapi.AppFood, toApi *ebaiapi.API, storeID string, VendorCategoryIDMap map[string]int64) []error {
|
||||
var errList = make([]error, 0, 0)
|
||||
for k, storeSku := range fromSku {
|
||||
params := map[string]interface{}{}
|
||||
|
||||
photos := []map[string]interface{}{}
|
||||
for _, img := range storeSku.PictureList {
|
||||
imgEbai, _ := api.EbaiAPI.PictureUpload(img, nil)
|
||||
if k == 0 {
|
||||
photos = append(photos, map[string]interface{}{
|
||||
"is_master": 1,
|
||||
"url": imgEbai,
|
||||
})
|
||||
} else {
|
||||
photos = append(photos, map[string]interface{}{
|
||||
"is_master": 0,
|
||||
"url": imgEbai,
|
||||
})
|
||||
}
|
||||
}
|
||||
params["photos"] = photos
|
||||
params["weight"] = storeSku.SkuList[0].Weight
|
||||
params["weight"] = storeSku.SkuList[0].Weight
|
||||
params["upc"] = storeSku.SkuList[0].Upc
|
||||
params["name"] = storeSku.Name
|
||||
//params["cat3_id"] = storeSku.CateId
|
||||
if storeSku.CategoryCode != "" {
|
||||
params["category_id"] = VendorCategoryIDMap[storeSku.CategoryCode]
|
||||
} else {
|
||||
params["category_id"] = VendorCategoryIDMap[storeSku.Name]
|
||||
}
|
||||
if storeSku.PictureContents != "" {
|
||||
params["desc"] = storeSku.PictureContents
|
||||
}
|
||||
params["left_num"] = storeSku.SkuList[0].Stock
|
||||
params["process_type"] = 0 // 是否支持加工服务0-不支持/1-支持
|
||||
//params["process_detail"] = storeSku.ProcessDetail
|
||||
params["sale_price"] = jxutils.StandardPrice2Int(utils.Str2Float64(storeSku.SkuList[0].Price))
|
||||
if storeSku.IsSoldOut == 1 {
|
||||
params["status"] = 0
|
||||
} else {
|
||||
params["status"] = 1
|
||||
}
|
||||
//params["minimum"] = storeSku.Minimum
|
||||
//params["seven_days_no_reason"] = storeSku.SevenDaysNoReason
|
||||
//if len(storeSku.SkuProperty) != model.NO {
|
||||
// params["sku_property"] = storeSku.SkuProperty
|
||||
//}
|
||||
customSkuID := int64(storeSku.Ctime + k)
|
||||
_, err := toApi.SkuCreate(ctx.GetTrackInfo(), storeID, customSkuID, params)
|
||||
if err != nil {
|
||||
errList = append(errList, err)
|
||||
}
|
||||
}
|
||||
|
||||
return errList
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 饿百同步到美团
|
||||
|
||||
func CopyEBaiToMt(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail, isAsync bool, offSet int) (hint string, errList []string, err error) {
|
||||
var api = api.EbaiAPI
|
||||
var toApi *mtwmapi.API
|
||||
if toStore.VendorOrgCode == globals.Mtwm2Code {
|
||||
toApi = mtwmapi.New(beego.AppConfig.DefaultString("mtwmAppID2", ""), beego.AppConfig.DefaultString("mtwmSecret2", ""), beego.AppConfig.DefaultString("mtwmCallbackURL2", ""), "")
|
||||
toApi.SetToken(toStore.MtwmToken)
|
||||
} else {
|
||||
toApi = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, toStore.VendorOrgCode).(*mtwmapi.API)
|
||||
}
|
||||
|
||||
taskName := fmt.Sprintf("将美团平台门店[%s],分类和商品复制到[%s]", fromStore.VendorStoreID, toStore.VendorStoreID)
|
||||
config := tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(false)
|
||||
work := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
step := batchItemList[0].(int)
|
||||
switch step {
|
||||
case 1:
|
||||
//同步分类
|
||||
fromCategoryList, err := api.ShopCategoryGet(utils.Int2Str(fromStore.ID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range fromCategoryList {
|
||||
categoryErr := toApi.RetailCatUpdate(toStore.VendorStoreID, v.Name, &mtwmapi.Param4UpdateCat{
|
||||
CategoryCode: utils.Int64ToStr(v.CategoryID),
|
||||
Sequence: v.Rank,
|
||||
})
|
||||
if categoryErr != nil {
|
||||
globals.SugarLogger.Debugf("err := RetailCatUpdate : %v", categoryErr)
|
||||
}
|
||||
if v.Children != nil && len(v.Children) != 0 {
|
||||
for _, c := range v.Children {
|
||||
if err3 := toApi.RetailCatUpdate(toStore.VendorStoreID, v.Name, &mtwmapi.Param4UpdateCat{
|
||||
CategoryNameOrigin: v.Name,
|
||||
SecondaryCategoryCode: utils.Int64ToStr(c.CategoryID),
|
||||
SecondaryCategoryName: c.Name,
|
||||
Sequence: c.Rank,
|
||||
}); err3 != nil {
|
||||
globals.SugarLogger.Debugf("err := RetailCatUpdate Children : %v", err3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
i := offSet
|
||||
for {
|
||||
// 同步商品
|
||||
fromFoodList, err1 := api.SkuList(utils.Int2Str(fromStore.ID), &ebaiapi.SkuListParams{
|
||||
Page: i,
|
||||
})
|
||||
if len(fromFoodList.List) == 0 || fromFoodList == nil {
|
||||
return nil, fmt.Errorf("fromFoodList 为空 %s ,i:= %d", utils.Format4Output(err1, false), i)
|
||||
}
|
||||
|
||||
errDataList, err := BatchInitSkuEBai2Mt(ctx, fromFoodList.List, toApi, toStore.VendorStoreID, i)
|
||||
if err != nil {
|
||||
globals.SugarLogger.Debugf("BatchInitData : %v", err)
|
||||
}
|
||||
if len(errDataList) > model.NO {
|
||||
globals.SugarLogger.Debugf("errListData %d:= %s", i, utils.Format4Output(errDataList, false))
|
||||
for _, v := range errDataList {
|
||||
errList = append(errList, fmt.Sprintf("%s,%s", v.AppFoodCode, v.ErrorMsg))
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Debugf("==========页数[%d],数据长度[%d]", i, len(fromFoodList.List))
|
||||
if len(fromFoodList.List) < 100 {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
task := tasksch.NewParallelTask(taskName, config, ctx, work, []int{1, 2})
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
if !isAsync {
|
||||
_, err = task.GetResult(0)
|
||||
hint = "1"
|
||||
} else {
|
||||
hint = task.ID
|
||||
}
|
||||
|
||||
globals.SugarLogger.Debugf("======errrList := %s", utils.Format4Output(errList, false))
|
||||
return hint, errList, err
|
||||
|
||||
}
|
||||
|
||||
func BatchInitSkuEBai2Mt(ctx *jxcontext.Context, fromSku []*ebaiapi.SkuInfo, toApi *mtwmapi.API, vendorStoreID string, offset int) ([]*mtwmapi.AppFoodResult, error) {
|
||||
errList := make([]*mtwmapi.AppFoodResult, 0, 0)
|
||||
foodDataList := make([]map[string]interface{}, len(fromSku))
|
||||
isNeedUpdatePrice := true
|
||||
for i, storeSku := range fromSku {
|
||||
foodData := make(map[string]interface{})
|
||||
foodDataList[i] = foodData
|
||||
if storeSku.CustomSkuId != "" {
|
||||
foodData[mtwmapi.KeyAppFoodCode] = storeSku.CustomSkuId
|
||||
} else {
|
||||
foodData[mtwmapi.KeyAppFoodCode] = storeSku.SkuId
|
||||
}
|
||||
skus := []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"sku_id": foodData[mtwmapi.KeyAppFoodCode],
|
||||
},
|
||||
}
|
||||
foodData["skus"] = skus
|
||||
foodData["name"] = utils.LimitUTF8StringLen(storeSku.Name, mtwmapi.MaxSkuNameCharCount)
|
||||
//foodData["description"] = storeSku.Comment
|
||||
if isNeedUpdatePrice {
|
||||
foodData["price"] = jxutils.IntPrice2Standard(int64(storeSku.SalePrice))
|
||||
}
|
||||
if storeSku.Minimum != 0 {
|
||||
foodData["min_order_count"] = storeSku.Minimum
|
||||
} else {
|
||||
foodData["min_order_count"] = 1
|
||||
}
|
||||
foodData["unit"] = "份"
|
||||
//todo 增加商品必填属性
|
||||
attr := mtwm.SwitchAttr(toApi, vendorStoreID, 0, 0, storeSku.Name)
|
||||
if attr != "" {
|
||||
foodData["common_attr_value"] = attr
|
||||
}
|
||||
//if storeSku.SellPoint != "" {// 卖点
|
||||
// foodData["sell_point"] = storeSku.SellPoint
|
||||
//}
|
||||
//if storeSku.SellPointTimes != "" {// 卖点展示期
|
||||
// foodData["sell_point_available_times"] = storeSku.SellPointTimes
|
||||
//}
|
||||
if storeSku.CateId2 != 0 {
|
||||
foodData["category_code"] = storeSku.CateId2
|
||||
} else {
|
||||
foodData["category_name"] = storeSku.CateName2
|
||||
}
|
||||
if storeSku.Status == "" {
|
||||
foodData["is_sold_out"] = 0
|
||||
} else {
|
||||
foodData["is_sold_out"] = 1
|
||||
}
|
||||
photos := make([]string, 0, len(storeSku.Photos))
|
||||
for _, v := range storeSku.Photos {
|
||||
photos = append(photos, v.Url)
|
||||
}
|
||||
foodData["picture"] = strings.Join(photos, ",")
|
||||
if storeSku.Rtf != "" {
|
||||
foodData["picture_contents"] = storeSku.Rtf
|
||||
}
|
||||
|
||||
//if storeSku.QuaPictures != "" {
|
||||
// foodData["qua_pictures"] = storeSku.QuaPictures
|
||||
// foodData["qua_effective_date"] = storeSku.QuaEffectiveDate
|
||||
// foodData["qua_approval_date"] = storeSku.QuaApprovalDate
|
||||
//}
|
||||
|
||||
// 周期性可售时间段
|
||||
//if storeSku.StatusSaleBegin != model.NO && storeSku.StatusSaleEnd != model.NO {
|
||||
// saleStart := utils.Int2Str(int(storeSku.StatusSaleBegin))
|
||||
// saleEnd := utils.Int2Str(int(storeSku.StatusSaleEnd))
|
||||
// for {
|
||||
// if len(saleStart) != 4 {
|
||||
// saleStart = "0" + saleStart
|
||||
// }
|
||||
// if len(saleEnd) != 4 {
|
||||
// saleEnd += "0" + saleEnd
|
||||
// }
|
||||
// if len(saleEnd) == 4 && len(saleStart) == 4 {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// saleStart = fmt.Sprintf("%s:%s", saleStart[:2], saleStart[2:])
|
||||
// saleEnd = fmt.Sprintf("%s:%s", saleEnd[:2], saleEnd[2:])
|
||||
// availableTimes := fmt.Sprintf("%s-%s", saleStart, saleEnd)
|
||||
// available, _ := json.Marshal(map[string]string{"monday": availableTimes, "tuesday": availableTimes, "wednesday": availableTimes, "thursday": availableTimes, "friday": availableTimes, "saturday": availableTimes, "sunday": availableTimes})
|
||||
// foodData["available_times"] = string(available)
|
||||
//}
|
||||
//foodData["sequence"] = storeSku.GetSeq()
|
||||
if tempCateId, err := toApi.RetailRecommendTag(storeSku.Name, vendorStoreID, 0, mtwmapi.TypeCategory); err == nil {
|
||||
foodData["tag_id"] = int64(tempCateId.TagID)
|
||||
}
|
||||
|
||||
//skus[0]["spec"] = jxutils.ComposeSkuSpec(storeSku.SpecQuality, storeSku.SpecUnit)
|
||||
skus[0]["price"] = utils.Float64ToStr(jxutils.IntPrice2Standard(int64(storeSku.SalePrice)))
|
||||
skus[0]["stock"] = utils.Int2Str(storeSku.LeftNum)
|
||||
skus[0]["upc"] = storeSku.Upc
|
||||
if storeSku.ShelfNumber != "" {
|
||||
skus[0]["location_code"] = storeSku.ShelfNumber
|
||||
}
|
||||
//skus[0]["ladder_box_num"] = "0"
|
||||
//skus[0]["ladder_box_price"] = "0"
|
||||
// 下面这个两个和上面有点重复,但是上面两个在更新的时候美团不识别,不知道创建的时候会不会覆盖一下吧(更新只能用下面这个)
|
||||
skus[0]["box_num"] = "0"
|
||||
skus[0]["box_price"] = "0"
|
||||
if foodData["tag_id"] != nil {
|
||||
skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
count := len(foodDataList) / 10
|
||||
if len(foodDataList)%10 != 0 {
|
||||
count += 1
|
||||
}
|
||||
for i := 0; i < count; i++ {
|
||||
if i == count-1 {
|
||||
failedFoodList, _ := toApi.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList[i*10:])
|
||||
if len(failedFoodList) != 0 {
|
||||
globals.SugarLogger.Debugf("failedFoodList := %s", utils.Format4Output(failedFoodList, false))
|
||||
errList = append(errList, failedFoodList...)
|
||||
}
|
||||
} else {
|
||||
failedFoodList, _ := toApi.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList[i*10:(i+1)*10])
|
||||
if len(failedFoodList) != 0 {
|
||||
globals.SugarLogger.Debugf("failedFoodList := %s", utils.Format4Output(failedFoodList, false))
|
||||
errList = append(errList, failedFoodList...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errList, nil
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#endregion
|
||||
|
||||
////#region 同步活动
|
||||
//
|
||||
//func CopyMtActToMt(ctx *jxcontext.Context, fromStore, toStore *dao.StoreDetail) {
|
||||
|
||||
Reference in New Issue
Block a user