- 清理三个平台的门店商品批处理操作,部分失败返回失败条目
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))
|
||||
}
|
||||
|
||||
@@ -207,28 +207,23 @@ func (a *API) AccessAPI(apiStr string, jdParams map[string]interface{}) (retVal
|
||||
}
|
||||
|
||||
func genNoPageResultParser(codeKey, msgKey, resultKey, okCode string) func(data map[string]interface{}) (interface{}, error) {
|
||||
return func(data map[string]interface{}) (interface{}, error) {
|
||||
return func(data map[string]interface{}) (innerData interface{}, err error) {
|
||||
rawInnerCode, ok := data[codeKey]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("genNoPageResultParser codeKey %s can not be found in result:%v", codeKey, data))
|
||||
}
|
||||
innerCode := forceInnerCode2Str(rawInnerCode)
|
||||
errMsg := formatErrorMsg(data[msgKey])
|
||||
if innerCode == okCode && errMsg != "调用订单中心修改承运商接口失败!" { // todo 京东的order/modifySellerDelivery在失败时也返回成功code,临时处理一下
|
||||
if resultKey != "" {
|
||||
if innerData, ok := data[resultKey]; ok {
|
||||
return innerData, nil
|
||||
}
|
||||
baseapi.SugarLogger.Warnf("genNoPageResultParser resultKey %s can not be found in result:%v", resultKey, utils.Format4Output(data, false))
|
||||
return nil, nil // 容错
|
||||
// panic(fmt.Sprintf("genNoPageResultParser resultKey %s can not be found in result:%v", resultKey, data))
|
||||
if resultKey != "" {
|
||||
innerData, _ = data[resultKey]
|
||||
}
|
||||
if innerCode != okCode {
|
||||
errMsg := formatErrorMsg(data[msgKey])
|
||||
if innerCode == ResponseInnerCodePartialFailed {
|
||||
errMsg += ", " + utils.Format4Output(innerData, true)
|
||||
}
|
||||
return nil, nil
|
||||
err = utils.NewErrorCode(errMsg, innerCode, 1)
|
||||
}
|
||||
if innerCode == ResponseInnerCodePartialFailed {
|
||||
errMsg += ", " + utils.Format4Output(data[resultKey], true)
|
||||
}
|
||||
return nil, utils.NewErrorCode(errMsg, innerCode, 1)
|
||||
return innerData, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -187,3 +187,12 @@ func TestUpdateSpu(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateSku(t *testing.T) {
|
||||
_, err := api.UpdateSku("27379", map[string]interface{}{
|
||||
"upc": "ttld20190712",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package jdapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
@@ -63,22 +62,23 @@ type QueryStockResponse struct {
|
||||
}
|
||||
|
||||
type UpdateVendibilityResponse struct {
|
||||
Code int `json:"code"`
|
||||
CurrentQty int `json:"currentQty"`
|
||||
LockQty int `json:"lockQty"`
|
||||
Msg string `json:"msg"`
|
||||
OrderQty int `json:"orderQty"`
|
||||
OutSkuID string `json:"outSkuId"`
|
||||
SkuID int64 `json:"skuId"`
|
||||
UsableQty int `json:"usableQty"`
|
||||
Vendibility int `json:"vendibility"`
|
||||
}
|
||||
|
||||
type StoreSkuBatchUpdateResponse struct {
|
||||
OutSkuID string `json:"outSkuId"`
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
|
||||
SkuID int64 `json:"skuId"`
|
||||
CurrentQty int `json:"currentQty"`
|
||||
LockQty int `json:"lockQty"`
|
||||
OrderQty int `json:"orderQty"`
|
||||
UsableQty int `json:"usableQty"`
|
||||
Vendibility int `json:"vendibility"`
|
||||
}
|
||||
|
||||
type StoreSkuBatchUpdateResponse struct {
|
||||
OutSkuID string `json:"outSkuId" json2:"outSkuId"`
|
||||
Code int `json:"code" json2:"errorCode"`
|
||||
Msg string `json:"msg" json2:"errorMessage"`
|
||||
|
||||
// UpdateVendibility会返回以下字段
|
||||
SkuID int64 `json:"skuId"`
|
||||
StationNo string `json:"stationNo"`
|
||||
@@ -97,10 +97,7 @@ type StoreSkuBatchUpdateResponse struct {
|
||||
|
||||
// 根据商家商品编码和商家门店编码批量修改门店价格接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=205&apiid=fcbf346648a54d03b92dec8fa62ea643
|
||||
func (a *API) UpdateVendorStationPrice(outStationNo, stationNo string, skuPriceInfoList []*SkuPriceInfo) ([]map[string]interface{}, error) {
|
||||
if (outStationNo == "" && stationNo == "") || (outStationNo != "" && stationNo != "") {
|
||||
return nil, errors.New("outStationNo and stationNo can not all be empty or have value")
|
||||
}
|
||||
func (a *API) UpdateVendorStationPrice(outStationNo, stationNo string, skuPriceInfoList []*SkuPriceInfo) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"skuPriceInfoList": skuPriceInfoList,
|
||||
}
|
||||
@@ -109,11 +106,14 @@ func (a *API) UpdateVendorStationPrice(outStationNo, stationNo string, skuPriceI
|
||||
} else {
|
||||
jdParams["stationNo"] = stationNo
|
||||
}
|
||||
result, err := a.AccessAPINoPage("venderprice/updateStationPrice", jdParams, nil, nil, nil)
|
||||
if err == nil && result != nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
result, err := a.AccessAPINoPage("venderprice/updateStationPrice", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
|
||||
if result != nil {
|
||||
var err2 error
|
||||
if responseList, err2 = a.handleBatchOpResult(len(skuPriceInfoList), result, "json2"); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
return responseList, err
|
||||
}
|
||||
|
||||
// 根据到家商品编码和到家门店编码修改门店价格接口
|
||||
@@ -146,16 +146,16 @@ func (a *API) GetStationInfoList(stationNo string, skuIds []int64) (priceInfo []
|
||||
return priceInfo, err
|
||||
}
|
||||
|
||||
func (a *API) handleBatchOpResult(batchCount int, result interface{}) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||||
if err = utils.Map2StructByJson(result, &responseList, true); err == nil {
|
||||
func (a *API) handleBatchOpResult(batchCount int, result interface{}, tagName string) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||||
if err = utils.Map2Struct(result, &responseList, true, tagName); err == nil {
|
||||
var failedList []*StoreSkuBatchUpdateResponse
|
||||
for _, v := range responseList {
|
||||
if v.Code != 0 {
|
||||
failedList = append(failedList, v)
|
||||
}
|
||||
}
|
||||
if batchCount == len(failedList) {
|
||||
err = fmt.Errorf(string(utils.MustMarshal(failedList)))
|
||||
if len(failedList) >= batchCount {
|
||||
err = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseCodeAccessFailed, 1) // 此错误基本用不到
|
||||
} else if len(failedList) > 0 { // 部分失败
|
||||
err = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseInnerCodePartialFailed, 1)
|
||||
}
|
||||
@@ -179,8 +179,11 @@ func (a *API) BatchUpdateCurrentQtys(outStationNo, stationNo string, skuStockLis
|
||||
jdParams["stationNo"] = stationNo
|
||||
}
|
||||
result, err := a.AccessAPINoPage("stock/batchUpdateCurrentQtys", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||||
if err == nil && result != nil {
|
||||
responseList, err = a.handleBatchOpResult(len(skuStockList), result)
|
||||
if result != nil {
|
||||
var err2 error
|
||||
if responseList, err2 = a.handleBatchOpResult(len(skuStockList), result, ""); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
return responseList, err
|
||||
}
|
||||
@@ -220,16 +223,19 @@ func (a *API) UpdateCurrentQty(stationNo string, skuID int64, currentQty int) er
|
||||
|
||||
// 根据到家商品编码和到家门店编码批量修改门店商品可售状态接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=b783a508e2cf4aca94681e4eed9af5bc
|
||||
// 尽量不用这个接口,用下面那个
|
||||
// 尽量不用这个接口,用下面那个,原因是这个不支持设置操作人,BatchUpdateVendibility可以
|
||||
func (a *API) UpdateVendibility(listBaseStockCenterRequest []*QueryStockRequest) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"listBaseStockCenterRequest": listBaseStockCenterRequest,
|
||||
}
|
||||
result, err := a.AccessAPINoPage("stock/updateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||||
if err == nil && result != nil {
|
||||
responseList, err = a.handleBatchOpResult(len(listBaseStockCenterRequest), result)
|
||||
if result != nil {
|
||||
var err2 error
|
||||
if responseList, err2 = a.handleBatchOpResult(len(listBaseStockCenterRequest), result, ""); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
return responseList, err
|
||||
}
|
||||
|
||||
// 根据商家商品编码和门店编码批量修改门店商品可售状态接口
|
||||
@@ -248,8 +254,11 @@ func (a *API) BatchUpdateVendibility(outStationNo, stationNo string, stockVendib
|
||||
jdParams["stationNo"] = stationNo
|
||||
}
|
||||
result, err := a.AccessAPINoPage("stock/batchUpdateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||||
if err == nil && result != nil {
|
||||
responseList, err = a.handleBatchOpResult(len(stockVendibilityList), result)
|
||||
if result != nil {
|
||||
var err2 error
|
||||
if responseList, err2 = a.handleBatchOpResult(len(stockVendibilityList), result, ""); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
return responseList, err
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ func (a *API) FullDiscountBatchSave(poiCode string, actInfo *FullDiscountActInfo
|
||||
if actInfo.ActType == ActTypeSkuFullDiscount {
|
||||
params["app_foods"] = string(utils.MustMarshal(actSkuList))
|
||||
}
|
||||
result, err := a.AccessAPI2("act/full/discount/batchsave", false, params, resultKeyMsg)
|
||||
result, err := a.AccessAPI2("act/full/discount/batchsave", false, params, resultKeySuccessMsg)
|
||||
if err == nil {
|
||||
err = utils.UnmarshalUseNumber([]byte(result.(string)), &actIDList)
|
||||
}
|
||||
@@ -322,7 +322,7 @@ func (a *API) RetailDiscountBatchSave(poiCode string, actData []*RetailDiscountA
|
||||
result, err := a.AccessAPI2("act/retail/discount/batchsave", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_data": string(utils.MustMarshal(actData)),
|
||||
}, resultKeyMsg)
|
||||
}, resultKeySuccessMsg)
|
||||
if err == nil {
|
||||
err = utils.UnmarshalUseNumber([]byte(result.(string)), &actResult)
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func (a *API) InStoreCouponBatchSave(poiCode string, limitTime *LimitTime, coupo
|
||||
KeyAppPoiCode: poiCode,
|
||||
"limit_time": string(utils.MustMarshal(limitTime)),
|
||||
"act_data": string(utils.MustMarshal(couponInfoList)),
|
||||
}, resultKeyMsg)
|
||||
}, resultKeySuccessMsg)
|
||||
if err == nil {
|
||||
err = utils.UnmarshalUseNumber([]byte(result.(string)), &couponResultList)
|
||||
}
|
||||
|
||||
@@ -33,8 +33,9 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
resultKeyData = "data"
|
||||
resultKeyMsg = "success_msg"
|
||||
resultKeyData = "data"
|
||||
resultKeyMsg = "msg"
|
||||
resultKeySuccessMsg = "success_msg"
|
||||
)
|
||||
const (
|
||||
GeneralMaxLimit = 200 // 大多数的API的批处理最大条数
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
@@ -14,6 +15,15 @@ const (
|
||||
MaxBatchDeleteSize = 100 // retailCat/batchdelete/catandretail这个接口的批量最大值
|
||||
)
|
||||
|
||||
const (
|
||||
SellStatusOnline = 0 // 上架
|
||||
SellStatusOffline = 1 // 下架
|
||||
)
|
||||
|
||||
var (
|
||||
retailBatchFailedSkuReg = regexp.MustCompile(`((?:\d+;)+)`)
|
||||
)
|
||||
|
||||
type RetailCategoryInfo struct {
|
||||
Name string `json:"name"`
|
||||
Sequence int `json:"sequence"`
|
||||
@@ -91,6 +101,11 @@ type AppFood struct {
|
||||
ZhName string `json:"zh_name"`
|
||||
}
|
||||
|
||||
type AppFoodResult struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
ErrorMsg string `json:"error_msg"`
|
||||
}
|
||||
|
||||
// 美团分类没有ID,就以名字为唯一标识,不论级别都必须不能重名
|
||||
// name(和originName)的长度不能超过10个字符(字符,不是字节)
|
||||
// 创建一级分类,originName为空,name为新分类名,secondaryName为空
|
||||
@@ -168,28 +183,78 @@ func (a *API) RetailList(poiCode string, offset, limit int) (foodList []*AppFood
|
||||
return foodList, err
|
||||
}
|
||||
|
||||
func (a *API) RetailBatchInitData(poiCode string, foodDataList []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/batchinitdata", false, map[string]interface{}{
|
||||
func handleRetailBatchResult(result interface{}) (failedFoodList []*AppFoodResult, err error) {
|
||||
if msg, ok := result.(string); ok && msg != "" {
|
||||
err = utils.UnmarshalUseNumber([]byte(msg), &failedFoodList)
|
||||
}
|
||||
return failedFoodList, err
|
||||
}
|
||||
|
||||
func handleRetailBatchResultByRegexp(result interface{}) (failedFoodList []*AppFoodResult, err error) {
|
||||
if msg, ok := result.(string); ok && msg != "" {
|
||||
findList := retailBatchFailedSkuReg.FindStringSubmatch(msg)
|
||||
if len(findList) == 2 {
|
||||
ids := strings.Split(strings.Trim(findList[1], ";"), ";")
|
||||
if len(ids) > 0 {
|
||||
failedFoodList = make([]*AppFoodResult, len(ids))
|
||||
for k, v := range ids {
|
||||
failedFoodList[k] = &AppFoodResult{
|
||||
AppFoodCode: v,
|
||||
ErrorMsg: "",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return failedFoodList, err
|
||||
}
|
||||
|
||||
func (a *API) RetailBatchInitData(poiCode string, foodDataList []map[string]interface{}) (failedFoodList []*AppFoodResult, err error) {
|
||||
result, err := a.AccessAPI2("retail/batchinitdata", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodDataList)),
|
||||
})
|
||||
return err
|
||||
}, resultKeyMsg)
|
||||
if err == nil {
|
||||
failedFoodList, err = handleRetailBatchResult(result)
|
||||
}
|
||||
return failedFoodList, err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuPrice(poiCode string, foodData []*BareStoreFoodInfo) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/price", false, map[string]interface{}{
|
||||
func (a *API) RetailSkuPrice(poiCode string, foodData []*BareStoreFoodInfo) (failedFoodList []*AppFoodResult, err error) {
|
||||
result, err := a.AccessAPI2("retail/sku/price", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
})
|
||||
return err
|
||||
}, resultKeyMsg)
|
||||
if err == nil {
|
||||
failedFoodList, err = handleRetailBatchResult(result)
|
||||
}
|
||||
return failedFoodList, err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuStock(poiCode string, foodData []*BareStoreFoodInfo) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/stock", false, map[string]interface{}{
|
||||
func (a *API) RetailSkuStock(poiCode string, foodData []*BareStoreFoodInfo) (failedFoodList []*AppFoodResult, err error) {
|
||||
result, err := a.AccessAPI2("retail/sku/stock", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
})
|
||||
return err
|
||||
}, resultKeyMsg)
|
||||
if err == nil {
|
||||
failedFoodList, err = handleRetailBatchResult(result)
|
||||
}
|
||||
return failedFoodList, err
|
||||
}
|
||||
|
||||
// retail/sku/sellStatus在部分失败时会返回错误,其它相应的批处理函数则会返回成功
|
||||
func (a *API) RetailSkuSellStatus(poiCode string, foodData []*BareStoreFoodInfo, sellStatus int) (failedFoodList []*AppFoodResult, err error) {
|
||||
_, err = a.AccessAPI2("retail/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
"sell_status": sellStatus,
|
||||
}, resultKeyMsg)
|
||||
if err != nil {
|
||||
if errExt, ok := err.(*utils.ErrorWithCode); ok {
|
||||
failedFoodList, _ = handleRetailBatchResultByRegexp(errExt.ErrMsg())
|
||||
}
|
||||
}
|
||||
return failedFoodList, err
|
||||
}
|
||||
|
||||
func (a *API) RetailGet(poiCode, foodCode string) (food *AppFood, err error) {
|
||||
@@ -216,24 +281,6 @@ func (a *API) RetailSkuSave(poiCode, foodCode string, standardSkus, unstandardSk
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSellStatus(poiCode string, foodData []map[string]interface{}, sellStatus int) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
"sell_status": sellStatus,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSellStatus2(poiCode string, foodData []*BareStoreFoodInfo, sellStatus int) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
"sell_status": sellStatus,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailDelete(poiCode, foodCode string) (err error) {
|
||||
_, err = a.AccessAPI("retail/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
|
||||
@@ -82,13 +82,14 @@ func TestRetailDelete(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetailBatchInitData(t *testing.T) {
|
||||
err := api.RetailBatchInitData("2464052", []map[string]interface{}{
|
||||
failedFoods, err := api.RetailBatchInitData(testPoiCode, []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"app_food_code": "23841",
|
||||
"box_num": 0,
|
||||
"box_price": 0,
|
||||
"category_name": "豆制良品🌾🌾",
|
||||
"category_name": "南北干货",
|
||||
"description": "",
|
||||
"is_sold_out": 0,
|
||||
"min_order_count": 1,
|
||||
@@ -104,6 +105,29 @@ func TestRetailBatchInitData(t *testing.T) {
|
||||
"upc": "",
|
||||
},
|
||||
},
|
||||
// "tag_id": "200000380",
|
||||
"unit": "份",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"app_food_code": "23840",
|
||||
"box_num": 0,
|
||||
"box_price": 0,
|
||||
"category_name": "南北干货",
|
||||
"description": "",
|
||||
"is_sold_out": 0,
|
||||
"min_order_count": 1,
|
||||
"name": "干腐竹约150g/份",
|
||||
"picture": "http://image.jxc4.com/5f7fba025fc9348796039423c48ac3f5.jpg",
|
||||
"price": 1000,
|
||||
"skus": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"price": 1000,
|
||||
"sku_id": "23840",
|
||||
"spec": "150g",
|
||||
"stock": "*",
|
||||
"upc": "",
|
||||
},
|
||||
},
|
||||
"tag_id": "200000380",
|
||||
"unit": "份",
|
||||
},
|
||||
@@ -111,4 +135,97 @@ func TestRetailBatchInitData(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(failedFoods, false))
|
||||
}
|
||||
|
||||
func TestRetailSkuPrice(t *testing.T) {
|
||||
result, err := api.RetailSkuPrice(testPoiCode, []*BareStoreFoodInfo{
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "23841",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "23841",
|
||||
Price: "1.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "23840",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "23840",
|
||||
Price: "1.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailSkuStock(t *testing.T) {
|
||||
result, err := api.RetailSkuStock(testPoiCode, []*BareStoreFoodInfo{
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "23841",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "23841",
|
||||
Price: "1.2",
|
||||
Stock: "123",
|
||||
},
|
||||
},
|
||||
},
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "23840",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "23840",
|
||||
Stock: "123",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailSkuSellStatus(t *testing.T) {
|
||||
result, err := api.RetailSkuSellStatus(testPoiCode, []*BareStoreFoodInfo{
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "23841",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "23841",
|
||||
Price: "1.2",
|
||||
Stock: "123",
|
||||
},
|
||||
},
|
||||
},
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "23840",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "23840",
|
||||
Stock: "123",
|
||||
},
|
||||
},
|
||||
},
|
||||
&BareStoreFoodInfo{
|
||||
AppFoodCode: "2384999",
|
||||
Skus: []*BareStoreSkuInfo{
|
||||
&BareStoreSkuInfo{
|
||||
SkuID: "2384999",
|
||||
Stock: "123",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, SellStatusOffline)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
@@ -183,15 +183,11 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
|
||||
func RebuildError(inErr error, bzParams map[string]interface{}, watchKeys []string) (outErr error) {
|
||||
if inErr != nil {
|
||||
if codeErr, ok := inErr.(*utils.ErrorWithCode); ok {
|
||||
appendErrList := []string{}
|
||||
for _, key := range watchKeys {
|
||||
if bzParams[key] != nil {
|
||||
appendErrList = append(appendErrList, fmt.Sprintf("[%s:%v]", key, bzParams[key]))
|
||||
codeErr.AddPrefixMsg(fmt.Sprintf("[%s:%v]", key, bzParams[key]))
|
||||
}
|
||||
}
|
||||
if len(appendErrList) > 0 {
|
||||
inErr = utils.NewErrorCode(strings.Join(appendErrList, ",")+", "+codeErr.ErrMsg(), codeErr.Code())
|
||||
}
|
||||
}
|
||||
}
|
||||
return inErr
|
||||
|
||||
@@ -7,10 +7,11 @@ import (
|
||||
)
|
||||
|
||||
type ErrorWithCode struct {
|
||||
level int
|
||||
errMsg string
|
||||
code string
|
||||
intCode int
|
||||
level int
|
||||
prefixList []string
|
||||
errMsg string
|
||||
code string
|
||||
intCode int
|
||||
}
|
||||
|
||||
func NewErrorCode(errMsg, code string, level ...int) *ErrorWithCode {
|
||||
@@ -31,7 +32,11 @@ func NewErrorIntCode(errMsg string, code int, level ...int) *ErrorWithCode {
|
||||
}
|
||||
|
||||
func (e *ErrorWithCode) Error() string {
|
||||
return fmt.Sprintf("%s level:%d, code:%s", e.errMsg, e.level, e.code)
|
||||
fullErrMsg := e.ErrMsg()
|
||||
if len(e.prefixList) > 0 {
|
||||
fullErrMsg = strings.Join(e.prefixList, ",") + ", " + fullErrMsg
|
||||
}
|
||||
return fmt.Sprintf("%s level:%d, code:%s", fullErrMsg, e.Level(), e.Code())
|
||||
}
|
||||
|
||||
func (e *ErrorWithCode) String() string {
|
||||
@@ -54,6 +59,10 @@ func (e *ErrorWithCode) ErrMsg() string {
|
||||
return e.errMsg
|
||||
}
|
||||
|
||||
func (e *ErrorWithCode) AddPrefixMsg(prefix string) {
|
||||
e.prefixList = append(e.prefixList, prefix)
|
||||
}
|
||||
|
||||
func IsErrMatch(err error, strCode string, strList []string) (isMatch bool) {
|
||||
if err != nil {
|
||||
if codeErr, ok := err.(*ErrorWithCode); ok {
|
||||
|
||||
@@ -247,6 +247,13 @@ func Int64ToStr(value int64) string {
|
||||
return strconv.FormatInt(value, 10)
|
||||
}
|
||||
|
||||
func Int64ToStrNoZero(value int64) string {
|
||||
if value == 0 {
|
||||
return ""
|
||||
}
|
||||
return strconv.FormatInt(value, 10)
|
||||
}
|
||||
|
||||
func Int2Str(value int) string {
|
||||
return strconv.Itoa(value)
|
||||
}
|
||||
@@ -469,11 +476,48 @@ func Struct2FlatMap(obj interface{}) map[string]interface{} {
|
||||
}
|
||||
|
||||
// !!! 此函数好像不支持struct是内嵌结构的
|
||||
func Map2StructByJson(inObj interface{}, outObjAddr interface{}, weaklyTypedInput bool) (err error) {
|
||||
func Map2Struct(inObj interface{}, outObjAddr interface{}, weaklyTypedInput bool, tagName string) (err error) {
|
||||
if tagName == "" {
|
||||
tagName = "json"
|
||||
}
|
||||
decoder, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
TagName: "json",
|
||||
TagName: tagName,
|
||||
Result: outObjAddr,
|
||||
WeaklyTypedInput: weaklyTypedInput,
|
||||
})
|
||||
return decoder.Decode(inObj)
|
||||
}
|
||||
|
||||
func Map2StructByJson(inObj interface{}, outObjAddr interface{}, weaklyTypedInput bool) (err error) {
|
||||
return Map2Struct(inObj, outObjAddr, weaklyTypedInput, "")
|
||||
}
|
||||
|
||||
func Int64Slice2String(intList []int64) (outList []string) {
|
||||
if len(intList) > 0 {
|
||||
outList = make([]string, len(intList))
|
||||
for k, v := range intList {
|
||||
outList[k] = Int64ToStr(v)
|
||||
}
|
||||
}
|
||||
return outList
|
||||
}
|
||||
|
||||
func StringSlice2Int64(intList []string) (outList []int64) {
|
||||
if len(intList) > 0 {
|
||||
outList = make([]int64, len(intList))
|
||||
for k, v := range intList {
|
||||
outList[k] = Str2Int64WithDefault(v, 0)
|
||||
}
|
||||
}
|
||||
return outList
|
||||
}
|
||||
|
||||
func IntSlice2Int64(intList []int) (outList []int64) {
|
||||
if len(intList) > 0 {
|
||||
outList = make([]int64, len(intList))
|
||||
for k, v := range intList {
|
||||
outList[k] = int64(v)
|
||||
}
|
||||
}
|
||||
return outList
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user