- 清理三个平台的门店商品批处理操作,部分失败返回失败条目

This commit is contained in:
gazebo
2019-07-21 16:08:37 +08:00
parent 0298f7de71
commit 414c359200
12 changed files with 597 additions and 179 deletions

View File

@@ -2,8 +2,11 @@ package ebaiapi
import (
"fmt"
"regexp"
"strings"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/utils"
)
@@ -24,6 +27,10 @@ const (
MaxStoreSkuBatchSize = 100 // sku.offline, sku.online, sku.price.update.batch和sku.stock.update.batch这些批量操作的最大值
)
var (
shopSkuBatchFailedSkuReg = regexp.MustCompile(`请核查以下sku(\{.*\})`)
)
type CategoryInfo struct {
CategoryID int64 `json:"category_id"`
Name string `json:"name"`
@@ -95,10 +102,112 @@ type PageDataInfo struct {
List []*SkuInfo `json:"List"`
}
func genSkuIDParams(skuID int64, customSkuID, upc string) map[string]interface{} {
type ShopSkuPriceUpdateResponseItem struct {
SkuID int64 `json:"sku_id"`
Price int `json:"price"`
ErrorNo int `json:"error_no,omitempty"`
ErrorMsg string `json:"error_msg,omitempty"`
}
type ShopSkuPriceUpdateResponse struct {
FailedList []*ShopSkuPriceUpdateResponseItem `json:"failed_list"`
SuccessList []*ShopSkuPriceUpdateResponseItem `json:"success_list"`
}
const (
SkuIDTypeUnknown = 0
SkuIDTypeSkuID = 1
SkuIDTypeCustomSkuID = 2
SkuIDTypeUpc = 3
)
var (
priceUpdateKeyIDMap = map[int]string{
SkuIDTypeSkuID: "skuid_price",
SkuIDTypeCustomSkuID: "custom_sku_id",
SkuIDTypeUpc: "upc_price",
}
stockUpdateKeyIDMap = map[int]string{
SkuIDTypeSkuID: "skuid_stocks",
SkuIDTypeCustomSkuID: "custom_sku_id",
SkuIDTypeUpc: "upc_stocks",
}
)
type ShopSkuInfo struct {
SkuID int64
CustomSkuID string
Upc string
SalePrice int64
MarketPrice int64
Stock int
}
type ShopSkuInfoList []*ShopSkuInfo
func (v *ShopSkuInfo) GuessIDType() int {
if v.SkuID > 0 {
return SkuIDTypeSkuID
} else if v.CustomSkuID != "" {
return SkuIDTypeCustomSkuID
}
return SkuIDTypeUpc
}
func (v *ShopSkuInfo) ToSkuID(skuIDType int) (str string) {
if skuIDType == SkuIDTypeUnknown {
skuIDType = v.GuessIDType()
}
if skuIDType == SkuIDTypeSkuID {
str = utils.Int64ToStr(v.SkuID)
} else if skuIDType == SkuIDTypeCustomSkuID {
str = v.CustomSkuID
} else {
str = v.Upc
}
return str
}
func (v *ShopSkuInfo) PriceString(skuIDType int) (str string) {
str = v.ToSkuID(skuIDType) + ":" + utils.Int64ToStr(v.SalePrice)
if v.MarketPrice > 0 {
str += "," + utils.Int64ToStr(v.MarketPrice)
}
return str
}
func (v *ShopSkuInfo) StockString(skuIDType int) (str string) {
str = v.ToSkuID(skuIDType) + ":" + utils.Int2Str(v.Stock)
return str
}
func (l ShopSkuInfoList) PriceString(skuIDType int) (str string) {
if len(l) > 0 {
strList := make([]string, len(l))
for k, v := range l {
strList[k] = v.PriceString(skuIDType)
}
str = strings.Join(strList, ";")
}
return str
}
func (l ShopSkuInfoList) StockString(skuIDType int) (str string) {
if len(l) > 0 {
strList := make([]string, len(l))
for k, v := range l {
strList[k] = v.StockString(skuIDType)
}
str = strings.Join(strList, ";")
}
return str
}
func genSkuIDParams(skuIDstr string, customSkuID, upc string) map[string]interface{} {
params := map[string]interface{}{}
if skuID != 0 {
params[KeySkuID] = skuID
if skuIDstr != "" {
params[KeySkuID] = skuIDstr
} else if customSkuID != "" {
params[KeyCustomSkuID] = customSkuID
} else if upc != "" {
@@ -216,100 +325,123 @@ func (a *API) SkuUpdate(shopID string, ebaiSkuID int64, params map[string]interf
return 0, err
}
func (a *API) SkuDelete(shopID, skuIDsStr string) (err error) {
params := map[string]interface{}{
KeyShopID: shopID,
KeySkuID: skuIDsStr,
}
_, err = a.AccessAPI("sku.delete", params)
return err
func intIDs2Str(intIDs []int64) (str string) {
return strings.Join(utils.Int64Slice2String(intIDs), ",")
}
func (a *API) SkuDeleteByCustomIDs(shopID, customSkuIDsStr string) (err error) {
params := map[string]interface{}{
KeyShopID: shopID,
KeyCustomSkuID: customSkuIDsStr,
}
_, err = a.AccessAPI("sku.delete", params)
return err
func strIDs2Str(strIDs []string) (str string) {
return strings.Join(strIDs, ",")
}
func (a *API) SkuOnline(shopID, skuIDsStr string) (err error) {
params := map[string]interface{}{
KeyShopID: shopID,
KeySkuID: skuIDsStr,
func handleShopSkuBatchResult(result *ResponseResult) (failedSkuIDs []int64, err error) {
if dataStr, ok := result.Data.(string); ok && dataStr != "" {
matchList := shopSkuBatchFailedSkuReg.FindStringSubmatch(dataStr)
if len(matchList) == 2 {
var failedMap map[string]interface{}
if err = utils.UnmarshalUseNumber([]byte(matchList[1]), &failedMap); err == nil && len(failedMap) > 0 {
for _, v := range failedMap {
if vStr, ok := v.(string); ok {
failedSkuIDs = append(failedSkuIDs, utils.Str2Int64WithDefault(vStr, 0))
} else {
failedSkuIDs = append(failedSkuIDs, utils.Interface2Int64WithDefault(v, 0))
}
}
}
}
}
_, err = a.AccessAPI("sku.online", params)
return err
return failedSkuIDs, err
}
// 文档上说支持custom_sku_id但实际好像只支持skuid
func (a *API) SkuDelete(shopID string, skuIDs []int64, customSkuDs []string) (failedSkuIDs []int64, err error) {
params := genSkuIDParams(intIDs2Str(skuIDs), strIDs2Str(customSkuDs), "")
params[KeyShopID] = shopID
result, err := a.AccessAPI("sku.delete", params)
if err == nil {
failedSkuIDs, err = handleShopSkuBatchResult(result)
}
return failedSkuIDs, err
}
func (a *API) SkuOnline(shopID string, skuIDs []int64, customSkuDs, upcs []string) (failedSkuIDs []int64, err error) {
params := genSkuIDParams(intIDs2Str(skuIDs), strIDs2Str(customSkuDs), strIDs2Str(upcs))
params[KeyShopID] = shopID
result, err := a.AccessAPI("sku.online", params)
if err == nil {
failedSkuIDs, err = handleShopSkuBatchResult(result)
}
return failedSkuIDs, err
}
func (a *API) SkuOnlineOne(shopID string, skuID int64, customSkuID, upc string) (err error) {
params := genSkuIDParams(skuID, customSkuID, upc)
params := genSkuIDParams(utils.Int64ToStrNoZero(skuID), customSkuID, upc)
params[KeyShopID] = shopID
_, err = a.AccessAPI("sku.online.one", params)
return err
}
func (a *API) SkuOffline(shopID, skuIDsStr string) (err error) {
params := map[string]interface{}{
KeyShopID: shopID,
KeySkuID: skuIDsStr,
func (a *API) SkuOffline(shopID string, skuIDs []int64, customSkuDs, upcs []string) (failedSkuIDs []int64, err error) {
params := genSkuIDParams(intIDs2Str(skuIDs), strIDs2Str(customSkuDs), strIDs2Str(upcs))
params[KeyShopID] = shopID
result, err := a.AccessAPI("sku.offline", params)
if err == nil {
failedSkuIDs, err = handleShopSkuBatchResult(result)
}
_, err = a.AccessAPI("sku.offline", params)
return err
return failedSkuIDs, err
}
func (a *API) SkuOfflineOne(shopID string, skuID int64, customSkuID, upc string) (err error) {
params := genSkuIDParams(skuID, customSkuID, upc)
params := genSkuIDParams(utils.Int64ToStrNoZero(skuID), customSkuID, upc)
params[KeyShopID] = shopID
_, err = a.AccessAPI("sku.offline.one", params)
return err
}
func genSkuPriceParams(isPrice bool, skuPriceStr, customSkuPriceStr, upcPriceStr string) map[string]interface{} {
params := map[string]interface{}{}
skuKey := "skuid_price"
upcKey := "upc_price"
if !isPrice {
skuKey = "skuid_stocks"
upcKey = "upc_stocks"
// 此函数在部分失败时会返回错误全部成功时不会返回明细其它ShopSku批处理操作的的则在部分失败时会返回成功
func (a *API) SkuPriceUpdateBatch(shopID string, priceList ShopSkuInfoList, skuIDType int) (updateResponse *ShopSkuPriceUpdateResponse, err error) {
params := map[string]interface{}{
KeyShopID: shopID,
priceUpdateKeyIDMap[skuIDType]: priceList.PriceString(skuIDType),
}
if skuPriceStr != "" {
params[skuKey] = skuPriceStr
} else if skuPriceStr != "" {
params["custom_sku_id"] = customSkuPriceStr
} else if upcPriceStr != "" {
params[upcKey] = upcPriceStr
} else {
panic("skuPriceStr, customSkuPriceStr and upcPriceStr are all empty!")
}
return params
}
func (a *API) SkuPriceUpdateBatch(shopID, skuPriceStr, customSkuPriceStr, upcPriceStr string) (err error) {
params := genSkuPriceParams(true, skuPriceStr, customSkuPriceStr, upcPriceStr)
params[KeyShopID] = shopID
_, err = a.AccessAPI("sku.price.update.batch", params)
return err
if err != nil {
// 文档上说的详情在data中但其实是在error中...
if errExt, ok := err.(*utils.ErrorWithCode); ok {
baseapi.SugarLogger.Debug(errExt.ErrMsg())
utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &updateResponse)
}
}
return updateResponse, err
}
func (a *API) SkuPriceUpdateOne(shopID, skuPriceStr, customSkuPriceStr, upcPriceStr string) (err error) {
params := genSkuPriceParams(true, skuPriceStr, customSkuPriceStr, upcPriceStr)
params[KeyShopID] = shopID
func (a *API) SkuPriceUpdateOne(shopID string, priceInfo *ShopSkuInfo) (err error) {
skuIDType := priceInfo.GuessIDType()
params := map[string]interface{}{
KeyShopID: shopID,
priceUpdateKeyIDMap[skuIDType]: priceInfo.PriceString(skuIDType),
}
_, err = a.AccessAPI("sku.price.update.one", params)
return err
}
func (a *API) SkuStockUpdateBatch(shopID, skuStockStr, customSkuStockStr, upcStockStr string) (err error) {
params := genSkuPriceParams(false, skuStockStr, customSkuStockStr, upcStockStr)
params[KeyShopID] = shopID
_, err = a.AccessAPI("sku.stock.update.batch", params)
return err
func (a *API) SkuStockUpdateBatch(shopID string, stockList ShopSkuInfoList, skuIDType int) (failedSkuIDs []int64, err error) {
params := map[string]interface{}{
KeyShopID: shopID,
stockUpdateKeyIDMap[skuIDType]: stockList.PriceString(skuIDType),
}
result, err := a.AccessAPI("sku.stock.update.batch", params)
if err == nil {
failedSkuIDs, err = handleShopSkuBatchResult(result)
}
return failedSkuIDs, err
}
func (a *API) SkuStockUpdateOne(shopID, skuStockStr, customSkuStockStr, upcStockStr string) (err error) {
params := genSkuPriceParams(false, skuStockStr, customSkuStockStr, upcStockStr)
params[KeyShopID] = shopID
func (a *API) SkuStockUpdateOne(shopID string, stockInfo *ShopSkuInfo) (err error) {
skuIDType := stockInfo.GuessIDType()
params := map[string]interface{}{
KeyShopID: shopID,
stockUpdateKeyIDMap[skuIDType]: stockInfo.PriceString(skuIDType),
}
_, err = a.AccessAPI("sku.stock.update.one", params)
return err
}

View File

@@ -16,7 +16,7 @@ func TestShopCategoryCreate(t *testing.T) {
}
func TestShopCategoryGet(t *testing.T) {
result, err := api.ShopCategoryGet(testShopID)
result, err := api.ShopCategoryGet("102493")
if err != nil {
t.Fatal(err)
} else {
@@ -48,8 +48,8 @@ func TestSkuGetItemsByCategoryId(t *testing.T) {
}
func TestSkuList(t *testing.T) {
result, err := api.SkuList(testShopID, &SkuListParams{
SkuID: 15579787500720732,
result, err := api.SkuList("102023", &SkuListParams{
// SkuID: 15579787500720732,
})
if err != nil {
t.Fatal(err)
@@ -107,23 +107,82 @@ func TestSkuUpdate(t *testing.T) {
}
}
func TestSkuDelete(t *testing.T) {
err := api.SkuDelete(testShopID, "153922044227304")
if err != nil {
t.Fatal(err)
}
}
func TestSkuDeleteByCustomIDs(t *testing.T) {
err := api.SkuDeleteByCustomIDs(testShopID, "17")
if err != nil {
t.Fatal(err)
}
}
func TestSkuShopCategoryMap(t *testing.T) {
err := api.SkuShopCategoryMap(testShopID, 15378849314129969, "153760472317166")
if err != nil {
t.Fatal(err)
}
}
func TestSkuDelete(t *testing.T) {
failedSkuIDs, err := api.SkuDelete(testShopID, []int64{12345678, 12423432}, nil)
if err != nil {
// t.Fatal(err)
}
t.Log(utils.Format4Output(failedSkuIDs, false))
}
func TestSkuOnline(t *testing.T) {
failedSkuIDs, err := api.SkuOnline(testShopID, []int64{156369111807787, 12345678, 12423432}, nil, nil)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(failedSkuIDs, false))
}
func TestSkuOnlineOne(t *testing.T) {
err := api.SkuOnlineOne(testShopID, 13211, "", "")
if err == nil {
t.Fatal("应该要报错才对")
}
}
func TestSkuOffline(t *testing.T) {
failedSkuIDs, err := api.SkuOffline(testShopID, []int64{156291398007698, 12345678, 12423432}, nil, nil)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(failedSkuIDs, false))
}
func TestSkuPriceUpdateBatch(t *testing.T) {
failedSkuIDs, err := api.SkuPriceUpdateBatch(testShopID, ShopSkuInfoList{
&ShopSkuInfo{
SkuID: 156369111807787,
SalePrice: 100,
},
&ShopSkuInfo{
SkuID: 156369111707770,
SalePrice: 100,
},
&ShopSkuInfo{
SkuID: 12321,
SalePrice: 100,
},
}, SkuIDTypeSkuID)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(failedSkuIDs, false))
}
func TestSkuStockUpdateBatch(t *testing.T) {
failedSkuIDs, err := api.SkuStockUpdateBatch(testShopID, ShopSkuInfoList{
&ShopSkuInfo{
SkuID: 156291398007698,
Stock: 2,
},
&ShopSkuInfo{
SkuID: 13121231,
Stock: 2,
},
&ShopSkuInfo{
SkuID: 12321,
Stock: 2,
},
}, SkuIDTypeSkuID)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(failedSkuIDs, false))
}