From 889ba315c46b21a04c79578b4403ff7c3fbb0a60 Mon Sep 17 00:00:00 2001 From: gazebo Date: Sun, 26 May 2019 22:07:46 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E6=95=B4=E7=90=86storesku=E7=9A=84?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=96=B9=E5=BC=8F=EF=BC=8C=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E4=B8=80=E4=B8=8B=EF=BC=8C=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- business/partner/partner_store_sku.go | 62 ++++++ business/partner/purchase/ebai/store_sku2.go | 192 +++++++++++++++++ business/partner/purchase/mtwm/store_sku2.go | 204 ++++++++++++++++++ .../partner/purchase/weimob/wsc/store_sku2.go | 187 ++++++++++++++++ 4 files changed, 645 insertions(+) create mode 100644 business/partner/partner_store_sku.go create mode 100644 business/partner/purchase/ebai/store_sku2.go create mode 100644 business/partner/purchase/mtwm/store_sku2.go create mode 100644 business/partner/purchase/weimob/wsc/store_sku2.go diff --git a/business/partner/partner_store_sku.go b/business/partner/partner_store_sku.go new file mode 100644 index 000000000..81202cf2e --- /dev/null +++ b/business/partner/partner_store_sku.go @@ -0,0 +1,62 @@ +package partner + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +const ( + FuncCreateStoreSkus = 1 + FuncDeleteStoreSkus = 2 + FuncUpdateStoreSkusStatus = 3 + FuncUpdateStoreSkusPrice = 4 + FuncUpdateStoreSkus = 5 +) + +type BareStoreSkuInfo struct { + SkuID int `json:"skuID,omitempty"` + VendorSkuID string `json:"vendorSkuID,omitempty"` + NameID int `json:"nameID,omitempty"` + VendorNameID string `json:"vendorNameID,omitempty"` + + Price int `json:"prrice,omitempty"` + Status int `json:"status,omitempty"` +} + +type BareStoreSkuInfoList []*BareStoreSkuInfo + +func (l BareStoreSkuInfoList) GetVendorSkuIDList() (vendorSkuIDList []string) { + vendorSkuIDList = make([]string, len(l)) + for k, v := range l { + vendorSkuIDList[k] = v.VendorSkuID + } + return vendorSkuIDList +} + +type BareCategoryInfo struct { + VendorCatID string `json:"vendorCatID"` + + Level int `json:"level"` + Name string `json:"name"` + Seq int `json:"seq,omitempty"` + Children []*BareCategoryInfo `json:"children,omitempty"` +} + +type IPurchasePlatformStoreSkuHandler interface { + GetStoreSkusBatchSize(funcID int) int + + CreateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) + DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*BareStoreSkuInfo) (err error) + UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*BareStoreSkuInfo) (err error) + UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*BareStoreSkuInfo) (err error) +} + +type ISingleStoreStoreSkuHandler interface { + IPurchasePlatformStoreSkuHandler + + ReadStoreCategory(ctx *jxcontext.Context, vendorStoreID string) (cats []*BareCategoryInfo, err error) + CreateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) + UpdateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) + DeleteStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID, vendorCatID string) (err error) + UpdateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) +} diff --git a/business/partner/purchase/ebai/store_sku2.go b/business/partner/purchase/ebai/store_sku2.go new file mode 100644 index 000000000..54f23e1ee --- /dev/null +++ b/business/partner/purchase/ebai/store_sku2.go @@ -0,0 +1,192 @@ +package ebai + +import ( + "fmt" + "strings" + + "git.rosy.net.cn/baseapi/platformapi/ebaiapi" + "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/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +const ( + minBatchSize = 5 // 使用batch相关的API最少的处理数量,因为饿百批处理API的调用频率限制得更低 +) + +// 门店分类 +func (p *PurchaseHandler) ReadStoreCategory(ctx *jxcontext.Context, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { + remoteCats, err := api.EbaiAPI.ShopCategoryGet(vendorStoreID) + if err == nil { + cats = convertVendorCatList(remoteCats) + } + return cats, err +} + +func convertVendorCatList(remoteCats []*ebaiapi.CategoryInfo) (cats []*partner.BareCategoryInfo) { + for _, rCat := range remoteCats { + cat := &partner.BareCategoryInfo{ + VendorCatID: utils.Int64ToStr(rCat.CategoryID), + Name: rCat.Name, + Level: rCat.Level, + Seq: jxCatSeq2Ebai(rCat.Rank), + Children: convertVendorCatList(rCat.Children), + } + cats = append(cats, cat) + } + return cats +} + +func (p *PurchaseHandler) CreateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + var vendorCatID int64 + if globals.EnableEbaiStoreWrite { + vendorCatID, err = api.EbaiAPI.ShopCategoryCreate(vendorStoreID, utils.Str2Int64WithDefault(storeCat.ParentVendorCatID, 0), storeCat.Name, jxCatSeq2Ebai(storeCat.Seq)) + } else { + vendorCatID = jxutils.GenFakeID() + } + storeCat.VendorCatID = utils.Int64ToStr(vendorCatID) + return err +} + +func (p *PurchaseHandler) UpdateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + if globals.EnableEbaiStoreWrite { + err = api.EbaiAPI.ShopCategoryUpdate(vendorStoreID, utils.Str2Int64WithDefault(storeCat.VendorCatID, 0), storeCat.Name, jxCatSeq2Ebai(storeCat.Seq)) + } + return err +} + +func (p *PurchaseHandler) DeleteStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID, vendorCatID string) (err error) { + if globals.EnableEbaiStoreWrite { + err = api.EbaiAPI.ShopCategoryDelete(vendorStoreID, utils.Str2Int64WithDefault(vendorCatID, 0)) + } + return err +} + +// 门店商品 + +// 多门店平台不需要实现这个接口 +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { + storeSku := storeSkuList[0] + if globals.EnableEbaiStoreWrite { + _, err = api.EbaiAPI.SkuUpdate(vendorStoreID, utils.Str2Int64(storeSku.VendorSkuID), genSkuParamsFromStoreSkuInfo2(storeSku)) + } + return err +} + +// 通用 + +func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) int { + return 1 +} + +// 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { + storeSku := storeSkuList[0] + var vendorSkuID int64 + if globals.EnableEbaiStoreWrite { + vendorSkuID, err = api.EbaiAPI.SkuCreate(vendorStoreID, storeSku.SkuID, genSkuParamsFromStoreSkuInfo2(storeSku)) + } else { + vendorSkuID = jxutils.GenFakeID() + } + storeSku.VendorSkuID = utils.Int64ToStr(vendorSkuID) + return err +} + +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + if globals.EnableEbaiStoreWrite { + err = api.EbaiAPI.SkuDelete(vendorStoreID, strings.Join(partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList(), ",")) + } + return err +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + var validSkus, invalidSkus []string + for _, storeSku := range storeSkuList { + if storeSku.Status == model.SkuStatusNormal { + validSkus = append(validSkus, storeSku.VendorSkuID) + } else { + invalidSkus = append(invalidSkus, storeSku.VendorSkuID) + } + } + if globals.EnableEbaiStoreWrite { + if len(invalidSkus) > minBatchSize { + err = api.EbaiAPI.SkuOffline(utils.Int2Str(storeID), strings.Join(invalidSkus, ",")) + } else if len(invalidSkus) > 0 { + for _, v := range invalidSkus { + if err = api.EbaiAPI.SkuOfflineOne(utils.Int2Str(storeID), utils.Str2Int64(v), "", ""); err != nil { + break + } + } + } + if err == nil { + if len(validSkus) > minBatchSize { + err = api.EbaiAPI.SkuOnline(utils.Int2Str(storeID), strings.Join(validSkus, ",")) + } else if len(validSkus) > 0 { + for _, v := range invalidSkus { + if err = api.EbaiAPI.SkuOnlineOne(utils.Int2Str(storeID), utils.Str2Int64(v), "", ""); err != nil { + break + } + } + } + } + } + return err +} + +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + skuPriceList := make([]string, len(storeSkuList)) + for k, v := range storeSkuList { + skuPriceList[k] = fmt.Sprintf("%s:%d", v.VendorSkuID, v.Price) + } + if globals.EnableEbaiStoreWrite { + if len(skuPriceList) > minBatchSize { + err = api.EbaiAPI.SkuPriceUpdateBatch(utils.Int2Str(storeID), strings.Join(skuPriceList, ";"), "", "") + } else { + for _, v := range skuPriceList { + if err = api.EbaiAPI.SkuPriceUpdateOne(utils.Int2Str(storeID), v, "", ""); err != nil { + break + } + } + } + } + return err +} + +func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo) (params map[string]interface{}) { + params = map[string]interface{}{ + "name": storeSku.Name, + "left_num": model.MaxStoreSkuStockQty, + "category_id": utils.Str2Int64(storeSku.VendorCatID), + "predict_cat": 0, // 不使用推荐类目 + "cat1_id": getEbaiCat(storeSku.VendorVendorCatID3, 1), + "cat2_id": getEbaiCat(storeSku.VendorVendorCatID2, 2), + "cat3_id": getEbaiCat(storeSku.VendorVendorCatID, 3), + "weight": storeSku.Weight, + "photos": []map[string]interface{}{ + map[string]interface{}{ + "is_master": true, + "url": storeSku.Img, + }, + }, + } + if storeSku.DescImg != "" { + params["rtf"] = storeSku.DescImg + } + if storeSku.StoreSkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 { + params["sale_price"] = storeSku.Price + params["market_price"] = storeSku.Price + } + if storeSku.StoreSkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 { + params["status"] = jxSkuStatus2Ebai(storeSku.StoreSkuStatus) + } + // todo 饿百如果给的UPC是空要报错,但如果我要删除UPC怎么弄? + if storeSku.Upc != "" { + params["upc"] = storeSku.Upc + } + return params +} diff --git a/business/partner/purchase/mtwm/store_sku2.go b/business/partner/purchase/mtwm/store_sku2.go new file mode 100644 index 000000000..8a69bf309 --- /dev/null +++ b/business/partner/purchase/mtwm/store_sku2.go @@ -0,0 +1,204 @@ +package mtwm + +import ( + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "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/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +// 门店分类 +func (p *PurchaseHandler) ReadStoreCategory(ctx *jxcontext.Context, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { + remoteCats, err := api.MtwmAPI.RetailCatList(vendorStoreID) + if err == nil { + cats = convertVendorCatList(remoteCats) + } + return cats, err +} + +func convertVendorCatList(remoteCats []*mtwmapi.RetailCategoryInfo) (cats []*partner.BareCategoryInfo) { + for _, rCat := range remoteCats { + cat := &partner.BareCategoryInfo{ + VendorCatID: rCat.Name, + Name: rCat.Name, + Level: rCat.Level, + Seq: rCat.Sequence, + Children: convertVendorCatList(rCat.Children), + } + cats = append(cats, cat) + } + return cats +} + +func (p *PurchaseHandler) CreateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + level := 1 + if storeCat.ParentCatName != "" { + level = 2 + } + catName := storeCat.Name + subCatName := "" + originName := "" + if storeCat.StoreCatSyncStatus&model.SyncFlagNewMask == 0 { + originName = storeCat.VendorCatID + } + if level == 2 { + originName = storeCat.ParentCatName + catName = storeCat.ParentCatName + subCatName = storeCat.Name + if storeCat.StoreCatSyncStatus&model.SyncFlagNewMask == 0 { + originName = storeCat.VendorCatID + catName = storeCat.Name + subCatName = "" + } + } + if catName == "" { + panic("catName is empty") + } + globals.SugarLogger.Debugf("mtwm CreateStoreSkuCategory vendorStoreID:%s, originName:%s, catName:%s, subCatName:%s, seq:%d", vendorStoreID, originName, catName, subCatName, storeCat.Seq) + if globals.EnableMtwmStoreWrite { + err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, originName, catName, subCatName, storeCat.Seq) + } + if err == nil { + storeCat.VendorCatID = storeCat.Name + } + return err +} + +func (p *PurchaseHandler) UpdateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + return p.CreateStoreSkuCategory(ctx, vendorStoreID, storeCat) +} + +func (p *PurchaseHandler) DeleteStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID, vendorCatID string) (err error) { + if globals.EnableMtwmStoreWrite { + err = api.MtwmAPI.RetailCatDelete(vendorStoreID, vendorCatID) + } + return err +} + +// 门店商品 + +// 多门店平台不需要实现这个接口 +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { + return p.CreateStoreSkus(ctx, vendorStoreID, storeSkuList) +} + +// 通用 + +func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) int { + return 1 +} + +// 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { + foodDataList := make([]map[string]interface{}, len(storeSkuList)) + for i, storeSku := range storeSkuList { + foodData := make(map[string]interface{}) + foodDataList[i] = foodData + foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(storeSku.SkuID) + skus := []map[string]interface{}{ + map[string]interface{}{ + "sku_id": foodData[mtwmapi.KeyAppFoodCode], + }, + } + foodData["skus"] = skus + foodData["name"] = utils.LimitUTF8StringLen(storeSku.Name, 30) + foodData["description"] = storeSku.Comment + foodData["price"] = storeSku.Price + foodData["min_order_count"] = 1 + foodData["unit"] = storeSku.Unit + foodData["box_num"] = 0 + foodData["box_price"] = 0.0 + foodData["category_name"] = storeSku.VendorCatID + foodData["is_sold_out"] = skuStatusJX2Mtwm(storeSku.StoreSkuStatus) + foodData["picture"] = storeSku.Img + if storeSku.DescImg != "" { + foodData["picture_contents"] = storeSku.DescImg + } + foodData["sequence"] = storeSku.Price + if storeSku.VendorVendorCatID != 0 { + foodData["tag_id"] = utils.Int64ToStr(storeSku.VendorVendorCatID) + } else { + // foodData["tag_id"] = utils.Int64ToStr(defVendorCatID) + } + skus[0]["spec"] = jxutils.ComposeSkuSpec(storeSku.SpecQuality, storeSku.SpecUnit) + skus[0]["price"] = foodData["price"] + skus[0]["stock"] = "*" + skus[0]["upc"] = storeSku.Upc + if foodData["tag_id"] != nil { + skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用 + } + } + if globals.EnableMtwmStoreWrite { + err = api.MtwmAPI.RetailBatchInitData(vendorStoreID, foodDataList) + } + if err == nil { + for _, storeSku := range storeSkuList { + storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) + } + } + return err +} + +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + if globals.EnableMtwmStoreWrite { + if len(storeSkuList) == 1 { + err = api.MtwmAPI.RetailDelete(vendorStoreID, storeSkuList[0].VendorSkuID) + } else { + err = api.MtwmAPI.RetailCatSkuBatchDelete(vendorStoreID, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) + } + } + return ignoreNoAppFoodErr(err) +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + var validSkus, invalidSkus []*mtwmapi.BareStoreFoodInfo + for _, storeSku := range storeSkuList { + skuInfo := &mtwmapi.BareStoreFoodInfo{ + AppFoodCode: storeSku.VendorSkuID, + Skus: []*mtwmapi.BareStoreSkuInfo{ + &mtwmapi.BareStoreSkuInfo{ + SkuID: storeSku.VendorSkuID, + }, + }, + } + if storeSku.Status == model.SkuStatusNormal { + validSkus = append(validSkus, skuInfo) + } else { + invalidSkus = append(invalidSkus, skuInfo) + } + } + if globals.EnableMtwmStoreWrite { + if len(invalidSkus) > 0 { + err = api.MtwmAPI.RetailSkuSellStatus2(vendorStoreID, invalidSkus, 1) + } + if err == nil && len(validSkus) > 0 { + err = api.MtwmAPI.RetailSkuSellStatus2(vendorStoreID, validSkus, 0) + } + } + return err +} + +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + var priceList []*mtwmapi.BareStoreFoodInfo + for _, storeSku := range storeSkuList { + skuInfo := &mtwmapi.BareStoreFoodInfo{ + AppFoodCode: storeSku.VendorSkuID, + Skus: []*mtwmapi.BareStoreSkuInfo{ + &mtwmapi.BareStoreSkuInfo{ + SkuID: storeSku.VendorSkuID, + Price: utils.Int2Str(storeSku.Price), + }, + }, + } + priceList = append(priceList, skuInfo) + } + if globals.EnableMtwmStoreWrite { + err = api.MtwmAPI.RetailSkuPrice(vendorStoreID, priceList) + } + return err +} diff --git a/business/partner/purchase/weimob/wsc/store_sku2.go b/business/partner/purchase/weimob/wsc/store_sku2.go new file mode 100644 index 000000000..20918a921 --- /dev/null +++ b/business/partner/purchase/weimob/wsc/store_sku2.go @@ -0,0 +1,187 @@ +package wsc + +import ( + "fmt" + "math/rand" + + "git.rosy.net.cn/baseapi/platformapi/weimobapi" + "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/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +// 门店分类 +func (p *PurchaseHandler) ReadStoreCategory(ctx *jxcontext.Context, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { + remoteCats, err := api.WeimobAPI.QueryClassifyInfoList() + if err == nil { + cats = convertVendorCatList(remoteCats) + } + return cats, err +} + +func convertVendorCatList(remoteCats []*weimobapi.GoodsClassify) (cats []*partner.BareCategoryInfo) { + for _, rCat := range remoteCats { + cat := &partner.BareCategoryInfo{ + VendorCatID: utils.Int64ToStr(rCat.ClassifyID), + Name: rCat.Title, + Level: rCat.Level, + Seq: 0, + Children: convertVendorCatList(rCat.ChildrenClassify), + } + cats = append(cats, cat) + } + return cats +} + +func (p *PurchaseHandler) CreateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + var vendorCatID int64 + if globals.EnableWscStoreWrite { + vendorCatID, err = api.WeimobAPI.AddClassify(storeCat.Name, utils.Str2Int64WithDefault(storeCat.ParentVendorCatID, 0), "") + } else { + vendorCatID = jxutils.GenFakeID() + } + storeCat.VendorCatID = utils.Int64ToStr(vendorCatID) + return err +} + +func (p *PurchaseHandler) UpdateStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + if globals.EnableWscStoreWrite { + err = api.WeimobAPI.UpdateClassify(utils.Str2Int64WithDefault(storeCat.VendorCatID, 0), storeCat.Name, "") + } + return err +} + +func (p *PurchaseHandler) DeleteStoreSkuCategory(ctx *jxcontext.Context, vendorStoreID, vendorCatID string) (err error) { + if globals.EnableWscStoreWrite { + err = api.WeimobAPI.UpdateClassify(utils.Str2Int64WithDefault(vendorCatID, 0), composeFakeDelName(vendorCatID), "") + } + return err +} + +// 门店商品 + +// 多门店平台不需要实现这个接口 +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { + storeSku := storeSkuList[0] + goodsInfo := genSkuParams(storeSku) + if globals.EnableWscStoreWrite { + _, _, err = api.WeimobAPI.UpdateGoods2(goodsInfo) + } + return err +} + +// 通用 + +func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) int { + return 1 +} + +func genSkuParams(storeSku *dao.StoreSkuSyncInfo) (goodsInfo *weimobapi.PendingSaveGoodsVo) { + outerGoodsCode := utils.Int2Str(storeSku.NameID) + isPutAway := storeSku.StoreSkuStatus == model.SkuStatusNormal + categoryId := storeSku.VendorVendorCatID + if categoryId == 0 { + categoryId = DefVendorCategoryId + } + classifyIdList := []int64{utils.Str2Int64WithDefault(storeSku.VendorCatID, 0)} + if storeSku.SkuVendorCatID != "" { + if int64Value := utils.Str2Int64WithDefault(storeSku.SkuVendorCatID, 0); int64Value > 0 { + classifyIdList = append(classifyIdList, int64Value) + } + } + b2cGoods := []*weimobapi.PendingSaveB2CGoodsVo{ + &weimobapi.PendingSaveB2CGoodsVo{ + FreightTemplateId: DefFreightTemplateId, + DeliveryTypeIdList: []int64{DefDeliveryTypeId}, + B2cGoodsType: weimobapi.GoodsTypeNormal, + }, + } + salePrice := int64(storeSku.Price) + goodsInfo = &weimobapi.PendingSaveGoodsVo{ + Title: storeSku.Name, + OuterGoodsCode: outerGoodsCode, + IsMultiSku: 0, + GoodsImageURL: []string{storeSku.Img}, + InitialSales: 0, + IsPutAway: utils.Bool2Int(!isPutAway), + Sort: int(storeSku.Price), + CategoryID: categoryId, + B2cGoods: b2cGoods, + SkuList: []*weimobapi.PendingSaveSkuVo{ + &weimobapi.PendingSaveSkuVo{ + OuterSkuCode: utils.Int2Str(storeSku.SkuID), + ImageURL: storeSku.Img, + SalePrice: jxutils.IntPrice2Standard(salePrice), + CostPrice: jxutils.IntPrice2Standard(salePrice * 8 / 10), + OriginalPrice: jxutils.IntPrice2Standard(salePrice * 10 / (6 + rand.Int63n(4))), + EditStockNum: 0, + B2cSku: &weimobapi.PendingSaveB2CSkuVo{ + Weight: jxutils.IntWeight2Float(storeSku.Weight), + }, + }, + }, + } + return goodsInfo +} + +// 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (err error) { + storeSku := storeSkuList[0] + goodsInfo := genSkuParams(storeSku) + var goodsID, vendorSkuID int64 + if globals.EnableWscStoreWrite { + var skuMap map[string]int64 + if goodsID, skuMap, err = api.WeimobAPI.AddGoods2(goodsInfo); err == nil { + vendorSkuID = skuMap[utils.Int2Str(storeSku.SkuID)] + } + } else { + goodsID = jxutils.GenFakeID() + vendorSkuID = jxutils.GenFakeID() + } + storeSku.VendorSkuID = utils.Int64ToStr(vendorSkuID) + storeSku.VendorNameID = utils.Int64ToStr(goodsID) + return err +} + +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + storeSku := storeSkuList[0] + goodsID := utils.Str2Int64(storeSku.VendorNameID) + if globals.EnableWscStoreWrite { + if err = api.WeimobAPI.UpdateGoodsShelfStatus([]int64{goodsID}, false); err == nil { + err = api.WeimobAPI.UpdateGoodsTitle(goodsID, composeFakeDelName(storeSku.VendorNameID)) + } else if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.Code() == "1001930300001" { // 商品不存在错 + err = nil // 强制忽略 + } + } + return err +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + var validGoodsIDList, invalidGoodsIDList []int64 + for _, storeSku := range storeSkuList { + if storeSku.Status == model.SkuStatusNormal { + validGoodsIDList = append(validGoodsIDList, utils.Str2Int64(storeSku.VendorSkuID)) + } else { + invalidGoodsIDList = append(invalidGoodsIDList, utils.Str2Int64(storeSku.VendorSkuID)) + } + } + if globals.EnableWscStoreWrite { + if len(validGoodsIDList) > 0 { + err = api.WeimobAPI.UpdateGoodsShelfStatus(validGoodsIDList, true) + } + if err == nil && len(invalidGoodsIDList) > 0 { + err = api.WeimobAPI.UpdateGoodsShelfStatus(invalidGoodsIDList, false) + } + } + return err +} + +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.BareStoreSkuInfo) (err error) { + err = fmt.Errorf("内部错误,微商城不支持UpdateStoreSkusPrice!") + return err +}