320 lines
12 KiB
Go
320 lines
12 KiB
Go
package jdapi
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
)
|
||
|
||
const (
|
||
MaxStoreSkuBatchSize = 50
|
||
MaxStockQty = 100000000
|
||
|
||
MaxAddByStoreAndSkusCount = 30 // 批量置顶商品排序接口的最大个数
|
||
)
|
||
|
||
type SkuPriceInfo struct {
|
||
OutSkuId string `json:"outSkuId"`
|
||
Price int `json:"price"`
|
||
}
|
||
|
||
type SkuStock struct {
|
||
OutSkuId string `json:"outSkuId"`
|
||
StockQty int `json:"stockQty"`
|
||
}
|
||
|
||
type QueryStockRequest struct {
|
||
StationNo string `json:"stationNo"`
|
||
SkuId int64 `json:"skuId"`
|
||
DoSale int `json:"doSale"` //可售状态(0:可售,1:不可售)
|
||
}
|
||
|
||
type StockVendibility struct {
|
||
OutSkuId string `json:"outSkuId"`
|
||
DoSale bool `json:"doSale"` // 可售状态(true:可售,false:不可售)
|
||
}
|
||
|
||
type BaseStockCenterRequest struct {
|
||
StationNo string `json:"stationNo"`
|
||
SkuId int64 `json:"skuId"`
|
||
}
|
||
|
||
type SkuIdEntity struct {
|
||
OutSkuId string `json:"outSkuId"`
|
||
}
|
||
|
||
type StorePriceInfo struct {
|
||
MarketPrice int64 `json:"marketPrice"`
|
||
Pin string `json:"pin"`
|
||
Price int64 `json:"price"`
|
||
PromoteVipPrice int64 `json:"promoteVipPrice"`
|
||
SkuID int64 `json:"skuId"`
|
||
StationNo string `json:"stationNo"`
|
||
VenderID string `json:"venderId"`
|
||
VipPrice int64 `json:"vipPrice"`
|
||
}
|
||
|
||
type QueryStockResponse struct {
|
||
SkuID int64 `json:"skuId"`
|
||
StationNo string `json:"stationNo"`
|
||
UsableQty int `json:"usableQty"`
|
||
LockQty int `json:"lockQty"`
|
||
OrderQty int `json:"orderQty"`
|
||
Vendibility int `json:"vendibility"`
|
||
}
|
||
|
||
type UpdateVendibilityResponse 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"`
|
||
BusinessNo int `json:"businessNo"`
|
||
CreatePin string `json:"createPin"`
|
||
StockQty int `json:"stockQty"`
|
||
StockSource int `json:"stockSource"`
|
||
UpdatePin string `json:"updatePin"`
|
||
Vendibility int `json:"vendibility"`
|
||
}
|
||
|
||
// 传入为数组的,最多一次为50个
|
||
// 有好些功能有两个类似的函数,一个为到家ID,一个为商家ID,建议都只用商家ID的那个,因为:
|
||
// 1,这类函数一般可以批量操作
|
||
// 2,这类函数一般可以记录操作人员
|
||
|
||
// 根据商家商品编码和商家门店编码批量修改门店价格接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=205&apiid=fcbf346648a54d03b92dec8fa62ea643
|
||
func (a *API) UpdateVendorStationPrice(trackInfo string, outStationNo, stationNo string, skuPriceInfoList []*SkuPriceInfo) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||
jdParams := map[string]interface{}{
|
||
"skuPriceInfoList": skuPriceInfoList,
|
||
}
|
||
if outStationNo != "" {
|
||
jdParams["outStationNo"] = outStationNo
|
||
} else {
|
||
jdParams["stationNo"] = stationNo
|
||
}
|
||
result, err := a.AccessAPINoPage2("venderprice/updateStationPrice", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "0"), trackInfo)
|
||
if result != nil {
|
||
var err2 error
|
||
if responseList, err2 = a.handleBatchOpResult(outStationNo, stationNo, len(skuPriceInfoList), err, result, "json2"); err2 != nil && err == nil {
|
||
err = err2
|
||
}
|
||
}
|
||
return responseList, err
|
||
}
|
||
|
||
// 根据到家商品编码和到家门店编码修改门店价格接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=205&apiid=45f83ef7c6e74dad94b6b68d3c50b673
|
||
// 单商品用此接口
|
||
func (a *API) UpdateStationPrice(trackInfo string, skuId int64, stationNo string, price int) (string, error) {
|
||
jdParams := map[string]interface{}{
|
||
"skuId": skuId,
|
||
"stationNo": stationNo,
|
||
"price": price,
|
||
}
|
||
result, err := a.AccessAPINoPage2("price/updateStationPrice", jdParams, nil, nil, nil, trackInfo)
|
||
if err == nil && result != nil {
|
||
return utils.Interface2String(result), nil
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
// 根据到家商品编码和到家门店编码批量查询商品门店价格信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=205&apiid=21ccd5a00d3a4582b4c9a8ef0ae238fc
|
||
func (a *API) GetStationInfoList(stationNo string, skuIds []int64) (priceInfo []*StorePriceInfo, err error) {
|
||
jdParams := map[string]interface{}{
|
||
"skuIds": skuIds,
|
||
"stationNo": stationNo,
|
||
}
|
||
result, err := a.AccessAPINoPage("price/getStationInfoList", jdParams, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
|
||
if err == nil && result != nil {
|
||
err = JdMap2StructByJson(result, &priceInfo, false)
|
||
}
|
||
return priceInfo, err
|
||
}
|
||
|
||
func (a *API) handleBatchOpResult(outStationNo, stationNo string, batchCount int, inErr error, result interface{}, tagName string) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||
if result != nil {
|
||
if err = utils.Map2Struct(result, &responseList, true, tagName, JavaDateHook); err == nil {
|
||
var failedList []*StoreSkuBatchUpdateResponse
|
||
for _, v := range responseList {
|
||
if v.Code != 0 {
|
||
failedList = append(failedList, v)
|
||
}
|
||
}
|
||
var err2 *utils.ErrorWithCode
|
||
if len(failedList) >= batchCount {
|
||
err2 = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseCodeAccessFailed, 1) // 此错误基本用不到
|
||
} else if len(failedList) > 0 { // 部分失败
|
||
err2 = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseInnerCodePartialFailed, 1)
|
||
}
|
||
if err2 != nil {
|
||
if stationNo != "" {
|
||
err2.AddPrefixMsg(fmt.Sprintf("stationNo:%s", stationNo))
|
||
} else if outStationNo != "" {
|
||
err2.AddPrefixMsg(fmt.Sprintf("outStationNo:%s", outStationNo))
|
||
}
|
||
err = err2
|
||
}
|
||
}
|
||
}
|
||
return responseList, err
|
||
}
|
||
|
||
// 根据商家商品编码和商家门店编码批量修改现货库存接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=10812f9fc7ee4564b552f19270a7e92e
|
||
func (a *API) BatchUpdateCurrentQtys(trackInfo, outStationNo, stationNo string, skuStockList []*SkuStock, userPin string) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||
if (outStationNo == "" && stationNo == "") || (outStationNo != "" && stationNo != "") {
|
||
return nil, errors.New("outStationNo and stationNo can not all be empty or have value")
|
||
}
|
||
jdParams := map[string]interface{}{
|
||
"skuStockList": skuStockList,
|
||
"userPin": utils.GetAPIOperator(userPin),
|
||
}
|
||
if outStationNo != "" {
|
||
jdParams["outStationNo"] = outStationNo
|
||
} else {
|
||
jdParams["stationNo"] = stationNo
|
||
}
|
||
result, err := a.AccessAPINoPage2("stock/batchUpdateCurrentQtys", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
||
if result != nil {
|
||
var err2 error
|
||
if responseList, err2 = a.handleBatchOpResult(outStationNo, stationNo, len(skuStockList), err, result, ""); err2 != nil && err == nil {
|
||
err = err2
|
||
}
|
||
}
|
||
return responseList, err
|
||
}
|
||
|
||
// 根据商家商品编码和商家门店编码更新门店现货库存接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=a78664d4ead349da95d2f4576ed18d7f
|
||
// 此接口基本可以不用
|
||
func (a *API) StockUpdate(trackInfo string, outStationNo string, outSkuID string, currentQty int) error {
|
||
// !这个接口的stationNo与skuId好像本身就写错了的
|
||
jdParams := map[string]interface{}{
|
||
"stationNo": outStationNo,
|
||
"skuId": outSkuID,
|
||
"currentQty": currentQty,
|
||
}
|
||
_, err := a.AccessAPINoPage2("stock/update", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "", "0"), trackInfo)
|
||
if err == nil {
|
||
return nil
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 根据到家商品编码和到家门店编码更新门店现货库存
|
||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=200&apiid=af70e699d4974e1683128742018f6381
|
||
// 单商品用此接口
|
||
func (a *API) UpdateCurrentQty(trackInfo string, stationNo string, skuID int64, currentQty int) error {
|
||
jdParams := map[string]interface{}{
|
||
"stationNo": stationNo,
|
||
"skuId": skuID,
|
||
"currentQty": currentQty,
|
||
}
|
||
_, err := a.AccessAPINoPage2("update/currentQty", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "", "0"), trackInfo)
|
||
if err == nil {
|
||
return nil
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 根据到家商品编码和到家门店编码批量修改门店商品可售状态接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=b783a508e2cf4aca94681e4eed9af5bc
|
||
// 尽量不用这个接口,用下面那个,原因是这个不支持设置操作人,BatchUpdateVendibility可以
|
||
func (a *API) UpdateVendibility(trackInfo string, listBaseStockCenterRequest []*QueryStockRequest) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||
jdParams := map[string]interface{}{
|
||
"listBaseStockCenterRequest": listBaseStockCenterRequest,
|
||
}
|
||
result, err := a.AccessAPINoPage2("stock/updateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
||
if result != nil {
|
||
var err2 error
|
||
if responseList, err2 = a.handleBatchOpResult("", listBaseStockCenterRequest[0].StationNo, len(listBaseStockCenterRequest), err, result, ""); err2 != nil && err == nil {
|
||
err = err2
|
||
}
|
||
}
|
||
return responseList, err
|
||
}
|
||
|
||
// 根据商家商品编码和门店编码批量修改门店商品可售状态接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=ac6f559ebabf4b70bc423687638e07c1
|
||
func (a *API) BatchUpdateVendibility(trackInfo, outStationNo, stationNo string, stockVendibilityList []*StockVendibility, userPin string) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||
if (outStationNo == "" && stationNo == "") || (outStationNo != "" && stationNo != "") {
|
||
return nil, errors.New("outStationNo and stationNo can not all be empty or have value")
|
||
}
|
||
jdParams := map[string]interface{}{
|
||
"stockVendibilityList": stockVendibilityList,
|
||
"userPin": utils.GetAPIOperator(userPin),
|
||
}
|
||
if outStationNo != "" {
|
||
jdParams["outStationNo"] = outStationNo
|
||
} else {
|
||
jdParams["stationNo"] = stationNo
|
||
}
|
||
// 此函数在全部失败时,err仍然返回成功
|
||
result, err := a.AccessAPINoPage2("stock/batchUpdateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
||
if result != nil {
|
||
var err2 error
|
||
if responseList, err2 = a.handleBatchOpResult(outStationNo, stationNo, len(stockVendibilityList), err, result, ""); err2 != nil && err == nil {
|
||
err = err2
|
||
}
|
||
}
|
||
return responseList, err
|
||
}
|
||
|
||
// 根据到家商品编码和门店编码批量查询商品库存及可售状态信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=bc6ad75e8fd34580856e06b5eb149aad
|
||
// 尽量不用这个接口,用下面那个
|
||
func (a *API) QueryOpenUseable(listBaseStockCenterRequest []*BaseStockCenterRequest) (stockResponse []*QueryStockResponse, err error) {
|
||
jdParams := map[string]interface{}{
|
||
"listBaseStockCenterRequest": listBaseStockCenterRequest,
|
||
}
|
||
result, err := a.AccessAPINoPage("stock/queryOpenUseable", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||
if err == nil && result != nil {
|
||
err = JdMap2StructByJson(result, &stockResponse, false)
|
||
}
|
||
return stockResponse, err
|
||
}
|
||
|
||
// 根据商家商品编码和门店编码批量查询商品库存及可售状态信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=ba70316bb84f425f8c088d3c19b2570d
|
||
func (a *API) QueryStockCenter(outStationNo string, skuIds []*SkuIdEntity, userPin string) (vendibilityResponse []*UpdateVendibilityResponse, err error) {
|
||
jdParams := map[string]interface{}{
|
||
"outStationNo": outStationNo,
|
||
"skuIds": skuIds,
|
||
"userPin": utils.GetAPIOperator(userPin),
|
||
}
|
||
result, err := a.AccessAPINoPage("stock/queryStockCenter", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||
if err == nil && result != nil {
|
||
err = JdMap2StructByJson(result, &vendibilityResponse, false)
|
||
}
|
||
return vendibilityResponse, err
|
||
}
|
||
|
||
// 批量置顶商品排序接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=a7677f1a75984ed3a6ea3d4827f5a6b4
|
||
func (a *API) AddByStoreAndSkus(stationNo int64, skuIDs []int64) (err error) {
|
||
jdParams := map[string]interface{}{
|
||
"storeId": stationNo,
|
||
"skuIds": skuIDs,
|
||
}
|
||
_, err = a.AccessAPINoPage("OrgSortService/addByStoreAndSkus", jdParams, nil, nil, genNoPageResultParser("status", "message", "", "200"))
|
||
return err
|
||
}
|