- 清理三个平台的门店商品批处理操作,部分失败返回失败条目
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user