add methods for returns
This commit is contained in:
@@ -21,6 +21,7 @@ type Client struct {
|
|||||||
promotions *Promotions
|
promotions *Promotions
|
||||||
rating *Rating
|
rating *Rating
|
||||||
warehouses *Warehouses
|
warehouses *Warehouses
|
||||||
|
returns *Returns
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) Analytics() *Analytics {
|
func (c Client) Analytics() *Analytics {
|
||||||
@@ -55,6 +56,10 @@ func (c Client) Warehouses() *Warehouses {
|
|||||||
return c.warehouses
|
return c.warehouses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Client) Returns() *Returns {
|
||||||
|
return c.returns
|
||||||
|
}
|
||||||
|
|
||||||
func NewClient(clientId, apiKey string) *Client {
|
func NewClient(clientId, apiKey string) *Client {
|
||||||
coreClient := core.NewClient(DefaultAPIBaseUrl, map[string]string{
|
coreClient := core.NewClient(DefaultAPIBaseUrl, map[string]string{
|
||||||
"Client-Id": clientId,
|
"Client-Id": clientId,
|
||||||
@@ -71,6 +76,7 @@ func NewClient(clientId, apiKey string) *Client {
|
|||||||
promotions: &Promotions{client: coreClient},
|
promotions: &Promotions{client: coreClient},
|
||||||
rating: &Rating{client: coreClient},
|
rating: &Rating{client: coreClient},
|
||||||
warehouses: &Warehouses{client: coreClient},
|
warehouses: &Warehouses{client: coreClient},
|
||||||
|
returns: &Returns{client: coreClient},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,5 +93,6 @@ func NewMockClient(handler http.HandlerFunc) *Client {
|
|||||||
promotions: &Promotions{client: coreClient},
|
promotions: &Promotions{client: coreClient},
|
||||||
rating: &Rating{client: coreClient},
|
rating: &Rating{client: coreClient},
|
||||||
warehouses: &Warehouses{client: coreClient},
|
warehouses: &Warehouses{client: coreClient},
|
||||||
|
returns: &Returns{client: coreClient},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -883,7 +883,7 @@ type GetProductsRatingBySKUResponse struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
|
||||||
// Indication that the condition is met
|
// Indication that the condition is met
|
||||||
Fulfilled bool `json:'fulfilled"`
|
Fulfilled bool `json:"fulfilled"`
|
||||||
|
|
||||||
// Condition identifier
|
// Condition identifier
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
|
|||||||
250
ozon/returns.go
Normal file
250
ozon/returns.go
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
package ozon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
core "github.com/diphantxm/ozon-api-client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Returns struct {
|
||||||
|
client *core.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBOReturnsParams struct {
|
||||||
|
// Filter
|
||||||
|
Filter GetFBOReturnsFilter `json:"filter"`
|
||||||
|
|
||||||
|
// Identifier of the last value on the page. Leave this field blank in the first request.
|
||||||
|
//
|
||||||
|
// To get the next values, specify the recieved value in the next request in the `last_id` parameter
|
||||||
|
LastId int64 `json:"last_id"`
|
||||||
|
|
||||||
|
// Number of values in the response
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBOReturnsFilter struct {
|
||||||
|
// Shipment number
|
||||||
|
PostingNumber string `json:"posting_number"`
|
||||||
|
|
||||||
|
Status []string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBOReturnsResponse struct {
|
||||||
|
core.CommonResponse
|
||||||
|
|
||||||
|
// Identifier of the last value on the page
|
||||||
|
LastId int64 `json:"last_id"`
|
||||||
|
|
||||||
|
// Returns information
|
||||||
|
Returns []struct {
|
||||||
|
// Time when a return was received from the customer
|
||||||
|
AcceptedFromCustomerMoment time.Time `json:"accepted_from_customer_moment"`
|
||||||
|
|
||||||
|
// Seller identifier
|
||||||
|
CompanyId int64 `json:"company_id"`
|
||||||
|
|
||||||
|
// Current return location
|
||||||
|
CurrentPlaceName string `json:"current_place_name"`
|
||||||
|
|
||||||
|
// Return destination
|
||||||
|
DestinationPlaceName string `json:"dst_place_name"`
|
||||||
|
|
||||||
|
// Return identifier
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
|
||||||
|
// Indication that the package has been opened. true, if it has been
|
||||||
|
IsOpened bool `json:"is_opened"`
|
||||||
|
|
||||||
|
// Shipment number
|
||||||
|
PostingNumber string `json:"posting_number"`
|
||||||
|
|
||||||
|
// Return reason
|
||||||
|
ReturnReasonName string `json:"return_reason_name"`
|
||||||
|
|
||||||
|
// Return delivery time to the Ozon warehouse
|
||||||
|
ReturnedToOzonMoment time.Time `json:"returned_to_ozon_moment"`
|
||||||
|
|
||||||
|
// Product identifier in the Ozon system, SKU
|
||||||
|
SKU int64 `json:"sku"`
|
||||||
|
|
||||||
|
// Return status
|
||||||
|
Status string `json:"status_name"`
|
||||||
|
} `json:"returns"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method for getting information on returned products that are sold from the Ozon warehouse
|
||||||
|
func (c Returns) GetFBOReturns(params *GetFBOReturnsParams) (*GetFBOReturnsResponse, error) {
|
||||||
|
url := "/v3/returns/company/fbo"
|
||||||
|
|
||||||
|
resp := &GetFBOReturnsResponse{}
|
||||||
|
|
||||||
|
response, err := c.client.Request(http.MethodPost, url, params, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
response.CopyCommonResponse(&resp.CommonResponse)
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBSReturnsParams struct {
|
||||||
|
// Filter
|
||||||
|
Filter GetFBSReturnsFilter `json:"filter"`
|
||||||
|
|
||||||
|
// Number of values in the response:
|
||||||
|
// - maximum — 1000,
|
||||||
|
// - minimum — 1
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
|
||||||
|
// Number of elements that will be skipped in the response.
|
||||||
|
// For example, if offset=10, the response will start with the 11th element found
|
||||||
|
Offset int64 `json:"offset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBSReturnsFilter struct {
|
||||||
|
// Time of receiving the return from the customer
|
||||||
|
AcceptedFromCustomerMoment GetFBSReturnsFilterTimeRange `json:"accepted_from_customer_moment"`
|
||||||
|
|
||||||
|
// Last day of free storage
|
||||||
|
LastFreeWaitingDay []GetFBSReturnsFilterTimeRange `json:"last_free_waiting_dat"`
|
||||||
|
|
||||||
|
// Order ID
|
||||||
|
OrderId int64 `json:"order_id"`
|
||||||
|
|
||||||
|
// Shipment ID
|
||||||
|
PostingNumber []string `json:"posting_number"`
|
||||||
|
|
||||||
|
// Product name
|
||||||
|
ProductName string `json:"product_name"`
|
||||||
|
|
||||||
|
// Product ID
|
||||||
|
ProductOfferId string `json:"product_offer_id"`
|
||||||
|
|
||||||
|
// Return status:
|
||||||
|
// - returned_to_seller — returned to seller,
|
||||||
|
// - waiting_for_seller — waiting for seller,
|
||||||
|
// - accepted_from_customer — accepted from customer,
|
||||||
|
// - cancelled_with_compensation — cancelled with compensation,
|
||||||
|
// - ready_for_shipment — ready for shipment
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBSReturnsFilterTimeRange struct {
|
||||||
|
// The beginning of the period.
|
||||||
|
//
|
||||||
|
// Format: YYYY-MM-DDTHH:mm:ss.sssZ.
|
||||||
|
//
|
||||||
|
// Example: 2019-11-25T10:43:06.51
|
||||||
|
TimeFrom time.Time `json:"time_from"`
|
||||||
|
|
||||||
|
// The end of the period
|
||||||
|
//
|
||||||
|
// Format: YYYY-MM-DDTHH:mm:ss.sssZ.
|
||||||
|
//
|
||||||
|
// Example: 2019-11-25T10:43:06.51
|
||||||
|
TimeTo time.Time `json:"time_to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFBSReturnsResponse struct {
|
||||||
|
core.CommonResponse
|
||||||
|
|
||||||
|
Result struct {
|
||||||
|
// Elements counter in the response
|
||||||
|
Count int64 `json:"count"`
|
||||||
|
|
||||||
|
// Returns information
|
||||||
|
Returns []struct {
|
||||||
|
// Time of receiving the return from the customer
|
||||||
|
AcceptedFromCustomerAmount string `json:"accepted_from_customer_amount"`
|
||||||
|
|
||||||
|
// Bottom barcode on the product label
|
||||||
|
ClearingId int64 `json:"clearing_id"`
|
||||||
|
|
||||||
|
// Commission fee
|
||||||
|
Commission float64 `json:"commission"`
|
||||||
|
|
||||||
|
// Commission percentage
|
||||||
|
CommissionPercent float64 `json:"commission_percent"`
|
||||||
|
|
||||||
|
// Return identifier
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
|
||||||
|
// If the product is in transit — true
|
||||||
|
IsMoving bool `json:"is_moving"`
|
||||||
|
|
||||||
|
// Indication that the package has been opened. true, if it has been
|
||||||
|
IsOpened bool `json:"is_opened"`
|
||||||
|
|
||||||
|
// Last day of free storage
|
||||||
|
LastFreeWaitingDay string `json:"last_free_waiting_day"`
|
||||||
|
|
||||||
|
// ID of the warehouse the product is being transported to
|
||||||
|
PlaceId int64 `json:"place_id"`
|
||||||
|
|
||||||
|
// Name of the warehouse the product is being transported to
|
||||||
|
MovingToPlaceName string `json:"moving_to_place_name"`
|
||||||
|
|
||||||
|
// Delivery cost
|
||||||
|
PickingAmount float64 `json:"picking_amount"`
|
||||||
|
|
||||||
|
// Shipment number
|
||||||
|
PostingNumber string `json:"posting_number"`
|
||||||
|
|
||||||
|
// Current product price without a discount
|
||||||
|
Price float64 `json:"price"`
|
||||||
|
|
||||||
|
// Product price without commission
|
||||||
|
PriceWithoutCommission float64 `json:"price_without_commission"`
|
||||||
|
|
||||||
|
// Product identifier
|
||||||
|
ProductId int64 `json:"product_id"`
|
||||||
|
|
||||||
|
// Product name
|
||||||
|
ProductName string `json:"product_name"`
|
||||||
|
|
||||||
|
// Product quantity
|
||||||
|
Quantity int64 `json:"quantity"`
|
||||||
|
|
||||||
|
// Product return date
|
||||||
|
ReturnDate string `json:"return_date"`
|
||||||
|
|
||||||
|
// Return reason
|
||||||
|
ReturnReasonName string `json:"return_reason_name"`
|
||||||
|
|
||||||
|
// Date when the product is ready to be handed over to the seller
|
||||||
|
WaitingForSellerDate string `json:"waiting_for_seller_date_time"`
|
||||||
|
|
||||||
|
// Date of handing over the product to the seller
|
||||||
|
ReturnedToSellerDate string `json:"returned_to_seller_date_time"`
|
||||||
|
|
||||||
|
// Return storage period in days
|
||||||
|
WaitingForSellerDays int64 `json:"waiting_for_seller_days"`
|
||||||
|
|
||||||
|
// Return storage cost
|
||||||
|
ReturnsKeepingCost float64 `json:"returns_keeping_cost"`
|
||||||
|
|
||||||
|
// Product identifier in the Ozon system, SKU
|
||||||
|
SKU int64 `json:"sku"`
|
||||||
|
|
||||||
|
// Return status
|
||||||
|
Status string `json:"status"`
|
||||||
|
} `json:"returns"`
|
||||||
|
} `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method for getting information on returned products that are sold from the seller's warehouse
|
||||||
|
func (c Returns) GetFBSReturns(params *GetFBSReturnsParams) (*GetFBSReturnsResponse, error) {
|
||||||
|
url := "/v2/returns/company/fbs"
|
||||||
|
|
||||||
|
resp := &GetFBSReturnsResponse{}
|
||||||
|
|
||||||
|
response, err := c.client.Request(http.MethodPost, url, params, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
response.CopyCommonResponse(&resp.CommonResponse)
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
152
ozon/returns_test.go
Normal file
152
ozon/returns_test.go
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package ozon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
core "github.com/diphantxm/ozon-api-client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetFBOReturns(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
statusCode int
|
||||||
|
headers map[string]string
|
||||||
|
params *GetFBOReturnsParams
|
||||||
|
response string
|
||||||
|
}{
|
||||||
|
// Test Ok
|
||||||
|
{
|
||||||
|
http.StatusOK,
|
||||||
|
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
||||||
|
&GetFBOReturnsParams{
|
||||||
|
Filter: GetFBOReturnsFilter{
|
||||||
|
PostingNumber: "some number",
|
||||||
|
},
|
||||||
|
LastId: 123,
|
||||||
|
Limit: 100,
|
||||||
|
},
|
||||||
|
`{
|
||||||
|
"last_id": 0,
|
||||||
|
"returns": [
|
||||||
|
{
|
||||||
|
"accepted_from_customer_moment": "2019-08-24T14:15:22Z",
|
||||||
|
"company_id": 0,
|
||||||
|
"current_place_name": "my-place",
|
||||||
|
"dst_place_name": "that-place",
|
||||||
|
"id": 0,
|
||||||
|
"is_opened": true,
|
||||||
|
"posting_number": "some number",
|
||||||
|
"return_reason_name": "ripped",
|
||||||
|
"returned_to_ozon_moment": "2019-08-24T14:15:22Z",
|
||||||
|
"sku": 0,
|
||||||
|
"status_name": "delivering"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
// Test No Client-Id or Api-Key
|
||||||
|
{
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
map[string]string{},
|
||||||
|
&GetFBOReturnsParams{},
|
||||||
|
`{
|
||||||
|
"code": 16,
|
||||||
|
"message": "Client-Id and Api-Key headers are required"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
|
||||||
|
|
||||||
|
resp, err := c.Returns().GetFBOReturns(test.params)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != test.statusCode {
|
||||||
|
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetFBSReturns(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
statusCode int
|
||||||
|
headers map[string]string
|
||||||
|
params *GetFBSReturnsParams
|
||||||
|
response string
|
||||||
|
}{
|
||||||
|
// Test Ok
|
||||||
|
{
|
||||||
|
http.StatusOK,
|
||||||
|
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
||||||
|
&GetFBSReturnsParams{
|
||||||
|
Filter: GetFBSReturnsFilter{
|
||||||
|
PostingNumber: []string{"07402477-0022-2"},
|
||||||
|
Status: "returned_to_seller",
|
||||||
|
},
|
||||||
|
Limit: 1000,
|
||||||
|
Offset: 0,
|
||||||
|
},
|
||||||
|
`{
|
||||||
|
"result": {
|
||||||
|
"returns": [
|
||||||
|
{
|
||||||
|
"id": 19166541735000,
|
||||||
|
"clearing_id": 19166541725000,
|
||||||
|
"posting_number": "07402477-0022-2",
|
||||||
|
"product_id": 172423678,
|
||||||
|
"sku": 172423678,
|
||||||
|
"status": "returned_to_seller",
|
||||||
|
"returns_keeping_cost": 0,
|
||||||
|
"return_reason_name": "5.12 Заказ более не актуален: долгие сроки доставки",
|
||||||
|
"return_date": "2020-08-12T17:27:50+00:00",
|
||||||
|
"quantity": 1,
|
||||||
|
"product_name": "Кофе ароматизированный \"Лесной орех\" 250 гр",
|
||||||
|
"price": 294,
|
||||||
|
"waiting_for_seller_date_time": "2020-08-16T02:50:35+00:00",
|
||||||
|
"returned_to_seller_date_time": "2020-08-21T10:07:13+00:00",
|
||||||
|
"last_free_waiting_day": "2020-08-19T23:59:59+00:00",
|
||||||
|
"is_opened": false,
|
||||||
|
"place_id": 0,
|
||||||
|
"commission_percent": 0,
|
||||||
|
"commission": 0,
|
||||||
|
"price_without_commission": 0,
|
||||||
|
"is_moving": false,
|
||||||
|
"moving_to_place_name": "МОСКВА_ХАБ",
|
||||||
|
"waiting_for_seller_days": 2,
|
||||||
|
"picking_amount": null,
|
||||||
|
"accepted_from_customer_moment": null,
|
||||||
|
"picking_tag": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
// Test No Client-Id or Api-Key
|
||||||
|
{
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
map[string]string{},
|
||||||
|
&GetFBSReturnsParams{},
|
||||||
|
`{
|
||||||
|
"code": 16,
|
||||||
|
"message": "Client-Id and Api-Key headers are required"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
|
||||||
|
|
||||||
|
resp, err := c.Returns().GetFBSReturns(test.params)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != test.statusCode {
|
||||||
|
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user