31 Commits

Author SHA1 Message Date
diPhantxm
b8b5cf8a72 added comments on restrictions for seller without Premium subscription 2023-08-25 16:35:27 +03:00
Kirill
854d110ab1 Configure HttpClient, added context parameter to all methods (#37)
Context is needed to limit time of execution of a method. Previously, context was passed to structure and it was stored inside structure which is a bad practice. Now we need to pass context to function, which is a best practice
2023-08-05 13:50:34 +03:00
Kirill
018d40e641 Update August 2, 2023 (#34) 2023-08-03 21:02:08 +03:00
Kirill
72b25b673d fix tests (#33) 2023-08-02 01:57:08 +03:00
Kirill
cb24f19e83 fbs_sku and fbo_sku are now just sku (#32) 2023-08-02 01:19:21 +03:00
Kirill
588f4748a9 Update 28 July, 2023 (#31) 2023-07-31 00:20:07 +03:00
Kirill
651c39595f add tests for notification server errors (#30) 2023-07-29 02:59:03 +03:00
Kirill
6c1a5e35c0 enhance tests for notification server
enhance tests for notification server
2023-07-29 01:37:01 +03:00
diPhantxm
580a752012 enhance tests for notification server 2023-07-29 01:29:38 +03:00
diPhantxm
83fd8cf825 fix examlpe for notification server 2023-07-27 03:20:32 +03:00
Kirill
ebbc21b618 Notification Server
Push-Notifications
2023-07-27 02:51:36 +03:00
diPhantxm
f53b573d62 fix tests 2023-07-27 02:49:55 +03:00
diPhantxm
eb0ce6feb6 update readme 2023-07-27 00:44:36 +03:00
diPhantxm
9a41bb1196 add notification server, tests 2023-07-27 00:23:47 +03:00
diPhantxm
e76b9f3961 add notification server message types 2023-07-26 04:18:24 +03:00
diPhantxm
add4202b3e added new response fields to GetProductPriceInfo: result.items.acquiring, result.items.commissions.sales_percent_fbo/fbs 2023-07-25 17:41:27 +03:00
diPhantxm
7beee39eb2 Added the prices.price_strategy_enabled parameter to the method request 2023-07-20 02:48:09 +03:00
diPhantxm
baeeef9b46 fix json names for GetDigitalActResponse 2023-07-15 03:02:45 +03:00
diPhantxm
336c49baa4 Added the response example to TestGetLabeling 2023-07-15 03:02:45 +03:00
diPhantxm
f11ccb4714 updated the schemas and examples for method responses: methods return the result in binary format 2023-07-15 03:02:45 +03:00
diPhantxm
1958dfb94e Added a method for getting a barcode from the /v2/posting/fbs/act/get-barcode response in text format 2023-07-12 19:14:48 +03:00
diPhantxm
2ca20d9b12 Added a method for getting a barcode used during product shipment 2023-07-12 19:14:48 +03:00
Anton Salnikov
eea0f99066 Change address field tag 2023-07-09 19:54:28 +03:00
diPhantxm
7adaa92ad4 Specify enum values for status in GetFBOReturns method 2023-07-06 19:48:33 +03:00
diPhantxm
f54aa64b63 Update GetFBSReturns to v3. Add exemplar_id and return_barcode fields to method reponse 2023-07-06 19:39:54 +03:00
diPhantxm
e7c5dc320e fix params field in GetReportsListResultReport 2023-06-24 02:06:18 +03:00
diPhantxm
006ecdf877 commmented all data types and methods 2023-06-23 23:23:23 +03:00
diPhantxm
f81e4ed350 flat structures 2023-06-23 20:57:38 +03:00
Kirill
e7290069f5 Create LICENSE
Add MIT License
2023-06-20 23:33:02 +03:00
diphantxm
422f959b9f add prr option to some methods 2023-06-16 21:52:49 +03:00
diphantxm
ac99c5ba2f added new status to getting act list filter, updated descriptions, changed test according to examples 2023-06-16 21:35:33 +03:00
46 changed files with 6248 additions and 3354 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Kirill
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -11,6 +11,7 @@ Read full [documentation](https://docs.ozon.ru/api/seller/en/#tag/Introduction)
You can check [list of supported endpoints](ENDPOINTS.md) You can check [list of supported endpoints](ENDPOINTS.md)
## How to start ## How to start
### API
Get Client-Id and Api-Key in your seller profile [here](https://seller.ozon.ru/app/settings/api-keys?locale=en) Get Client-Id and Api-Key in your seller profile [here](https://seller.ozon.ru/app/settings/api-keys?locale=en)
Just add dependency to your project and you're ready to go. Just add dependency to your project and you're ready to go.
@@ -35,6 +36,7 @@ func main() {
client := ozon.NewClient("my-client-id", "my-api-key") client := ozon.NewClient("my-client-id", "my-api-key")
// Send request with parameters // Send request with parameters
ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := client.Products().GetProductDetails(&ozon.GetProductDetailsParams{ resp, err := client.Products().GetProductDetails(&ozon.GetProductDetailsParams{
ProductId: 123456789, ProductId: 123456789,
}) })
@@ -49,6 +51,43 @@ func main() {
} }
``` ```
### Notifications
Ozon can send push-notifications to your REST server. There is an implementation of REST server that handles notifications in this library.
[Official documentation](https://docs.ozon.ru/api/seller/en/#tag/push_intro)
How to use:
```Golang
package main
import (
"log"
"github.com/diphantxm/ozon-api-client/ozon/notifications"
)
func main() {
// Create server
port := 5000
server := notifications.NewNotificationServer(port)
// Register handlers passing message type and handler itself
server.Register(notifications.ChatClosedType, func(req interface{}) error {
notification := req.(*notifications.ChatClosed)
// Do something with the notification here...
log.Printf("chat %s has been closed\n", notification.ChatId)
return nil
})
// Run server
if err := server.Run(); err != nil {
log.Printf("error while running notification server: %s", err)
}
}
```
## Contribution ## Contribution
If you need some endpoints ASAP, create an issue and list all the endpoints. I will add them to library soon. If you need some endpoints ASAP, create an issue and list all the endpoints. I will add them to library soon.

View File

@@ -15,36 +15,33 @@ type HttpClient interface {
type Client struct { type Client struct {
baseUrl string baseUrl string
ctx context.Context
Options map[string]string Options map[string]string
client HttpClient client HttpClient
} }
func NewClient(baseUrl string, opts map[string]string) *Client { func NewClient(client HttpClient, baseUrl string, opts map[string]string) *Client {
return &Client{ return &Client{
Options: opts, Options: opts,
ctx: context.Background(), client: client,
client: http.DefaultClient,
baseUrl: baseUrl, baseUrl: baseUrl,
} }
} }
func NewMockClient(handler http.HandlerFunc) *Client { func NewMockClient(handler http.HandlerFunc) *Client {
return &Client{ return &Client{
ctx: context.Background(),
client: NewMockHttpClient(handler), client: NewMockHttpClient(handler),
} }
} }
func (c Client) newRequest(method string, url string, body interface{}) (*http.Request, error) { func (c Client) newRequest(ctx context.Context, method string, url string, body interface{}) (*http.Request, error) {
bodyJson, err := json.Marshal(body) bodyJson, err := json.Marshal(body)
if err != nil { if err != nil {
return nil, err return nil, err
} }
url = c.baseUrl + url url = c.baseUrl + url
req, err := http.NewRequestWithContext(c.ctx, method, url, bytes.NewBuffer(bodyJson)) req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewBuffer(bodyJson))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -56,8 +53,8 @@ func (c Client) newRequest(method string, url string, body interface{}) (*http.R
return req, nil return req, nil
} }
func (c Client) Request(method string, path string, req, resp interface{}, options map[string]string) (*Response, error) { func (c Client) Request(ctx context.Context, method string, path string, req, resp interface{}, options map[string]string) (*Response, error) {
httpReq, err := c.newRequest(method, path, req) httpReq, err := c.newRequest(ctx, method, path, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,8 +1,14 @@
package core package core
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
"time"
)
const (
testTimeout = 5 * time.Second
) )
type TestRequestRequest struct { type TestRequestRequest struct {
@@ -55,7 +61,8 @@ func TestRequest(t *testing.T) {
c := NewMockClient(NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(NewMockHttpHandler(test.statusCode, test.response, test.headers))
respStruct := &TestRequestResponse{} respStruct := &TestRequestResponse{}
resp, err := c.Request(http.MethodPost, "/", test.params, respStruct, nil) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Request(ctx, http.MethodPost, "/", test.params, respStruct, nil)
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -19,10 +20,66 @@ type GetAnalyticsDataParams struct {
DateTo time.Time `json:"date_to"` DateTo time.Time `json:"date_to"`
// Items Enum: "unknownDimension" "sku" "spu" "day" "week" "month" "year" "category1" "category2" "category3" "category4" "brand" "modelID" // Items Enum: "unknownDimension" "sku" "spu" "day" "week" "month" "year" "category1" "category2" "category3" "category4" "brand" "modelID"
// Data grouping available to all sellers:
// - unknownDimension—unknown,
// - sku—product identifier,
// - spu—product identifier,
// - day—day,
// - week—week,
// - month—month.
// Data grouping available to sellers with Premium subscription:
// - year—year,
// - category1—first level category,
// - category2—second level category,
// - category3—third level category,
// - category4—fourth level category,
// - brand—brand,
// - modelID—model.
Dimension []GetAnalyticsDataDimension `json:"dimension"` Dimension []GetAnalyticsDataDimension `json:"dimension"`
// Filters // Filters
Filters []struct { Filters []GetAnalyticsDataFilter `json:"filters"`
// Number of items in the respones:
// - maximum is 1000,
// - minimum is 1.
Limit int64 `json:"limit"`
// Specify up to 14 metrics. If there are more, you will get an error with the InvalidArgument code
// The list of metrics for which the report will be generated.
//
// Metrics available to all sellers:
//
// - revenue—ordered amount,
// - ordered_units—ordered products.
// Metrics available to sellers with Premium subscription:
// - unknown_metric—unknown metric,
// - hits_view_search—impressions in search and category,
// - hits_view_pdp—impressions on the product description page,
// - hits_view—total impressions,
// - hits_tocart_search—added to cart from search or category,
// - hits_tocart_pdp—added to cart from the product description page,
// - hits_tocart—added to cart total,
// - session_view_search—sessions with impressions in search or category,
// - session_view_pdp—sessions with impressions on the product description page,
// - session_view—sessions total,
// - conv_tocart_search—conversion to cart from search or category,
// - conv_tocart_pdp—conversion to cart from a product description page,
// - conv_tocart—total conversion to cart,
// - returns—returned products,
// - cancellations—canceled products,
// - delivered_units—delivered products,
// - position_category—position in search and category.
Metrics []GetAnalyticsDataFilterMetric `json:"metrics"`
// 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"`
// Report sorting settings
Sort []GetAnalyticsDataSort `json:"sort"`
}
type GetAnalyticsDataFilter struct {
// Sorting parameter. You can pass any attribute from the `dimension` and `metric` parameters except the `brand` attribute // Sorting parameter. You can pass any attribute from the `dimension` and `metric` parameters except the `brand` attribute
Key string `json:"key"` Key string `json:"key"`
@@ -31,21 +88,6 @@ type GetAnalyticsDataParams struct {
// Value for comparison // Value for comparison
Value string `json:"value"` Value string `json:"value"`
} `json:"filters"`
// Number of items in the respones:
// - maximum is 1000,
// - minimum is 1.
Limit int64 `json:"limit"`
// Specify up to 14 metrics. If there are more, you will get an error with the InvalidArgument code
Metrics []GetAnalyticsDataFilterMetric `json:"metrics"`
// 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"`
// Report sorting settings
Sort []GetAnalyticsDataSort `json:"sort"`
} }
// Report sorting settings // Report sorting settings
@@ -61,37 +103,50 @@ type GetAnalyticsDataResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetAnalyticsDataResult `json:"result"`
// Data array
Data []struct {
// Data grouping in the report
Dimensions []struct {
// Identifier
Id string `json:"id"`
// Name
Name string `json:"name"`
} `json:"dimensions"`
// Metric values list
Metrics []float64 `json:"metrics"`
} `json:"data"`
// Total and average metrics values
Totals []float64 `json:"totals"`
} `json:"result"`
// Report creation time // Report creation time
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
} }
type GetAnalyticsDataResult struct {
// Data array
Data []GetAnalyticsDataResultData `json:"data"`
// Total and average metrics values
Totals []float64 `json:"totals"`
}
type GetAnalyticsDataResultData struct {
// Data grouping in the report
Dimensions []GetAnalyticsDataResultDimension `json:"dimensions"`
// Metric values list
Metrics []float64 `json:"metrics"`
}
type GetAnalyticsDataResultDimension struct {
// Identifier
Id string `json:"id"`
// Name
Name string `json:"name"`
}
// Specify the period and metrics that are required. The response will contain analytical data grouped by the `dimensions` parameter. // Specify the period and metrics that are required. The response will contain analytical data grouped by the `dimensions` parameter.
func (c Analytics) GetAnalyticsData(params *GetAnalyticsDataParams) (*GetAnalyticsDataResponse, error) { //
// There are restrictions for sellers without Premium subscription:
//
// - data is available for the last 3 months,
// - some of the data grouping methods and metrics aren't available.
//
// There are no restrictions for sellers with Premium subscription
func (c Analytics) GetAnalyticsData(ctx context.Context, params *GetAnalyticsDataParams) (*GetAnalyticsDataResponse, error) {
url := "/v1/analytics/data" url := "/v1/analytics/data"
resp := &GetAnalyticsDataResponse{} resp := &GetAnalyticsDataResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -117,9 +172,15 @@ type GetStocksOnWarehousesResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetStocksOnWarehousesResult `json:"result"`
}
type GetStocksOnWarehousesResult struct {
// Information about products and stocks // Information about products and stocks
Rows []struct { Rows []GetStocksOnWarehousesResultRow `json:"rows"`
}
type GetStocksOnWarehousesResultRow struct {
// Product identifier in the Ozon system, SKU // Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"` SKU int64 `json:"sku"`
@@ -140,17 +201,15 @@ type GetStocksOnWarehousesResponse struct {
// Name of the warehouse where the products are stored // Name of the warehouse where the products are stored
WarehouseName string `json:"warehouse_name"` WarehouseName string `json:"warehouse_name"`
} `json:"rows"`
} `json:"result"`
} }
// Report on stocks and products movement at Ozon warehouses // Report on stocks and products movement at Ozon warehouses
func (c Analytics) GetStocksOnWarehouses(params *GetStocksOnWarehousesParams) (*GetStocksOnWarehousesResponse, error) { func (c Analytics) GetStocksOnWarehouses(ctx context.Context, params *GetStocksOnWarehousesParams) (*GetStocksOnWarehousesResponse, error) {
url := "/v2/analytics/stock_on_warehouses" url := "/v2/analytics/stock_on_warehouses"
resp := &GetStocksOnWarehousesResponse{} resp := &GetStocksOnWarehousesResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -24,7 +25,7 @@ func TestGetAnalyticsData(t *testing.T) {
DateFrom: core.TimeFromString(t, "2006-01-02", "2020-09-01"), DateFrom: core.TimeFromString(t, "2006-01-02", "2020-09-01"),
DateTo: core.TimeFromString(t, "2006-01-02", "2021-10-15"), DateTo: core.TimeFromString(t, "2006-01-02", "2021-10-15"),
Dimension: []GetAnalyticsDataDimension{SKUDimension, DayDimension}, Dimension: []GetAnalyticsDataDimension{SKUDimension, DayDimension},
Metrics: []GetAnalyticsDataFilterMetric{AdvViewAll}, Metrics: []GetAnalyticsDataFilterMetric{HistViewPDP},
Sort: []GetAnalyticsDataSort{ Sort: []GetAnalyticsDataSort{
{ {
Key: HistViewPDP, Key: HistViewPDP,
@@ -59,7 +60,8 @@ func TestGetAnalyticsData(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Analytics().GetAnalyticsData(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Analytics().GetAnalyticsData(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -119,7 +121,8 @@ func TestGetStocksOnWarehouses(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Analytics().GetStocksOnWarehouses(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Analytics().GetStocksOnWarehouses(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
core "github.com/diphantxm/ozon-api-client" core "github.com/diphantxm/ozon-api-client"
@@ -22,9 +23,18 @@ type ListCertifiedBrandsResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ListCertifiedBrandsResult `json:"result"`
}
type ListCertifiedBrandsResult struct {
// Certified brands details // Certified brands details
BrandCertification []struct { BrandCertification []ListCertifiedBrandsResultCertificate `json:"brand_certification"`
// Total number of brands
Total int64 `json:"total"`
}
type ListCertifiedBrandsResultCertificate struct {
// Brand name // Brand name
BrandName string `json:"brand_name"` BrandName string `json:"brand_name"`
@@ -32,20 +42,15 @@ type ListCertifiedBrandsResponse struct {
// - true if the certificate is required; // - true if the certificate is required;
// - false if not // - false if not
HasCertificate bool `json:"has_certificate"` HasCertificate bool `json:"has_certificate"`
} `json:"brand_certification"`
// Total number of brands
Total int64 `json:"total"`
} `json:"result"`
} }
// List of certified brands // List of certified brands
func (c Brands) List(params *ListCertifiedBrandsParams) (*ListCertifiedBrandsResponse, error) { func (c Brands) List(ctx context.Context, params *ListCertifiedBrandsParams) (*ListCertifiedBrandsResponse, error) {
url := "/v1/brand/company-certification/list" url := "/v1/brand/company-certification/list"
resp := &ListCertifiedBrandsResponse{} resp := &ListCertifiedBrandsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -52,7 +53,8 @@ func TestListCertifiedBrands(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Brands().List(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Brands().List(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -31,13 +32,7 @@ type CancellationInfo struct {
PostingNumber string `json:"posting_number"` PostingNumber string `json:"posting_number"`
// Cancellation reason // Cancellation reason
CancellationReason struct { CancellationReason CancellationInfoReason `json:"cancellation_reason"`
// Cancellation reason identifier
Id int64 `json:"id"`
// Cancellation reason name
Name string `json:"name"`
} `json:"cancellation_reason"`
// Cancellation request creation date // Cancellation request creation date
CancelledAt time.Time `json:"cancelled_at"` CancelledAt time.Time `json:"cancelled_at"`
@@ -49,16 +44,7 @@ type CancellationInfo struct {
TPLIntegrationType string `json:"tpl_integration_type"` TPLIntegrationType string `json:"tpl_integration_type"`
// Cancellation request status // Cancellation request status
State struct { State CancellationInfoState `json:"state"`
// Status identifier
Id int64 `json:"id"`
// Status name
Name string `json:"name"`
// Request status
State string `json:"state"`
} `json:"state"`
// Cancellation initiator // Cancellation initiator
CancellationInitiator string `json:"cancellation_initiator"` CancellationInitiator string `json:"cancellation_initiator"`
@@ -76,13 +62,32 @@ type CancellationInfo struct {
AutoApproveDate time.Time `json:"auto_approve_date"` AutoApproveDate time.Time `json:"auto_approve_date"`
} }
type CancellationInfoReason struct {
// Cancellation reason identifier
Id int64 `json:"id"`
// Cancellation reason name
Name string `json:"name"`
}
type CancellationInfoState struct {
// Status identifier
Id int64 `json:"id"`
// Status name
Name string `json:"name"`
// Request status
State string `json:"state"`
}
// Method for getting information about a rFBS cancellation request // Method for getting information about a rFBS cancellation request
func (c Cancellations) GetInfo(params *GetCancellationInfoParams) (*GetCancellationInfoResponse, error) { func (c Cancellations) GetInfo(ctx context.Context, params *GetCancellationInfoParams) (*GetCancellationInfoResponse, error) {
url := "/v1/delivery-method/list" url := "/v1/delivery-method/list"
resp := &GetCancellationInfoResponse{} resp := &GetCancellationInfoResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -134,7 +139,10 @@ type ListCancellationsResponse struct {
Total int32 `json:"total"` Total int32 `json:"total"`
// Counter of requests in different statuses // Counter of requests in different statuses
Counters struct { Counters ListCancellationResponseCounters `json:"counters"`
}
type ListCancellationResponseCounters struct {
// Number of requests for approval // Number of requests for approval
OnApproval int64 `json:"on_approval"` OnApproval int64 `json:"on_approval"`
@@ -143,16 +151,15 @@ type ListCancellationsResponse struct {
// Number of rejected requests // Number of rejected requests
Rejected int64 `json:"rejected"` Rejected int64 `json:"rejected"`
} `json:"counters"`
} }
// Method for getting a list of rFBS cancellation requests // Method for getting a list of rFBS cancellation requests
func (c Cancellations) List(params *ListCancellationsParams) (*ListCancellationsResponse, error) { func (c Cancellations) List(ctx context.Context, params *ListCancellationsParams) (*ListCancellationsResponse, error) {
url := "/v1/conditional-cancellation/list" url := "/v1/conditional-cancellation/list"
resp := &ListCancellationsResponse{} resp := &ListCancellationsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -175,12 +182,12 @@ type ApproveRejectCancellationsResponse struct {
// The method allows to approve an rFBS cancellation request in the ON_APPROVAL status. // The method allows to approve an rFBS cancellation request in the ON_APPROVAL status.
// The order will be canceled and the money will be returned to the customer // The order will be canceled and the money will be returned to the customer
func (c Cancellations) Approve(params *ApproveRejectCancellationsParams) (*ApproveRejectCancellationsResponse, error) { func (c Cancellations) Approve(ctx context.Context, params *ApproveRejectCancellationsParams) (*ApproveRejectCancellationsResponse, error) {
url := "/v1/conditional-cancellation/approve" url := "/v1/conditional-cancellation/approve"
resp := &ApproveRejectCancellationsResponse{} resp := &ApproveRejectCancellationsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -192,12 +199,12 @@ func (c Cancellations) Approve(params *ApproveRejectCancellationsParams) (*Appro
// The method allows to reject an rFBS cancellation request in the ON_APPROVAL status. Explain your decision in the comment parameter. // The method allows to reject an rFBS cancellation request in the ON_APPROVAL status. Explain your decision in the comment parameter.
// //
// The order will remain in the same status and must be delivered to the customer // The order will remain in the same status and must be delivered to the customer
func (c Cancellations) Reject(params *ApproveRejectCancellationsParams) (*ApproveRejectCancellationsResponse, error) { func (c Cancellations) Reject(ctx context.Context, params *ApproveRejectCancellationsParams) (*ApproveRejectCancellationsResponse, error) {
url := "/v1/conditional-cancellation/reject" url := "/v1/conditional-cancellation/reject"
resp := &ApproveRejectCancellationsResponse{} resp := &ApproveRejectCancellationsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -62,7 +63,8 @@ func TestGetCancellationInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Cancellations().GetInfo(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Cancellations().GetInfo(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -171,7 +173,8 @@ func TestListCancellations(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Cancellations().List(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Cancellations().List(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -215,7 +218,8 @@ func TestApproveCancellations(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Cancellations().Approve(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Cancellations().Approve(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -259,7 +263,8 @@ func TestRejectCancellations(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Cancellations().Reject(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Cancellations().Reject(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
core "github.com/diphantxm/ozon-api-client" core "github.com/diphantxm/ozon-api-client"
@@ -22,7 +23,10 @@ type GetProductTreeResponse struct {
core.CommonResponse core.CommonResponse
// Category list // Category list
Result []struct { Result []GetProductTreeResult `json:"result"`
}
type GetProductTreeResult struct {
// Category identifier // Category identifier
CategoryId int64 `json:"category_id"` CategoryId int64 `json:"category_id"`
@@ -31,19 +35,18 @@ type GetProductTreeResponse struct {
// Category name // Category name
Title string `json:"title"` Title string `json:"title"`
} `json:"result"`
} }
// Returns product categories in the tree view. // Returns product categories in the tree view.
// New products can be created in the last level categories only. // New products can be created in the last level categories only.
// This means that you need to match these particular categories with the categories of your site. // This means that you need to match these particular categories with the categories of your site.
// It is not possible to create categories by user request // It is not possible to create categories by user request
func (c Categories) Tree(params *GetProductTreeParams) (*GetProductTreeResponse, error) { func (c Categories) Tree(ctx context.Context, params *GetProductTreeParams) (*GetProductTreeResponse, error) {
url := "/v2/category/tree" url := "/v2/category/tree"
resp := &GetProductTreeResponse{} resp := &GetProductTreeResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -67,9 +70,18 @@ type GetCategoryAttributesResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result []struct { Result []GetCategoryAttributesResult `json:"result"`
}
type GetCategoryAttributesResult struct {
// Array of product characteristics // Array of product characteristics
Attributes []struct { Attributes []GetCategoryAttributesResultAttribute `json:"attributes"`
// Category identifier
CategoryId int64 `json:"category_id"`
}
type GetCategoryAttributesResultAttribute struct {
// Indication that the dictionary attribute values depend on the category: // Indication that the dictionary attribute values depend on the category:
// - true — the attribute has its own set of values for each category. // - true — the attribute has its own set of values for each category.
// - false — the attribute has the same set of values for all categories // - false — the attribute has the same set of values for all categories
@@ -114,11 +126,6 @@ type GetCategoryAttributesResponse struct {
// Characteristic type // Characteristic type
Type string `json:"type"` Type string `json:"type"`
} `json:"attributes"`
// Category identifier
CategoryId int64 `json:"category_id"`
} `json:"result"`
} }
// Getting characteristics for specified product category. // Getting characteristics for specified product category.
@@ -128,12 +135,12 @@ type GetCategoryAttributesResponse struct {
// You can check whether the attribute has a nested directory by the `dictionary_id` parameter. // You can check whether the attribute has a nested directory by the `dictionary_id` parameter.
// The 0 value means there is no directory. If the value is different, then there are directories. // The 0 value means there is no directory. If the value is different, then there are directories.
// You can get them using the `/v2/category/attribute/values` method // You can get them using the `/v2/category/attribute/values` method
func (c Categories) Attributes(params *GetCategoryAttributesParams) (*GetCategoryAttributesResponse, error) { func (c Categories) Attributes(ctx context.Context, params *GetCategoryAttributesParams) (*GetCategoryAttributesResponse, error) {
url := "/v3/category/attribute" url := "/v3/category/attribute"
resp := &GetCategoryAttributesResponse{} resp := &GetCategoryAttributesResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -167,24 +174,26 @@ type GetAttributeDictionaryResponse struct {
HasNext bool `json:"has_next"` HasNext bool `json:"has_next"`
// Method result // Method result
Result []struct { Result []GetAttributeDictionaryResult `json:"result"`
}
type GetAttributeDictionaryResult struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Info string `json:"info"` Info string `json:"info"`
Picture string `json:"picture"` Picture string `json:"picture"`
// Product characteristic value // Product characteristic value
Value string `json:"value"` Value string `json:"value"`
} `json:"result"`
} }
// You can use the `/v3/category/attribute` method to check if an attribute has a nested directory. // You can use the `/v3/category/attribute` method to check if an attribute has a nested directory.
// If there are directories, get them using this method // If there are directories, get them using this method
func (c Categories) AttributesDictionary(params *GetAttributeDictionaryParams) (*GetAttributeDictionaryResponse, error) { func (c Categories) AttributesDictionary(ctx context.Context, params *GetAttributeDictionaryParams) (*GetAttributeDictionaryResponse, error) {
url := "/v2/category/attribute/values" url := "/v2/category/attribute/values"
resp := &GetAttributeDictionaryResponse{} resp := &GetAttributeDictionaryResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -48,7 +49,8 @@ func TestGetProductTree(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Categories().Tree(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Categories().Tree(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -119,7 +121,8 @@ func TestGetCategoryAttributes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Categories().Attributes(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Categories().Attributes(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -199,7 +202,8 @@ func TestGetAttributeDictionary(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Categories().AttributesDictionary(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Categories().AttributesDictionary(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -15,34 +16,40 @@ type ListOfAccordanceTypesResponse struct {
core.CommonResponse core.CommonResponse
// Accordance types // Accordance types
Result struct { Result ListOfAccordanceTypesResult `json:"result"`
// Main accordance types }
Base []struct {
// Accordance type code
Code string `json:"code"`
// Accordance type description type ListOfAccordanceTypesResult struct {
Title string `json:"title"` // Main accordance types
} `json:"base"` Base []ListOfAccordanceTypesResultBase `json:"base"`
// Main accordance types related to dangerous products // Main accordance types related to dangerous products
Hazard []struct { Hazard []ListOfAccordanceTypesResultHazard `json:"hazard"`
}
type ListOfAccordanceTypesResultBase struct {
// Accordance type code
Code string `json:"code"`
// Accordance type description
Title string `json:"title"`
}
type ListOfAccordanceTypesResultHazard struct {
// Accordance type code // Accordance type code
Code string `json:"code"` Code string `json:"code"`
// Accordance type description // Accordance type description
Title string `json:"title"` Title string `json:"title"`
} `json:"hazard"`
} `json:"result"`
} }
// List of accordance types (version 2) // List of accordance types (version 2)
func (c Certificates) ListOfAccordanceTypes() (*ListOfAccordanceTypesResponse, error) { func (c Certificates) ListOfAccordanceTypes(ctx context.Context) (*ListOfAccordanceTypesResponse, error) {
url := "/v2/product/certificate/accordance-types/list" url := "/v2/product/certificate/accordance-types/list"
resp := &ListOfAccordanceTypesResponse{} resp := &ListOfAccordanceTypesResponse{}
response, err := c.client.Request(http.MethodGet, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodGet, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -55,22 +62,24 @@ type DirectoryOfDocumentTypesResponse struct {
core.CommonResponse core.CommonResponse
// List of certificate types and names // List of certificate types and names
Result []struct { Result []DirectoryOfDocumentTypesResult `json:"result"`
}
type DirectoryOfDocumentTypesResult struct {
// Certificate name // Certificate name
Name string `json:"name"` Name string `json:"name"`
// Certificate type // Certificate type
Value string `json:"value"` Value string `json:"value"`
} `json:"result"`
} }
// Directory of document types // Directory of document types
func (c Certificates) DirectoryOfDocumentTypes() (*DirectoryOfDocumentTypesResponse, error) { func (c Certificates) DirectoryOfDocumentTypes(ctx context.Context) (*DirectoryOfDocumentTypesResponse, error) {
url := "/v1/product/certificate/types" url := "/v1/product/certificate/types"
resp := &DirectoryOfDocumentTypesResponse{} resp := &DirectoryOfDocumentTypesResponse{}
response, err := c.client.Request(http.MethodGet, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodGet, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -91,28 +100,32 @@ type ListOfCertifiedCategoriesResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ListOfCertifiedCategoriesResult `json:"reult"`
}
type ListOfCertifiedCategoriesResult struct {
// Certified categories details // Certified categories details
Certification []struct { Certification []ListOfCertifiedCategoriesResultCert `json:"certification"`
// Total number of categories
Total int64 `json:"total"`
}
type ListOfCertifiedCategoriesResultCert struct {
// Category name // Category name
CategoryName string `json:"category_name"` CategoryName string `json:"category_name"`
// Indication of a mandatory category // Indication of a mandatory category
IsRequired bool `json:"is_required"` IsRequired bool `json:"is_required"`
} `json:"certification"`
// Total number of categories
Total int64 `json:"total"`
} `json:"reult"`
} }
// List of certified categories // List of certified categories
func (c Certificates) ListOfCertifiedCategories(params *ListOfCertifiedCategoriesParams) (*ListOfCertifiedCategoriesResponse, error) { func (c Certificates) ListOfCertifiedCategories(ctx context.Context, params *ListOfCertifiedCategoriesParams) (*ListOfCertifiedCategoriesResponse, error) {
url := "/v1/product/certificate/types" url := "/v1/product/certificate/types"
resp := &ListOfCertifiedCategoriesResponse{} resp := &ListOfCertifiedCategoriesResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -137,12 +150,12 @@ type LinkCertificateToProductResponse struct {
} }
// Link the certificate to the product // Link the certificate to the product
func (c Certificates) LinkToProduct(params *LinkCertificateToProductParams) (*LinkCertificateToProductResponse, error) { func (c Certificates) LinkToProduct(ctx context.Context, params *LinkCertificateToProductParams) (*LinkCertificateToProductResponse, error) {
url := "/v1/product/certificate/bind" url := "/v1/product/certificate/bind"
resp := &LinkCertificateToProductResponse{} resp := &LinkCertificateToProductResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -160,7 +173,10 @@ type DeleteCertificateResponse struct {
core.CommonResponse core.CommonResponse
// Result of deleting the certificate // Result of deleting the certificate
Result struct { Result DeleteCertificateResult `json:"result"`
}
type DeleteCertificateResult struct {
// Indication that a certificate has been deleted: // Indication that a certificate has been deleted:
// - true — deleted // - true — deleted
// - false — not deleted // - false — not deleted
@@ -168,16 +184,15 @@ type DeleteCertificateResponse struct {
// Description of errors during certificate deletion // Description of errors during certificate deletion
ErrorMessage string `json:"error_message"` ErrorMessage string `json:"error_message"`
} `json:"result"`
} }
// Delete certificate // Delete certificate
func (c Certificates) Delete(params *DeleteCertificateParams) (*DeleteCertificateResponse, error) { func (c Certificates) Delete(ctx context.Context, params *DeleteCertificateParams) (*DeleteCertificateResponse, error) {
url := "/v1/product/certificate/delete" url := "/v1/product/certificate/delete"
resp := &DeleteCertificateResponse{} resp := &DeleteCertificateResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -195,7 +210,10 @@ type GetCertificateInfoResponse struct {
core.CommonResponse core.CommonResponse
// Certificate information // Certificate information
Result struct { Result GetCertificateInfoResult `json:"result"`
}
type GetCertificateInfoResult struct {
// Identifier // Identifier
CertificateId int32 `json:"certificate_id"` CertificateId int32 `json:"certificate_id"`
@@ -228,16 +246,15 @@ type GetCertificateInfoResponse struct {
// Number of products associated with a certificate // Number of products associated with a certificate
ProductsCount int32 `json:"products_count"` ProductsCount int32 `json:"products_count"`
} `json:"result"`
} }
// Certificate information // Certificate information
func (c Certificates) GetInfo(params *GetCertificateInfoParams) (*GetCertificateInfoResponse, error) { func (c Certificates) GetInfo(ctx context.Context, params *GetCertificateInfoParams) (*GetCertificateInfoResponse, error) {
url := "/v1/product/certificate/info" url := "/v1/product/certificate/info"
resp := &GetCertificateInfoResponse{} resp := &GetCertificateInfoResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -268,9 +285,18 @@ type ListCertificatesResponse struct {
core.CommonResponse core.CommonResponse
// Certificates // Certificates
Result struct { Result ListCertificatesResult `json:"result"`
}
type ListCertificatesResult struct {
// Сertificate information // Сertificate information
Certificates []struct { Certificates []ListCertificatesResultCert `json:"certificates"`
// Number of pages
PageCount int32 `json:"page_count"`
}
type ListCertificatesResultCert struct {
// Identifier // Identifier
CertificateId int32 `json:"certificate_id"` CertificateId int32 `json:"certificate_id"`
@@ -303,20 +329,15 @@ type ListCertificatesResponse struct {
// Number of products associated with a certificate // Number of products associated with a certificate
ProductsCount int32 `json:"products_count"` ProductsCount int32 `json:"products_count"`
} `json:"certificates"`
// Number of pages
PageCount int32 `json:"page_count"`
} `json:"result"`
} }
// Certificates list // Certificates list
func (c Certificates) List(params *ListCertificatesParams) (*ListCertificatesResponse, error) { func (c Certificates) List(ctx context.Context, params *ListCertificatesParams) (*ListCertificatesResponse, error) {
url := "/v1/product/certificate/list" url := "/v1/product/certificate/list"
resp := &ListCertificatesResponse{} resp := &ListCertificatesResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -329,21 +350,23 @@ type ProductStatusesResponse struct {
core.CommonResponse core.CommonResponse
// Product statuses // Product statuses
Result []struct { Result []ProductStatusesResult `json:"result"`
}
type ProductStatusesResult struct {
// Product status code when linking it to the certificate // Product status code when linking it to the certificate
Code string `json:"code"` Code string `json:"code"`
// Status description // Status description
Name string `json:"name"` Name string `json:"name"`
} `json:"result"`
} }
func (c Certificates) ProductStatuses() (*ProductStatusesResponse, error) { func (c Certificates) ProductStatuses(ctx context.Context) (*ProductStatusesResponse, error) {
url := "/v1/product/certificate/list" url := "/v1/product/certificate/list"
resp := &ProductStatusesResponse{} resp := &ProductStatusesResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -370,7 +393,10 @@ type ListProductsForCertificateResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ListProductsForCertificateResult `json:"result"`
}
type ListProductsForCertificateResult struct {
// List of products // List of products
Items []struct { Items []struct {
// Product identifier // Product identifier
@@ -382,16 +408,15 @@ type ListProductsForCertificateResponse struct {
// Number of products found // Number of products found
Count int64 `json:"count"` Count int64 `json:"count"`
} `json:"result"`
} }
// A method for getting a list of possible statuses of products when binding them to a certificate // A method for getting a list of possible statuses of products when binding them to a certificate
func (c Certificates) ListProductsForCertificate(params *ListProductsForCertificateParams) (*ListProductsForCertificateResponse, error) { func (c Certificates) ListProductsForCertificate(ctx context.Context, params *ListProductsForCertificateParams) (*ListProductsForCertificateResponse, error) {
url := "/v1/product/certificate/products/list" url := "/v1/product/certificate/products/list"
resp := &ListProductsForCertificateResponse{} resp := &ListProductsForCertificateResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -412,7 +437,10 @@ type UnlinkFromProductResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result []struct { Result []UnlinkFromProductResult `json:"result"`
}
type UnlinkFromProductResult struct {
// Error message when unbinding a product // Error message when unbinding a product
Error string `json:"error"` Error string `json:"error"`
@@ -423,16 +451,15 @@ type UnlinkFromProductResponse struct {
// - true — it was unbound, // - true — it was unbound,
// - false — it is still bound // - false — it is still bound
Updated bool `json:"updated"` Updated bool `json:"updated"`
} `json:"result"`
} }
// Unbind products from a certificate // Unbind products from a certificate
func (c Certificates) UnlinkFromProduct(params *UnlinkFromProductParams) (*UnlinkFromProductResponse, error) { func (c Certificates) UnlinkFromProduct(ctx context.Context, params *UnlinkFromProductParams) (*UnlinkFromProductResponse, error) {
url := "/v1/product/certificate/unbind" url := "/v1/product/certificate/unbind"
resp := &UnlinkFromProductResponse{} resp := &UnlinkFromProductResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -445,22 +472,24 @@ type PossibleRejectReasonsResponse struct {
core.CommonResponse core.CommonResponse
// Certificate rejection reasons // Certificate rejection reasons
Result []struct { Result []PossibleRejectReasonsResult `json:"result"`
}
type PossibleRejectReasonsResult struct {
// Сode of a certificate rejection reason // Сode of a certificate rejection reason
Code string `json:"code"` Code string `json:"code"`
// Description of a certificate rejection reason // Description of a certificate rejection reason
Name string `json:"name"` Name string `json:"name"`
} `json:"result"`
} }
// Possible certificate rejection reasons // Possible certificate rejection reasons
func (c Certificates) PossibleRejectReasons() (*PossibleRejectReasonsResponse, error) { func (c Certificates) PossibleRejectReasons(ctx context.Context) (*PossibleRejectReasonsResponse, error) {
url := "/v1/product/certificate/rejection_reasons/list" url := "/v1/product/certificate/rejection_reasons/list"
resp := &PossibleRejectReasonsResponse{} resp := &PossibleRejectReasonsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -473,21 +502,23 @@ type PossibleStatusesResponse struct {
core.CommonResponse core.CommonResponse
// Possible certificate statuses // Possible certificate statuses
Result []struct { Result []PossibleStatusesResult `json:"result"`
}
type PossibleStatusesResult struct {
// Certificate status code // Certificate status code
Code string `json:"code"` Code string `json:"code"`
// Status description // Status description
Name string `json:"name"` Name string `json:"name"`
} `json:"result"`
} }
func (c Certificates) PossibleStatuses() (*PossibleStatusesResponse, error) { func (c Certificates) PossibleStatuses(ctx context.Context) (*PossibleStatusesResponse, error) {
url := "/v1/product/certificate/status/list" url := "/v1/product/certificate/status/list"
resp := &PossibleStatusesResponse{} resp := &PossibleStatusesResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -526,12 +557,12 @@ type AddCertificatesForProductsResponse struct {
} }
// Adding certificates for products // Adding certificates for products
func (c Certificates) AddForProducts(params *AddCertificatesForProductsParams) (*AddCertificatesForProductsResponse, error) { func (c Certificates) AddForProducts(ctx context.Context, params *AddCertificatesForProductsParams) (*AddCertificatesForProductsResponse, error) {
url := "/v1/product/certificate/create" url := "/v1/product/certificate/create"
resp := &AddCertificatesForProductsResponse{} resp := &AddCertificatesForProductsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, map[string]string{ response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, map[string]string{
"Content-Type": "multipart/form-data", "Content-Type": "multipart/form-data",
}) })
if err != nil { if err != nil {

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
"time" "time"
@@ -51,7 +52,8 @@ func TestListOfAccordanceTypes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().ListOfAccordanceTypes() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().ListOfAccordanceTypes(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -113,7 +115,8 @@ func TestDirectoryOfDocumentTypes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().DirectoryOfDocumentTypes() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().DirectoryOfDocumentTypes(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -168,7 +171,8 @@ func TestListOfCertifiedCategories(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().ListOfCertifiedCategories(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().ListOfCertifiedCategories(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -215,7 +219,8 @@ func TestLinkCertificateToProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().LinkToProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().LinkToProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -264,7 +269,8 @@ func TestDeleteCertificate(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().Delete(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().Delete(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -322,7 +328,8 @@ func TestGetCertificateInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().GetInfo(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().GetInfo(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -395,7 +402,8 @@ func TestListCertificates(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().List(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().List(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -441,7 +449,8 @@ func TestProductStatuses(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().ProductStatuses() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().ProductStatuses(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -498,7 +507,8 @@ func TestListProductsForCertificate(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().ListProductsForCertificate(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().ListProductsForCertificate(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -551,7 +561,8 @@ func TestUnlinkFromProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().UnlinkFromProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().UnlinkFromProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -597,7 +608,8 @@ func TestPossibleRejectReasons(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().PossibleRejectReasons() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().PossibleRejectReasons(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -643,7 +655,8 @@ func TestPossibleStatuses(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().PossibleStatuses() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().PossibleStatuses(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -695,7 +708,8 @@ func TestAddCertificatesForProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Certificates().AddForProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Certificates().AddForProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -38,9 +39,30 @@ type ListChatsResponse struct {
core.CommonResponse core.CommonResponse
// Chats data // Chats data
Chats []struct { Chats []ListChatsChat `json:"chats"`
// Total number of chats
TotalChatsCount int64 `json:"total_chats_count"`
// Total number of unread messages
TotalUnreadCount int64 `json:"total_unread_count"`
}
type ListChatsChat struct {
// Chat data // Chat data
Chat struct { Chat ListChatsChatData `json:"chat"`
// Identifier of the first unread chat message
FirstUnreadMessageId string `json:"first_unread_message_id"`
// Identifier of the last message in the chat
LastMessageId string `json:"last_message_id"`
// Number of unread messages in the chat
UnreadCount int64 `json:"unread_count"`
}
type ListChatsChatData struct {
// Chat identifier // Chat identifier
ChatId string `json:"chat_id"` ChatId string `json:"chat_id"`
@@ -57,32 +79,15 @@ type ListChatsResponse struct {
// Chat creation date // Chat creation date
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} `json:"chat"`
// Identifier of the first unread chat message
FirstUnreadMessageId string `json:"first_unread_message_id"`
// Identifier of the last message in the chat
LastMessageId string `json:"last_message_id"`
// Number of unread messages in the chat
UnreadCount int64 `json:"unread_count"`
} `json:"chats"`
// Total number of chats
TotalChatsCount int64 `json:"total_chats_count"`
// Total number of unread messages
TotalUnreadCount int64 `json:"total_unread_count"`
} }
// Returns information about chats by specified filters // Returns information about chats by specified filters
func (c Chats) List(params *ListChatsParams) (*ListChatsResponse, error) { func (c Chats) List(ctx context.Context, params *ListChatsParams) (*ListChatsResponse, error) {
url := "/v2/chat/list" url := "/v2/chat/list"
resp := &ListChatsResponse{} resp := &ListChatsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -107,12 +112,12 @@ type SendMessageResponse struct {
} }
// Sends a message to an existing chat by its identifier // Sends a message to an existing chat by its identifier
func (c Chats) SendMessage(params *SendMessageParams) (*SendMessageResponse, error) { func (c Chats) SendMessage(ctx context.Context, params *SendMessageParams) (*SendMessageResponse, error) {
url := "/v1/chat/send/message" url := "/v1/chat/send/message"
resp := &SendMessageResponse{} resp := &SendMessageResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -140,12 +145,12 @@ type SendFileResponse struct {
} }
// Sends a file to an existing chat by its identifier // Sends a file to an existing chat by its identifier
func (c Chats) SendFile(params *SendFileParams) (*SendFileResponse, error) { func (c Chats) SendFile(ctx context.Context, params *SendFileParams) (*SendFileResponse, error) {
url := "/v1/chat/send/file" url := "/v1/chat/send/file"
resp := &SendFileResponse{} resp := &SendFileResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -179,7 +184,10 @@ type ChatHistoryResponse struct {
HasNext bool `json:"has_next"` HasNext bool `json:"has_next"`
// An array of messages sorted according to the direction parameter in the request body // An array of messages sorted according to the direction parameter in the request body
Messages []struct { Messages []ChatHistoryMessage `json:"messages"`
}
type ChatHistoryMessage struct {
// Message creation date // Message creation date
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
@@ -193,7 +201,10 @@ type ChatHistoryResponse struct {
MessageId string `json:"message_id"` MessageId string `json:"message_id"`
// Chat participant identifier // Chat participant identifier
User struct { User ChatHistoryMessageUser `json:"user"`
}
type ChatHistoryMessageUser struct {
// Chat participant identifier // Chat participant identifier
Id string `json:"id"` Id string `json:"id"`
@@ -204,17 +215,15 @@ type ChatHistoryResponse struct {
// - courier // - courier
// - support // - support
Type string `json:"type"` Type string `json:"type"`
} `json:"user"`
} `json:"messages"`
} }
// Chat history // Chat history
func (c Chats) History(params *ChatHistoryParams) (*ChatHistoryResponse, error) { func (c Chats) History(ctx context.Context, params *ChatHistoryParams) (*ChatHistoryResponse, error) {
url := "/v2/chat/history" url := "/v2/chat/history"
resp := &ChatHistoryResponse{} resp := &ChatHistoryResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -238,55 +247,18 @@ type UpdateChatResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result []struct { Result []UpdateChatResult `json:"result"`
}
type UpdateChatResult struct {
// An order or a product user wrote about in the chat // An order or a product user wrote about in the chat
Context struct { Context UpdateChatResultContext `json:"context"`
// Product inforamtion
Item struct {
// Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"`
} `json:"item"`
// Order information
Order struct {
// Order number
OrderNumber string `json:"order_number"`
// Shipment information
Postings []struct {
// Delivery scheme:
// - FBO
// - FBS
// - RFBS
// - Crossborder
DeliverySchema string `json:"delivery_schema"`
// Shipment number
PostingNumber string `json:"posting_number"`
// List of product identifiers in the shipment
SKUList []int64 `json:"sku_list"`
} `json:"postings"`
} `json:"order"`
} `json:"context"`
// Creation date and time // Creation date and time
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
// Information about the file in the chat. Displayed only for `type = file` // Information about the file in the chat. Displayed only for `type = file`
File struct { File UpdateChatResultFile `json:"file"`
// File type
Mime string `json:"mime"`
// File name
Name string `json:"name"`
// File size in bytes
Size int64 `json:"size"`
// File URL
URL string `json:"url"`
} `json:"file"`
// File identifier // File identifier
Id uint64 `json:"id"` Id uint64 `json:"id"`
@@ -300,7 +272,60 @@ type UpdateChatResponse struct {
Type string `json:"type"` Type string `json:"type"`
// Chat participant information // Chat participant information
User struct { User UpdateChatResultUser `json:"user"`
}
type UpdateChatResultContext struct {
// Product inforamtion
Item UpdateChatResultContextItem `json:"item"`
// Order information
Order UpdateChatResultContextOrder `json:"order"`
}
type UpdateChatResultContextItem struct {
// Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"`
}
type UpdateChatResultContextOrder struct {
// Order number
OrderNumber string `json:"order_number"`
// Shipment information
Postings []UpdateChatResultContextOrderPosting `json:"postings"`
}
type UpdateChatResultContextOrderPosting struct {
// Delivery scheme:
// - FBO
// - FBS
// - RFBS
// - Crossborder
DeliverySchema string `json:"delivery_schema"`
// Shipment number
PostingNumber string `json:"posting_number"`
// List of product identifiers in the shipment
SKUList []int64 `json:"sku_list"`
}
type UpdateChatResultFile struct {
// File type
Mime string `json:"mime"`
// File name
Name string `json:"name"`
// File size in bytes
Size int64 `json:"size"`
// File URL
URL string `json:"url"`
}
type UpdateChatResultUser struct {
// Chat participant identifier // Chat participant identifier
Id string `json:"id"` Id string `json:"id"`
@@ -310,17 +335,15 @@ type UpdateChatResponse struct {
// - crm—system messages // - crm—system messages
// - courier // - courier
Type string `json:"type"` Type string `json:"type"`
} `json:"user"`
} `json:"result"`
} }
// Update chat // Update chat
func (c Chats) Update(params *UpdateChatParams) (*UpdateChatResponse, error) { func (c Chats) Update(ctx context.Context, params *UpdateChatParams) (*UpdateChatResponse, error) {
url := "/v1/chat/updates" url := "/v1/chat/updates"
resp := &UpdateChatResponse{} resp := &UpdateChatResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -338,19 +361,21 @@ type CreateNewChatResponse struct {
core.CommonResponse core.CommonResponse
//Method result //Method result
Result struct { Result CreateNewChatResult `json:"result"`
}
type CreateNewChatResult struct {
// Chat identifier // Chat identifier
ChatId string `json:"chat_id"` ChatId string `json:"chat_id"`
} `json:"result"`
} }
// Creates a new chat on the shipment with the customer. For example, to clarify the address or the product model // Creates a new chat on the shipment with the customer. For example, to clarify the address or the product model
func (c Chats) Create(params *CreateNewChatParams) (*CreateNewChatResponse, error) { func (c Chats) Create(ctx context.Context, params *CreateNewChatParams) (*CreateNewChatResponse, error) {
url := "/v1/chat/start" url := "/v1/chat/start"
resp := &CreateNewChatResponse{} resp := &CreateNewChatResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -375,12 +400,12 @@ type MarkAsReadResponse struct {
} }
// A method for marking the selected message and messages before it as read // A method for marking the selected message and messages before it as read
func (c Chats) MarkAsRead(params *MarkAsReadParams) (*MarkAsReadResponse, error) { func (c Chats) MarkAsRead(ctx context.Context, params *MarkAsReadParams) (*MarkAsReadResponse, error) {
url := "/v2/chat/read" url := "/v2/chat/read"
resp := &MarkAsReadResponse{} resp := &MarkAsReadResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -61,7 +62,8 @@ func TestListChats(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().List(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().List(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -119,7 +121,8 @@ func TestSendMessage(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().SendMessage(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().SendMessage(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -167,7 +170,8 @@ func TestSendFile(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().SendFile(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().SendFile(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -230,7 +234,8 @@ func TestChatHistory(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().History(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().History(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -296,7 +301,8 @@ func TestUpdateChat(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().Update(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().Update(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -344,7 +350,8 @@ func TestCreateNewChat(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().Create(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().Create(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -397,7 +404,8 @@ func TestMarkAsRead(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Chats().MarkAsRead(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Chats().MarkAsRead(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,5 +1,11 @@
package ozon package ozon
import "time"
const (
testTimeout = 5 * time.Second
)
type Order string type Order string
const ( const (
@@ -37,13 +43,7 @@ const (
CancellationsMetric GetAnalyticsDataFilterMetric = "cancellations" CancellationsMetric GetAnalyticsDataFilterMetric = "cancellations"
OrderedUnits GetAnalyticsDataFilterMetric = "ordered_units" OrderedUnits GetAnalyticsDataFilterMetric = "ordered_units"
DeliveredUnits GetAnalyticsDataFilterMetric = "delivered_units" DeliveredUnits GetAnalyticsDataFilterMetric = "delivered_units"
AdvViewPDP GetAnalyticsDataFilterMetric = "adv_view_pdp"
AdvViewSearchCategory GetAnalyticsDataFilterMetric = "adv_view_search_category"
AdvViewAll GetAnalyticsDataFilterMetric = "adv_view_all"
AdvSumAll GetAnalyticsDataFilterMetric = "adv_sum_all"
PositionCategory GetAnalyticsDataFilterMetric = "position_category" PositionCategory GetAnalyticsDataFilterMetric = "position_category"
PostingsMetric GetAnalyticsDataFilterMetric = "postings"
PostingsPremium GetAnalyticsDataFilterMetric = "postings_premium"
) )
type WarehouseType string type WarehouseType string
@@ -377,3 +377,166 @@ const (
StrategyCreated StrategyUpdateType = "strategyCreated" StrategyCreated StrategyUpdateType = "strategyCreated"
StrategyItemsListChanged StrategyUpdateType = "strategyItemsListChanged" StrategyItemsListChanged StrategyUpdateType = "strategyItemsListChanged"
) )
type ShipmentCertificateFilterStatus string
const (
// new
ShitmentCertificateFilterNew ShipmentCertificateFilterStatus = "new"
// retry creation
ShitmentCertificateFilterAwaitingRetry ShipmentCertificateFilterStatus = "awaiting-retry"
// is being packaged
ShitmentCertificateFilterInProcess ShipmentCertificateFilterStatus = "in_process"
// created
ShitmentCertificateFilterSuccess ShipmentCertificateFilterStatus = "success"
// creation error
ShitmentCertificateFilterError ShipmentCertificateFilterStatus = "error"
// sent
ShitmentCertificateFilterSend ShipmentCertificateFilterStatus = "sent"
// received
ShitmentCertificateFilterReceived ShipmentCertificateFilterStatus = "received"
// packaged
ShitmentCertificateFilterFormed ShipmentCertificateFilterStatus = "formed"
// canceled
ShitmentCertificateFilterCancelled ShipmentCertificateFilterStatus = "cancelled"
// in the queue for packaging
ShitmentCertificateFilterPending ShipmentCertificateFilterStatus = "pending"
// in the queue for completion
ShitmentCertificateFilterCompletionEnqueued ShipmentCertificateFilterStatus = "completion_enqueued"
// in the process of completion
ShitmentCertificateFilterCompletionProcessing ShipmentCertificateFilterStatus = "completion_processing"
// completion error
ShitmentCertificateFilterCompletionFailed ShipmentCertificateFilterStatus = "completion_failed"
// in the queue for cancellation
ShitmentCertificateFilterCancelationEnqueued ShipmentCertificateFilterStatus = "cancelation_enqueued"
// in the process of cancellation
ShitmentCertificateFilterCancelationProcessing ShipmentCertificateFilterStatus = "cancelation_processing"
// cancellation error
ShitmentCertificateFilterCancelationFailed ShipmentCertificateFilterStatus = "cancelation_failed"
// completed
ShitmentCertificateFilterCompleted ShipmentCertificateFilterStatus = "completed"
// closed
ShitmentCertificateFilterClosed ShipmentCertificateFilterStatus = "closed"
)
type PRROptionStatus string
const (
// carrying the bulky product using the elevator
PRROptionLift PRROptionStatus = "lift"
// carrying the bulky product upstairs
PRROptionStairs PRROptionStatus = "stairs"
// the customer canceled the service,
// you don't need to lift the shipment
PRROptionNone PRROptionStatus = "none"
// delivery is included in the price.
// According to the offer you need to
// deliver products to the floor
PRROptionDeliveryDefault PRROptionStatus = "delivery_default"
)
type GetFBSReturnsFilterStatus string
const (
ReturnedToSeller GetFBSReturnsFilterStatus = "returned_to_seller"
WaitingForSeller GetFBSReturnsFilterStatus = "waiting_for_seller"
AcceptedFromCustomer GetFBSReturnsFilterStatus = "accepted_from_customer"
CancelledWithCompensation GetFBSReturnsFilterStatus = "cancelled_with_compensation"
ReadyForShipment GetFBSReturnsFilterStatus = "ready_for_shipment"
)
type GetFBOReturnsFilterStatus string
const (
GetFBOReturnsFilterStatusReturnedToOzon GetFBOReturnsFilterStatus = "ReturnedToOzon"
GetFBOReturnsFilterStatusCancelled GetFBOReturnsFilterStatus = "Cancelled"
)
type GetFBOReturnsReturnStatus string
const (
GetFBOReturnsReturnStatusCancelled GetFBOReturnsReturnStatus = "Возврат отменен"
GetFBOReturnsReturnStatusAcceptedFromCustomer GetFBOReturnsReturnStatus = "Принят от покупателя"
GetFBOReturnsReturnStatusReceivedAtOzon GetFBOReturnsReturnStatus = "Получен в Ozon"
)
type DigitalActType string
const (
// acceptance certificate
DigitalActTypeOfAcceptance DigitalActType = "act_of_acceptance"
// discrepancy certificate
DigitalActTypeOfMismatch DigitalActType = "act_of_mismatch"
// surplus certificate
DigitalActTypeOfExcess DigitalActType = "act_of_excess"
)
type PriceStrategy string
const (
// enable
PriceStrategyEnabled PriceStrategy = "ENABLED"
// disable
PriceStrategyDisabled PriceStrategy = "DISABLED"
// don't change anything. Default value
PriceStrategyUnknown PriceStrategy = "UNKNOWN"
)
type FBPFilter string
const (
// all shipments matching other filters will be returned in the response
FBPFilterAll FBPFilter = "all"
// only FBP shipments will be returned
FBPFilterOnly FBPFilter = "only"
// all shipments except FBP will be returned
FBPFilterWithout FBPFilter = "without"
)
type InvoiceCurrency string
const (
// dollar
InvoiceCurrencyUSD InvoiceCurrency = "USD"
// euro
InvoiceCurrencyEUR InvoiceCurrency = "EUR"
// Turkish lira
InvoiceCurrencyTRY InvoiceCurrency = "TRY"
// yuan
InvoiceCurrencyCNY InvoiceCurrency = "CNY"
// ruble
InvoiceCurrencyRUB InvoiceCurrency = "RUB"
// pound sterling
InvoiceCurrencyGBP InvoiceCurrency = "GBP"
)

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -56,41 +57,15 @@ type GetFBOShipmentsListResponse struct {
core.CommonResponse core.CommonResponse
// Shipments list // Shipments list
Result []struct { Result []GetFBOShipmentsListResult `json:"result"`
}
type GetFBOShipmentsListResult struct {
// Additional data for shipment list // Additional data for shipment list
AdditionalData []struct { AdditionalData []GetFBOShipmentsListResultAdditionalData `json:"additional_data"`
Key string `json:"key"`
Value string `json:"value"`
} `json:"additional_data"`
// Analytical data // Analytical data
AnalyticsData struct { AnalyticsData GetFBOShipmentsListResultAnalyticsData `json:"analytics_data"`
// Delivery city
City string `json:"city"`
// Delivery method
DeliveryType string `json:"delivery_type"`
// Indication that the recipient is a legal person
// * true — a legal person,
// * false — a natural person.
IsLegal bool `json:"is_legal"`
// Premium subscription
IsPremium bool `json:"is_premium"`
// Payment method
PaymentTypeGroupName string `json:"payment_type_group_name"`
// Delivery region
Region string `json:"region"`
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
// Name of the warehouse from which the order is shipped
WarehouseName string `json:"warehouse_name"`
} `json:"analytics_data"`
// Shipment cancellation reason identifier // Shipment cancellation reason identifier
CancelReasonId int64 `json:"cancel_reason_id"` CancelReasonId int64 `json:"cancel_reason_id"`
@@ -118,7 +93,39 @@ type GetFBOShipmentsListResponse struct {
// Shipment status // Shipment status
Status string `json:"status"` Status string `json:"status"`
} `json:"result"` }
type GetFBOShipmentsListResultAdditionalData struct {
Key string `json:"key"`
Value string `json:"value"`
}
type GetFBOShipmentsListResultAnalyticsData struct {
// Delivery city
City string `json:"city"`
// Delivery method
DeliveryType string `json:"delivery_type"`
// Indication that the recipient is a legal person
// * true — a legal person,
// * false — a natural person.
IsLegal bool `json:"is_legal"`
// Premium subscription
IsPremium bool `json:"is_premium"`
// Payment method
PaymentTypeGroupName string `json:"payment_type_group_name"`
// Delivery region
Region string `json:"region"`
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
// Name of the warehouse from which the order is shipped
WarehouseName string `json:"warehouse_name"`
} }
type FBOPostingProduct struct { type FBOPostingProduct struct {
@@ -159,12 +166,12 @@ type FBOFinancialData struct {
} }
// Returns a list of shipments for a specified period of time. You can additionally filter the shipments by their status // Returns a list of shipments for a specified period of time. You can additionally filter the shipments by their status
func (c FBO) GetShipmentsList(params *GetFBOShipmentsListParams) (*GetFBOShipmentsListResponse, error) { func (c FBO) GetShipmentsList(ctx context.Context, params *GetFBOShipmentsListParams) (*GetFBOShipmentsListResponse, error) {
url := "/v2/posting/fbo/list" url := "/v2/posting/fbo/list"
resp := &GetFBOShipmentsListResponse{} resp := &GetFBOShipmentsListResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -196,41 +203,15 @@ type GetShipmentDetailsResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetShipmentDetailsResult `json:"result"`
}
type GetShipmentDetailsResult struct {
// Additional data // Additional data
AdditionalData []struct { AdditionalData []GetShipmentDetailsResultAdditionalData `json:"additional_data"`
Key string `json:"key"`
Value string `json:"value"`
} `json:"additional_data"`
// Analytical data // Analytical data
AnalyticsData struct { AnalyticsData GetShipmentDetailsResultAnalyticsData `json:"analytics_data"`
// Delivery city
City string `json:"Delivery city"`
// Delivery method
DeliveryType string `json:"delivery_type"`
// Indication that the recipient is a legal person:
// - true — a legal person
// - false — a natural person
IsLegal bool `json:"is_legal"`
// Premium subscription
IsPremium bool `json:"is_premium"`
// Payment method
PaymentTypeGroupName string `json:"payment_type_group_name"`
// Delivery region
Region string `json:"region"`
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
// Name of the warehouse from which the order is shipped
WarehouseName string `json:"warehouse_name"`
} `json:"analytics_data"`
// Shipment cancellation reason identifier // Shipment cancellation reason identifier
CancelReasonId int64 `json:"cancel_reason_id"` CancelReasonId int64 `json:"cancel_reason_id"`
@@ -258,16 +239,48 @@ type GetShipmentDetailsResponse struct {
// Shipment status // Shipment status
Status string `json:"status"` Status string `json:"status"`
} `json:"result"` }
type GetShipmentDetailsResultAdditionalData struct {
Key string `json:"key"`
Value string `json:"value"`
}
type GetShipmentDetailsResultAnalyticsData struct {
// Delivery city
City string `json:"Delivery city"`
// Delivery method
DeliveryType string `json:"delivery_type"`
// Indication that the recipient is a legal person:
// - true — a legal person
// - false — a natural person
IsLegal bool `json:"is_legal"`
// Premium subscription
IsPremium bool `json:"is_premium"`
// Payment method
PaymentTypeGroupName string `json:"payment_type_group_name"`
// Delivery region
Region string `json:"region"`
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
// Name of the warehouse from which the order is shipped
WarehouseName string `json:"warehouse_name"`
} }
// Returns information about the shipment by its identifier // Returns information about the shipment by its identifier
func (c FBO) GetShipmentDetails(params *GetShipmentDetailsParams) (*GetShipmentDetailsResponse, error) { func (c FBO) GetShipmentDetails(ctx context.Context, params *GetShipmentDetailsParams) (*GetShipmentDetailsResponse, error) {
url := "/v2/posting/fbo/get" url := "/v2/posting/fbo/get"
resp := &GetShipmentDetailsResponse{} resp := &GetShipmentDetailsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -307,13 +320,7 @@ type SupplyRequestCommonResponse struct {
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
// Local time supply interval // Local time supply interval
LocalTimeslot struct { LocalTimeslot SupplyRequestCommonResponseLocalTimeslot `json:"local_timeslot"`
// Interval start
From string `json:"from"`
// Interval end
To string `json:"to"`
} `json:"local_timeslot"`
// Date from which you want to bring the supply to the warehouse. Only for supplies via vDC // Date from which you want to bring the supply to the warehouse. Only for supplies via vDC
PreferredSupplyDataFrom string `json:"preferred_supply_data_from"` PreferredSupplyDataFrom string `json:"preferred_supply_data_from"`
@@ -331,16 +338,7 @@ type SupplyRequestCommonResponse struct {
SupplyOrderNumber string `json:"supply_order_number"` SupplyOrderNumber string `json:"supply_order_number"`
// Supply warehouse // Supply warehouse
SupplyWarehouse struct { SupplyWarehouse SupplyRequestCommonResponseSupplyWarehouse `json:"supply_warehouse"`
// Warehouse address
Address string `json:address"`
// Warehouse name
Name string `json:"name"`
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
} `json:"supply_warehouse"`
// time_left_to_prepare_supply // time_left_to_prepare_supply
TimeLeftToPrepareSupply int64 `json:"time_left_to_prepare_supply"` TimeLeftToPrepareSupply int64 `json:"time_left_to_prepare_supply"`
@@ -355,15 +353,34 @@ type SupplyRequestCommonResponse struct {
TotalQuantity int32 `json:"total_quantity"` TotalQuantity int32 `json:"total_quantity"`
} }
type SupplyRequestCommonResponseLocalTimeslot struct {
// Interval start
From string `json:"from"`
// Interval end
To string `json:"to"`
}
type SupplyRequestCommonResponseSupplyWarehouse struct {
// Warehouse address
Address string `json:"address"`
// Warehouse name
Name string `json:"name"`
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
}
// Method for getting a list of supply requests to the Ozon warehouse. // Method for getting a list of supply requests to the Ozon warehouse.
// Requests with supply both to a specific warehouse and via a virtual // Requests with supply both to a specific warehouse and via a virtual
// distribution center (vDC) are taken into account // distribution center (vDC) are taken into account
func (c FBO) ListSupplyRequests(params *ListSupplyRequestsParams) (*ListSupplyRequestsResponse, error) { func (c FBO) ListSupplyRequests(ctx context.Context, params *ListSupplyRequestsParams) (*ListSupplyRequestsResponse, error) {
url := "/v1/supply-order/list" url := "/v1/supply-order/list"
resp := &ListSupplyRequestsResponse{} resp := &ListSupplyRequestsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -383,7 +400,10 @@ type GetSupplyRequestInfoResponse struct {
SupplyRequestCommonResponse SupplyRequestCommonResponse
// Driver and car information // Driver and car information
VehicleInfo struct { VehicleInfo GetSupplyRequestInfoVehicle `json:"vehicle_info"`
}
type GetSupplyRequestInfoVehicle struct {
// Driver name // Driver name
DriverName string `json:"driver_name"` DriverName string `json:"driver_name"`
@@ -395,18 +415,17 @@ type GetSupplyRequestInfoResponse struct {
// Car number // Car number
VehicleNumber string `json:"vehicle_number"` VehicleNumber string `json:"vehicle_number"`
} `json:"vehicle_info"`
} }
// Method for getting detailed information on a supply request. // Method for getting detailed information on a supply request.
// Requests with supply both to a specific warehouse and via a // Requests with supply both to a specific warehouse and via a
// virtual distribution center (vDC) are taken into account // virtual distribution center (vDC) are taken into account
func (c FBO) GetSupplyRequestInfo(params *GetSupplyRequestInfoParams) (*GetSupplyRequestInfoResponse, error) { func (c FBO) GetSupplyRequestInfo(ctx context.Context, params *GetSupplyRequestInfoParams) (*GetSupplyRequestInfoResponse, error) {
url := "/v1/supply-order/get" url := "/v1/supply-order/get"
resp := &GetSupplyRequestInfoResponse{} resp := &GetSupplyRequestInfoResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -435,7 +454,13 @@ type ListProductsInSupplyRequestResponse struct {
HasNext bool `json:"has_next"` HasNext bool `json:"has_next"`
// Products list // Products list
Items []struct { Items []ListProductsInSupplyRequestItem `json:"items"`
// Total number of products in the request
TotalItemsCount int32 `json:"total_items_count"`
}
type ListProductsInSupplyRequestItem struct {
// Link to product image // Link to product image
IconPath string `json:"icon_path"` IconPath string `json:"icon_path"`
@@ -450,19 +475,15 @@ type ListProductsInSupplyRequestResponse struct {
// Product identifier in the Ozon system, SKU // Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"` SKU int64 `json:"sku"`
} `json:"items"`
// Total number of products in the request
TotalItemsCount int32 `json:"total_items_count"`
} }
// List of products in the sullpy request // List of products in the sullpy request
func (c FBO) ListProductsInSupplyRequest(params *ListProductsInSupplyRequestParams) (*ListProductsInSupplyRequestResponse, error) { func (c FBO) ListProductsInSupplyRequest(ctx context.Context, params *ListProductsInSupplyRequestParams) (*ListProductsInSupplyRequestResponse, error) {
url := "/v1/supply-order/items" url := "/v1/supply-order/items"
resp := &ListProductsInSupplyRequestResponse{} resp := &ListProductsInSupplyRequestResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -475,11 +496,26 @@ type GetWarehouseWorkloadResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result []struct { Result []GetWarehouseWorkloadResult `json:"result"`
}
type GetWarehouseWorkloadResult struct {
// Workload // Workload
Schedule struct { Schedule GetWarehouseWorkloadResultSchedule `json:"schedule"`
// Warehouse
Warehouse GetWarehouseWorkloadResultWarehouse `json:"warehouse"`
}
type GetWarehouseWorkloadResultSchedule struct {
// Data on the products quantity supplied to the warehouse // Data on the products quantity supplied to the warehouse
Capacity []struct { Capacity []GetWarehouseWorkloadResultScheduleCapacity `json:"capacity"`
// The closest available date for supply, local time
Date time.Time `json:"date"`
}
type GetWarehouseWorkloadResultScheduleCapacity struct {
// Period start, local time // Period start, local time
Start time.Time `json:"start"` Start time.Time `json:"start"`
@@ -488,30 +524,23 @@ type GetWarehouseWorkloadResponse struct {
// Average number of products that the warehouse can accept per day for the period // Average number of products that the warehouse can accept per day for the period
Value int32 `json:"value"` Value int32 `json:"value"`
} `json:"capacity"` }
// The closest available date for supply, local time type GetWarehouseWorkloadResultWarehouse struct {
Date time.Time `json:"date"`
} `json:"schedule"`
// Warehouse
Warehouse struct {
// Warehouse identifier // Warehouse identifier
Id string `json:"id"` Id string `json:"id"`
// Warehouse name // Warehouse name
Name string `json:"name"` Name string `json:"name"`
} `json:"warehouse"`
} `json:"result"`
} }
// Method returns a list of active Ozon warehouses with information about their average workload in the nearest future // Method returns a list of active Ozon warehouses with information about their average workload in the nearest future
func (c FBO) GetWarehouseWorkload() (*GetWarehouseWorkloadResponse, error) { func (c FBO) GetWarehouseWorkload(ctx context.Context) (*GetWarehouseWorkloadResponse, error) {
url := "/v1/supplier/available_warehouses" url := "/v1/supplier/available_warehouses"
resp := &GetWarehouseWorkloadResponse{} resp := &GetWarehouseWorkloadResponse{}
response, err := c.client.Request(http.MethodGet, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodGet, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -43,8 +44,8 @@ func TestGetFBOShipmentsList(t *testing.T) {
"posting_number": "16965409-0014-1", "posting_number": "16965409-0014-1",
"status": "delivered", "status": "delivered",
"cancel_reason_id": 0, "cancel_reason_id": 0,
"created_at": "2021-09-01T00:23:45.607Z", "created_at": "2021-09-01T00:23:45.607000Z",
"in_process_at": "2021-09-01T00:25:30.120Z", "in_process_at": "2021-09-01T00:25:30.120000Z",
"products": [ "products": [
{ {
"sku": 160249683, "sku": 160249683,
@@ -133,7 +134,8 @@ func TestGetFBOShipmentsList(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBO().GetShipmentsList(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBO().GetShipmentsList(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -261,7 +263,8 @@ func TestGetShipmentDetails(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBO().GetShipmentDetails(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBO().GetShipmentDetails(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -339,7 +342,8 @@ func TestListSupplyRequests(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBO().ListSupplyRequests(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBO().ListSupplyRequests(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -414,7 +418,8 @@ func TestGetSupplyRequestInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBO().GetSupplyRequestInfo(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBO().GetSupplyRequestInfo(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -472,7 +477,8 @@ func TestListProductsInSupplyRequest(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBO().ListProductsInSupplyRequest(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBO().ListProductsInSupplyRequest(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -530,7 +536,8 @@ func TestGetWarehouseWorkload(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBO().GetWarehouseWorkload() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBO().GetWarehouseWorkload(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -167,7 +168,8 @@ func TestListUnprocessedShipments(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ListUnprocessedShipments(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ListUnprocessedShipments(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -278,7 +280,8 @@ func TestGetFBSShipmentsList(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetFBSShipmentsList(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetFBSShipmentsList(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -339,7 +342,8 @@ func TestPackOrder(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().PackOrder(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().PackOrder(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -416,7 +420,8 @@ func TestValidateLabelingCodes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ValidateLabelingCodes(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ValidateLabelingCodes(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -529,7 +534,8 @@ func TestGetShipmentDataByBarcode(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetShipmentDataByBarcode(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetShipmentDataByBarcode(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -642,7 +648,8 @@ func TestGetShipmentDataByIdentifier(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetShipmentDataByIdentifier(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetShipmentDataByIdentifier(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -714,7 +721,8 @@ func TestAddTrackingNumbers(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().AddTrackingNumbers(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().AddTrackingNumbers(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -751,11 +759,11 @@ func TestListOfShipmentCertificates(t *testing.T) {
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&ListOfShipmentCertificatesParams{ &ListOfShipmentCertificatesParams{
Limit: 100, Limit: 100,
Filter: ListOfShipmentCertificates{ Filter: ListOfShipmentCertificatesFilter{
DateFrom: "2021-08-04", DateFrom: "2021-08-04",
DateTo: "2022-08-04", DateTo: "2022-08-04",
IntegrationType: "ozon", IntegrationType: "ozon",
Status: []string{"delivered"}, Status: []ShipmentCertificateFilterStatus{ShitmentCertificateFilterFormed},
}, },
}, },
`{ `{
@@ -807,7 +815,8 @@ func TestListOfShipmentCertificates(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ListOfShipmentCertificates(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ListOfShipmentCertificates(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -868,7 +877,8 @@ func TestSignShipmentCertificate(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().SignShipmentCertificate(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().SignShipmentCertificate(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -943,22 +953,26 @@ func TestChangeStatusTo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
deliveringResp, err := c.FBS().ChangeStatusToDelivering(test.params) deliveringctx, _ := context.WithTimeout(context.Background(), testTimeout)
deliveringResp, err := c.FBS().ChangeStatusToDelivering(deliveringctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
lastMileResp, err := c.FBS().ChangeStatusToLastMile(test.params) lastMilectx, _ := context.WithTimeout(context.Background(), testTimeout)
lastMileResp, err := c.FBS().ChangeStatusToLastMile(lastMilectx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
deliveredResp, err := c.FBS().ChangeStatusToDelivered(test.params) deliveredctx, _ := context.WithTimeout(context.Background(), testTimeout)
deliveredResp, err := c.FBS().ChangeStatusToDelivered(deliveredctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
sendBySellerResp, err := c.FBS().ChangeStatusToSendBySeller(test.params) sendBySellerctx, _ := context.WithTimeout(context.Background(), testTimeout)
sendBySellerResp, err := c.FBS().ChangeStatusToSendBySeller(sendBySellerctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1005,7 +1019,8 @@ func TestPassShipmentToShipping(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().PassShipmentToShipping(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().PassShipmentToShipping(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1053,7 +1068,8 @@ func TestCancelShipment(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().CancelShipment(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().CancelShipment(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1103,7 +1119,8 @@ func TestCreateAct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().CreateAct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().CreateAct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1132,9 +1149,8 @@ func TestGetLabeling(t *testing.T) {
}, },
`{ `{
"result": { "result": {
"error": "24", "status": "completed",
"file_url": "some-url", "file_url": "https://cdn1.ozone.ru/s3/sc-temporary/e6/0c/e60cdfd7aed78c2b44d134504fbd591d.pdf"
"status": "completed"
} }
}`, }`,
}, },
@@ -1153,7 +1169,8 @@ func TestGetLabeling(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetLabeling(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetLabeling(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1186,7 +1203,9 @@ func TestPrintLabeling(t *testing.T) {
PostingNumber: []string{"48173252-0034-4"}, PostingNumber: []string{"48173252-0034-4"},
}, },
`{ `{
"content": "https://cdn1.ozone.ru/s3/ozon-disk-api/c4a11c8b748033daf6cdd44aca7ed4c492e55d6f4810f13feae4792afa7934191647255705" "content_type": "application/pdf",
"file_name": "ticket-170660-2023-07-13T13:17:06Z.pdf",
"file_content": "%PDF-1.7\n%âãÏÓ\n53 0 obj\n<</MarkInfo<</Marked true/Type/MarkInfo>>/Pages 9 0 R/StructTreeRoot 10 0 R/Type/Catalog>>\nendobj\n8 0 obj\n<</Filter/FlateDecode/Length 2888>>\nstream\nxœå[[ݶ\u0011~?¿BÏ\u0005Bs†\u001c^\u0000Àwí5ú\u0010 m\u0016Èsà¦)\n;hÒ\u0014èÏïG‰\u0014)‰<{äµ] ]?¬¬oIÎ}†¤F±‰óϤñï\u001bÕü×X­´OÏï?^~¹$<ø¨È9q\u0013Y\u0012åñì§_¼|ÿ‡égü\t+\u0012\u001bxžª}Æxšҿ¿¼›–‡_º¼xg¦Ÿþ5Oku˜œÌ3ýíògüûå\"Ni\u0016C\u0001°\u000fA9g‰'r¢\"\u0013YóĪ\u0018NÑ{\u001d–ÕóZ¬\\Ô\""
}`, }`,
}, },
// Test No Client-Id or Api-Key // Test No Client-Id or Api-Key
@@ -1204,7 +1223,8 @@ func TestPrintLabeling(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().PrintLabeling(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().PrintLabeling(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1212,6 +1232,12 @@ func TestPrintLabeling(t *testing.T) {
if resp.StatusCode != test.statusCode { if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
} }
if resp.StatusCode == http.StatusOK {
if resp.Content == "" {
t.Error("content cannot be empty")
}
}
} }
} }
@@ -1252,7 +1278,8 @@ func TestCreateTaskForGeneratingLabel(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().CreateTaskForGeneratingLabel(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().CreateTaskForGeneratingLabel(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1312,7 +1339,8 @@ func TestGetDropOffPointRestrictions(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetDropOffPointRestrictions(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetDropOffPointRestrictions(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1372,7 +1400,8 @@ func TestCheckProductItemsData(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().CheckproductItemsData(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().CheckproductItemsData(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1435,7 +1464,8 @@ func TestGetProductItemsCheckStatuses(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetProductItemsCheckStatuses(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetProductItemsCheckStatuses(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1480,8 +1510,8 @@ func TestRescheduleShipmentDeliveryDate(t *testing.T) {
&RescheduleShipmentDeliveryDateParams{ &RescheduleShipmentDeliveryDateParams{
PostingNumber: "23281294-0063-2", PostingNumber: "23281294-0063-2",
NewTimeslot: RescheduleShipmentDeliveryDateTimeslot{ NewTimeslot: RescheduleShipmentDeliveryDateTimeslot{
DeliveryDateBegin: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2023-03-03T11:07:00.381Z"), From: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2023-03-25T08:51:56.932Z"),
DeliveryDateEnd: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2023-03-03T11:07:00.381Z"), To: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2023-03-25T08:51:56.932Z"),
}, },
}, },
`{ `{
@@ -1503,7 +1533,8 @@ func TestRescheduleShipmentDeliveryDate(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().RescheduleShipmentDeliveryDate(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().RescheduleShipmentDeliveryDate(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1554,7 +1585,8 @@ func TestDateAvailableForDeliverySchedule(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().DateAvailableForDeliverySchedule(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().DateAvailableForDeliverySchedule(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1613,7 +1645,8 @@ func TestListManufactoruingCountries(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ListManufacturingCountries(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ListManufacturingCountries(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1673,7 +1706,8 @@ func TestSetManufacturingCountry(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().SetManufacturingCountry(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().SetManufacturingCountry(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1740,7 +1774,8 @@ func TestPartialPackOrder(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().PartialPackOrder(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().PartialPackOrder(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1812,7 +1847,8 @@ func TestAvailableFreightsList(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().AvailableFreightsList(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().AvailableFreightsList(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1859,7 +1895,8 @@ func TestGenerateAct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GenerateAct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GenerateAct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1888,9 +1925,9 @@ func TestGetDigitalAct(t *testing.T) {
DocType: "act_of_acceptance", DocType: "act_of_acceptance",
}, },
`{ `{
"content": "string", "content_type": "application/pdf",
"name": "string", "file_name": "20816409_act_of_mismatch.pdf",
"type": "string" "file_content": "%PDF-1.4\n%ÓôÌá\n1 0 obj\n<<\n/Creator(Chromium)\n/Producer(PDFsharp 1.50.5147 \\([www.pdfsharp.com|http://www.pdfsharp.com/]\\) \\(Original: Skia/PDF m103\\))\n/CreationDate(D:20230625092529+00'00')\n/ModDate(D:20230625092529+00'00')\n>>\nendobj\n2 0 obj\n<<\n/Type/Page\n/Resources\n<<\n/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]\n/ExtGState\n<<\n/G3 3 0 R\n/G8 8 0 R\n>>\n/XObject\n<<\n/X6 6 0 R\n/X7 7 0 R\n>>\n/Font\n<<\n/F4 4 0 R\n/F5 5 0 R\n>>\n>>\n/MediaBox[0 0 594.96 841.92]\n/Contents 9 0 R\n/StructParents 0\n/Parent 13 0 R\n/Group\n<<\n/CS/DeviceRGB\n/S/Transparency\n>>\n>>\nendobj\n3 0 obj\n<<\n/ca 1\n/BM/Normal\n>>\nendobj\n4 0 obj\n<<\n/Type/Font\n/Subtype/Type0\n/BaseFont/AAAAAA+LiberationSans\n/Encoding/Identity-H\n/DescendantFonts[160 0 R]\n/ToUnicode 161 0 R\n>>\nendobj\n5 0 obj\n<<\n/Type/Font\n/Subtype/Type0\n/BaseFont/BAAAAA+LiberationSans-Bold\n/Encoding/Identity-H\n/DescendantFonts[164 0"
}`, }`,
}, },
// Test No Client-Id or Api-Key // Test No Client-Id or Api-Key
@@ -1908,7 +1945,8 @@ func TestGetDigitalAct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().GetDigitalAct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetDigitalAct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1962,7 +2000,8 @@ func TestPackageUnitLabels(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().PackageUnitLabel(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().PackageUnitLabel(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2014,7 +2053,8 @@ func TestOpenDisputeOverShipment(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().OpenDisputeOverShipment(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().OpenDisputeOverShipment(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2081,7 +2121,8 @@ func TestShipmentCancellationReasons(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ShipmentCancellationReasons(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ShipmentCancellationReasons(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2176,7 +2217,8 @@ func TestShipmentsCancellationReasons(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ShipmentsCancellationReasons() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ShipmentsCancellationReasons(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2237,7 +2279,8 @@ func TestAddWeightForBulkProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().AddWeightForBulkProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().AddWeightForBulkProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2297,7 +2340,8 @@ func TestCancelSending(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().CancelSending(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().CancelSending(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2362,7 +2406,8 @@ func TestListShipmentInCertificate(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ListShipmentInCertificate(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ListShipmentInCertificate(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2410,7 +2455,8 @@ func TestSpecifyNumberOfBoxes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().SpecifyNumberOfBoxes(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().SpecifyNumberOfBoxes(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2458,7 +2504,8 @@ func TestStatusOfAct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().StatusOfAct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().StatusOfAct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2516,7 +2563,8 @@ func TestETGBCustomsDeclarations(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.FBS().ETGBCustomsDeclarations(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().ETGBCustomsDeclarations(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2526,3 +2574,172 @@ func TestETGBCustomsDeclarations(t *testing.T) {
} }
} }
} }
func TestBarcodeFromProductShipment(t *testing.T) {
t.Parallel()
tests := []struct {
statusCode int
headers map[string]string
params *BarcodeFromProductShipmentParams
response string
}{
// Test Ok
{
http.StatusOK,
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&BarcodeFromProductShipmentParams{
Id: 295662811,
},
`{
"content_type": "image/png",
"file_name": "20913984_barcode.png",
"file_content": "‰PNG\r\n\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0003\u0010\u0000\u0000\u0000\u0010\u0000\u0000\u0000\u0000íZ\u000e'\u0000\u0000\u0002pIDATxœìÕÁJ\u00031\u0014@Q+þÿ/×E\u0017\u000e¼›\u0010u¡-ç¬$£Éˌp?î÷·§t» }ýü¸ÃcåzŸ¹2w˜OWû\\Ϛ뫧×Ùö;œì|rÇýßîç¼úî{˜§¬N?™í7oì•v¸®Ÿµ¹Ãù„û•¹¾ÿÏ9ÿî?›až¸ºéê7O&߿É9çÉ\u000eÏáý¯\u0007\u0000à\u0012\b\u0000’@\u0000\u0004\u0002€$\u0010\u0000$\u0000 \t\u0004\u0000I \u0000H\u0002\u0001@\u0012\b\u0000’@\u0000\u0004\u0002€$\u0010\u0000$\u0000 \t\u0004\u0000I \u0000H\u0002\u0001@\u0012\b\u0000’@\u0000\u0004\u0002€$\u0010\u0000$\u0000 \t\u0004\u0000I \u0000H\u0002\u0001@\u0012\b\u0000’@\u0000\u0004\u0002€$\u0010\u0000$\u0000 \t\u0004\u0000I \u0000H\u0002\u0001@\u0012\b\u0000’@\u0000\u0004\u0002€$\u0010\u0000"
}`,
},
// Test No Client-Id or Api-Key
{
http.StatusUnauthorized,
map[string]string{},
&BarcodeFromProductShipmentParams{},
`{
"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))
ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().BarcodeFromProductShipment(ctx, 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)
}
if resp.StatusCode == http.StatusOK {
if resp.Content == "" {
t.Errorf("content cannot be empty")
}
if resp.Type == "" {
t.Error("type cannot be empty")
}
if resp.Name == "" {
t.Error("name cannot be empty")
}
}
}
}
func TestBarcodeValueFromProductShipment(t *testing.T) {
t.Parallel()
tests := []struct {
statusCode int
headers map[string]string
params *BarcodeValueFromProductShipmentParams
response string
}{
// Test Ok
{
http.StatusOK,
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&BarcodeValueFromProductShipmentParams{
Id: 295662811,
},
`{
"result": "%303%24276481394"
}`,
},
// Test No Client-Id or Api-Key
{
http.StatusUnauthorized,
map[string]string{},
&BarcodeValueFromProductShipmentParams{},
`{
"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))
ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().BarcodeValueFromProductShipment(ctx, 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)
}
if resp.StatusCode == http.StatusOK {
if resp.Result == "" {
t.Errorf("result cannot be empty")
}
}
}
}
func TestGetActPDF(t *testing.T) {
t.Parallel()
tests := []struct {
statusCode int
headers map[string]string
params *GetActPDFParams
response string
}{
// Test Ok
{
http.StatusOK,
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&GetActPDFParams{
Id: 22435521842000,
},
`{
"content_type": "application/pdf",
"file_name": "20928233.pdf",
"file_content": "binarystring"
}`,
},
// Test No Client-Id or Api-Key
{
http.StatusUnauthorized,
map[string]string{},
&GetActPDFParams{},
`{
"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))
ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.FBS().GetActPDF(ctx, 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)
}
if resp.StatusCode == http.StatusOK {
if resp.FileContent == "" {
t.Errorf("result cannot be empty")
}
}
}
}

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -20,9 +21,18 @@ type ReportOnSoldProductsResponse struct {
core.CommonResponse core.CommonResponse
// Query result // Query result
Result []struct { Result []ReportonSoldProductsResult `json:"result"`
}
type ReportonSoldProductsResult struct {
// Report title page // Report title page
Header []struct { Header []ReportOnSoldProductsResultHeader `json:"header"`
// Report table
Rows []ReportOnSoldProductsResultRow `json:"rows"`
}
type ReportOnSoldProductsResultHeader struct {
// Report ID // Report ID
Id string `json:"num"` Id string `json:"num"`
@@ -67,10 +77,9 @@ type ReportOnSoldProductsResponse struct {
// Period end in the report // Period end in the report
StopDate string `json:"stop_date"` StopDate string `json:"stop_date"`
} `json:"header"` }
// Report table type ReportOnSoldProductsResultRow struct {
Rows []struct {
// Row number // Row number
RowNumber int32 `json:"row_number"` RowNumber int32 `json:"row_number"`
@@ -138,19 +147,17 @@ type ReportOnSoldProductsResponse struct {
// Quantity of returned products // Quantity of returned products
ReturnQuantity int32 `json:"return_qty"` ReturnQuantity int32 `json:"return_qty"`
} `json:"rows"`
} `json:"result"`
} }
// Returns information on products sold and returned within a month. Canceled or non-purchased products are not included. // Returns information on products sold and returned within a month. Canceled or non-purchased products are not included.
// //
// Report is returned no later than the 5th day of the next month // Report is returned no later than the 5th day of the next month
func (c Finance) ReportOnSoldProducts(params *ReportOnSoldProductsParams) (*ReportOnSoldProductsResponse, error) { func (c Finance) ReportOnSoldProducts(ctx context.Context, params *ReportOnSoldProductsParams) (*ReportOnSoldProductsResponse, error) {
url := "/v1/finance/realization" url := "/v1/finance/realization"
resp := &ReportOnSoldProductsResponse{} resp := &ReportOnSoldProductsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -196,7 +203,10 @@ type GetTotalTransactionsSumResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetTotalTransactionsSumResult `json:"result"`
}
type GetTotalTransactionsSumResult struct {
// Total cost of products and returns for specified period // Total cost of products and returns for specified period
AccrualsForSale float64 `json:"accruals_for_sale"` AccrualsForSale float64 `json:"accruals_for_sale"`
@@ -229,16 +239,15 @@ type GetTotalTransactionsSumResponse struct {
// The additional services cost that are not directly related to deliveries and returns. // The additional services cost that are not directly related to deliveries and returns.
// For example, promotion or product placement // For example, promotion or product placement
ServicesAmount float64 `json:"services_amount"` ServicesAmount float64 `json:"services_amount"`
} `json:"result"`
} }
// Returns total sums for transactions for specified period // Returns total sums for transactions for specified period
func (c Finance) GetTotalTransactionsSum(params *GetTotalTransactionsSumParams) (*GetTotalTransactionsSumResponse, error) { func (c Finance) GetTotalTransactionsSum(ctx context.Context, params *GetTotalTransactionsSumParams) (*GetTotalTransactionsSumResponse, error) {
url := "/v3/finance/transaction/totals" url := "/v3/finance/transaction/totals"
resp := &GetTotalTransactionsSumResponse{} resp := &GetTotalTransactionsSumResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -290,9 +299,21 @@ type ListTransactionsResponse struct{
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct{ Result ListTransactionsResult `json:"result"`
}
type ListTransactionsResult struct {
// Transactions infromation // Transactions infromation
Operations []struct{ Operations []ListTransactionsResultOperation `json:"operations"`
// Number of pages
PageCount int64 `json:"page_count"`
// Number of products
RowCount int64 `json:"row_count"`
}
type ListTransactionsResultOperation struct {
// Cost of the products with seller's discounts applied // Cost of the products with seller's discounts applied
AccrualsForSale float64 `json:"accruals_for_sale"` AccrualsForSale float64 `json:"accruals_for_sale"`
@@ -303,13 +324,7 @@ type ListTransactionsResponse struct{
DeliveryCharge float64 `json:"delivery_charge"` DeliveryCharge float64 `json:"delivery_charge"`
// Product information // Product information
Items []struct{ Items []ListTransactionsResultOperationItem `json:"items"`
// Product name
Name string `json:"name"`
// Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"`
} `json:"items"`
// Operation date // Operation date
OperationDate string `json:"operation_date"` OperationDate string `json:"operation_date"`
@@ -324,7 +339,30 @@ type ListTransactionsResponse struct{
OperationTypeName string `json:"operation_type_name"` OperationTypeName string `json:"operation_type_name"`
// Shipment information // Shipment information
Posting struct{ Posting ListTransactionsResultOperationPosting `json:"posting"`
// Returns and cancellation cost for charges by rates that were in effect until February 1, 2021, and for charges for bulky products
ReturnDeliveryCharge float64 `json:"return_delivery_charge"`
// Sales commission or sales commission refund
SaleCommission float64 `json:"sale_commission"`
// Additional services
Services []ListTransactionsResultOperationService `json:"services"`
// Transaction type
Type string `json:"type"`
}
type ListTransactionsResultOperationItem struct {
// Product name
Name string `json:"name"`
// Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"`
}
type ListTransactionsResultOperationPosting struct {
// Delivery scheme: // Delivery scheme:
// - FBO — delivery to Ozon warehouse // - FBO — delivery to Ozon warehouse
// - FBS — delivery from seller's warehouse // - FBS — delivery from seller's warehouse
@@ -340,44 +378,25 @@ type ListTransactionsResponse struct{
// Warehouse identifier // Warehouse identifier
WarehouseId int64 `json:"warehouse_id"` WarehouseId int64 `json:"warehouse_id"`
} `json:"posting"` }
// Returns and cancellation cost for charges by rates that were in effect until February 1, 2021, and for charges for bulky products type ListTransactionsResultOperationService struct {
ReturnDeliveryCharge float64 `json:"return_delivery_charge"`
// Sales commission or sales commission refund
SaleCommission float64 `json:"sale_commission"`
// Additional services
Services []struct{
// Service name // Service name
Name string `json:"name"` Name string `json:"name"`
// Price // Price
Price float64 `json:"price"` Price float64 `json:"price"`
} `json:"services"`
// Transaction type
Type string `json:"type"`
} `json:"operations"`
// Number of pages
PageCount int64 `json:"page_count"`
// Number of products
RowCount int64 `json:"row_count"`
} `json:"result"`
} }
// Returns detailed information on all accruals. The maximum period for which you can get information in one request is 1 month. // Returns detailed information on all accruals. The maximum period for which you can get information in one request is 1 month.
// //
// If you don't specify the posting_number in request, the response contains all shipments for the specified period or shipments of a certain type // If you don't specify the posting_number in request, the response contains all shipments for the specified period or shipments of a certain type
func (c Finance) ListTransactions(params *ListTransactionsParams) (*ListTransactionsResponse, error) { func (c Finance) ListTransactions(ctx context.Context, params *ListTransactionsParams) (*ListTransactionsResponse, error) {
url := "/v3/finance/transaction/list" url := "/v3/finance/transaction/list"
resp := &ListTransactionsResponse{} resp := &ListTransactionsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -90,7 +91,8 @@ func TestReportOnSoldProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Finance().ReportOnSoldProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Finance().ReportOnSoldProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -158,7 +160,8 @@ func TestGetTotalTransactionsSum(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Finance().GetTotalTransactionsSum(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Finance().GetTotalTransactionsSum(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -246,7 +249,8 @@ func TestListTransactions(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Finance().ListTransactions(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Finance().ListTransactions(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,7 +1,9 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time"
core "github.com/diphantxm/ozon-api-client" core "github.com/diphantxm/ozon-api-client"
) )
@@ -16,6 +18,21 @@ type CreateUpdateProformaLinkParams struct {
// Proforma invoice link // Proforma invoice link
URL string `json:"url"` URL string `json:"url"`
// Invoice HS-code. Pass a number up to 12 characters long
HSCode string `json:"hs_code"`
// Invoice date
Date time.Time `json:"date"`
// Invoice number. The number can contain letters and digits, maximum length is 50 characters
Number string `json:"number"`
// Cost stated in the invoice. The fractional part is separated by decimal point, up to two digits after the decimal poin
Price float64 `json:"price"`
// Invoice currency
PriceCurrency InvoiceCurrency `json:"price_currency" default:"USD"`
} }
type CreateUpdateProformaLinkResponse struct { type CreateUpdateProformaLinkResponse struct {
@@ -26,12 +43,12 @@ type CreateUpdateProformaLinkResponse struct {
} }
// Create or edit proforma invoice link for VAT refund to Turkey sellers // Create or edit proforma invoice link for VAT refund to Turkey sellers
func (c Invoices) CreateUpdate(params *CreateUpdateProformaLinkParams) (*CreateUpdateProformaLinkResponse, error) { func (c Invoices) CreateUpdate(ctx context.Context, params *CreateUpdateProformaLinkParams) (*CreateUpdateProformaLinkResponse, error) {
url := "/v1/invoice/create-or-update" url := "/v1/invoice/create-or-update"
resp := &CreateUpdateProformaLinkResponse{} resp := &CreateUpdateProformaLinkResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -49,19 +66,21 @@ type GetProformaLinkResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetProformaLinkResult `json:"result"`
}
type GetProformaLinkResult struct {
// Proforma invoice link // Proforma invoice link
FileURL string `json:"file_url"` FileURL string `json:"file_url"`
} `json:"result"`
} }
// Get a proforma invoice link // Get a proforma invoice link
func (c Invoices) Get(params *GetProformaLinkParams) (*GetProformaLinkResponse, error) { func (c Invoices) Get(ctx context.Context, params *GetProformaLinkParams) (*GetProformaLinkResponse, error) {
url := "/v1/invoice/get" url := "/v1/invoice/get"
resp := &GetProformaLinkResponse{} resp := &GetProformaLinkResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -82,12 +101,12 @@ type DeleteProformaLinkResponse struct {
Result bool `json:"result"` Result bool `json:"result"`
} }
func (c Invoices) Delete(params *DeleteProformaLinkParams) (*DeleteProformaLinkResponse, error) { func (c Invoices) Delete(ctx context.Context, params *DeleteProformaLinkParams) (*DeleteProformaLinkResponse, error) {
url := "/v1/invoice/delete" url := "/v1/invoice/delete"
resp := &DeleteProformaLinkResponse{} resp := &DeleteProformaLinkResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -21,8 +22,13 @@ func TestCreateUpdateProformaLink(t *testing.T) {
http.StatusOK, http.StatusOK,
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&CreateUpdateProformaLinkParams{ &CreateUpdateProformaLinkParams{
PostingNumber: "posting number", PostingNumber: "33920146-0252-1",
URL: "link", URL: "https://cdn.ozone.ru/s3/ozon-disk-api/techdoc/seller-api/earsivfatura_1690960445.pdf",
HSCode: "2134322",
Date: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2023-08-01T12:08:44.342Z"),
Number: "424fdsf234",
Price: 234.34,
PriceCurrency: InvoiceCurrencyRUB,
}, },
`{ `{
"result": true "result": true
@@ -43,7 +49,8 @@ func TestCreateUpdateProformaLink(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Invoices().CreateUpdate(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Invoices().CreateUpdate(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -91,7 +98,8 @@ func TestGetProformaLink(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Invoices().Get(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Invoices().Get(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -137,7 +145,8 @@ func TestDeleteProformaLink(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Invoices().Delete(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Invoices().Delete(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -0,0 +1,19 @@
package notifications
type MessageType string
const (
PingType MessageType = "TYPE_PING"
NewPostingType MessageType = "TYPE_NEW_POSTING"
PostingCancelledType MessageType = "TYPE_POSTING_CANCELLED"
StateChangedType MessageType = "TYPE_STATE_CHANGED"
CutoffDateChangedType MessageType = "TYPE_CUTOFF_DATE_CHANGED"
DeliveryDateChangedType MessageType = "TYPE_DELIVERY_DATE_CHANGED"
CreateOrUpdateType MessageType = "TYPE_CREATE_OR_UPDATE_ITEM"
PriceIndexChangedType MessageType = "TYPE_PRICE_INDEX_CHANGED"
StocksChangedType MessageType = "TYPE_STOCKS_CHANGED"
NewMessageType MessageType = "TYPE_NEW_MESSAGE"
UpdateMessageType MessageType = "TYPE_UPDATE_MESSAGE"
MessageReadType MessageType = "TYPE_MESSAGE_READ"
ChatClosedType MessageType = "TYPE_CHAT_CLOSED"
)

View File

@@ -0,0 +1,158 @@
package notifications
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
type Handler func(req interface{}) error
type NotificationServer struct {
port int
handlers map[MessageType]Handler
}
func NewNotificationServer(port int) *NotificationServer {
return &NotificationServer{
port: port,
handlers: map[MessageType]Handler{},
}
}
func (ns *NotificationServer) Run() error {
mux := http.NewServeMux()
mux.HandleFunc("/", ns.handler)
server := http.Server{
Addr: fmt.Sprintf("0.0.0.0:%d", ns.port),
Handler: mux,
}
return server.ListenAndServe()
}
func (ns *NotificationServer) handler(rw http.ResponseWriter, httpReq *http.Request) {
mt := &Common{}
content, err := ioutil.ReadAll(httpReq.Body)
if err != nil {
log.Print(err)
ns.error(rw, http.StatusBadRequest, err)
return
}
if err := json.Unmarshal(content, mt); err != nil {
log.Print(err)
ns.error(rw, http.StatusBadRequest, err)
return
}
if mt.MessageType == PingType {
resp := pingResponse{
Version: "1.0",
Name: "Ozon Seller API",
Time: time.Now(),
}
respJson, _ := json.Marshal(resp)
rw.WriteHeader(http.StatusOK)
rw.Write(respJson)
return
}
req, err := ns.unmarshal(mt.MessageType, content)
if err != nil {
log.Print(err)
ns.error(rw, http.StatusInternalServerError, err)
return
}
h, ok := ns.handlers[mt.MessageType]
if !ok {
ns.result(rw, true)
log.Printf("handler for %s is not registered", mt.MessageType)
return
}
if err := h(req); err != nil {
log.Print(err)
ns.result(rw, true)
return
}
ns.result(rw, true)
}
func (ns *NotificationServer) Register(mt MessageType, handler func(req interface{}) error) {
ns.handlers[mt] = handler
}
func (ns *NotificationServer) unmarshal(messageType MessageType, content []byte) (interface{}, error) {
switch messageType {
case NewPostingType:
v := &NewPosting{}
err := json.Unmarshal(content, v)
return v, err
case PostingCancelledType:
v := &PostingCancelled{}
err := json.Unmarshal(content, v)
return v, err
case StateChangedType:
v := &StateChanged{}
err := json.Unmarshal(content, v)
return v, err
case CutoffDateChangedType:
v := &CutoffDateChanged{}
err := json.Unmarshal(content, v)
return v, err
case DeliveryDateChangedType:
v := &DeliveryDateChanged{}
err := json.Unmarshal(content, v)
return v, err
case CreateOrUpdateType:
v := &CreateOrUpdateItem{}
err := json.Unmarshal(content, v)
return v, err
case PriceIndexChangedType:
v := &PriceIndexChanged{}
err := json.Unmarshal(content, v)
return v, err
case StocksChangedType:
v := &StocksChanged{}
err := json.Unmarshal(content, v)
return v, err
case NewMessageType:
v := &NewMessage{}
err := json.Unmarshal(content, v)
return v, err
case UpdateMessageType:
v := &UpdateMessage{}
err := json.Unmarshal(content, v)
return v, err
case MessageReadType:
v := &MessageRead{}
err := json.Unmarshal(content, v)
return v, err
case ChatClosedType:
v := &ChatClosed{}
err := json.Unmarshal(content, v)
return v, err
default:
return nil, fmt.Errorf("unsupported type: %s", messageType)
}
}
func (ns *NotificationServer) error(rw http.ResponseWriter, statusCode int, err error) {
errResp := errorResponse{
Data: errorData{
Code: fmt.Sprintf("%d", statusCode),
Message: err.Error(),
},
}
errJson, _ := json.Marshal(errResp)
rw.WriteHeader(statusCode)
rw.Write(errJson)
}
func (ns *NotificationServer) result(rw http.ResponseWriter, res bool) {
rw.WriteHeader(http.StatusOK)
rw.Write([]byte(fmt.Sprintf(`{"result": %t}`, res)))
}

View File

@@ -0,0 +1,682 @@
package notifications
import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"reflect"
"strings"
"testing"
"time"
core "github.com/diphantxm/ozon-api-client"
)
type testData struct {
raw string
object interface{}
}
func pingTest(t *testing.T) testData {
return testData{
object: &pingRequest{
Common: Common{MessageType: PingType},
Time: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
},
raw: `{
"message_type": "TYPE_PING",
"time": "2019-08-24T14:15:22Z"
}`,
}
}
func newPostingTest(t *testing.T) testData {
return testData{
object: &NewPosting{
Common: Common{MessageType: NewPostingType},
PostingNumber: "24219509-0020-1",
Products: []Product{
{
SKU: 147451959,
Quantity: 2,
},
},
InProccessAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-01-26T06:56:36.294Z"),
WarehouseId: 18850503335000,
SellerId: 15,
},
raw: `{
"message_type": "TYPE_NEW_POSTING",
"posting_number": "24219509-0020-1",
"products": [
{
"sku": 147451959,
"quantity": 2
}
],
"in_process_at": "2021-01-26T06:56:36.294Z",
"warehouse_id": 18850503335000,
"seller_id": 15
}`,
}
}
func postingCancelledTest(t *testing.T) testData {
return testData{
object: &PostingCancelled{
Common: Common{MessageType: PostingCancelledType},
PostingNumber: "24219509-0020-1",
Products: []Product{
{
SKU: 147451959,
Quantity: 1,
},
},
OldState: "posting_transferred_to_courier_service",
NewState: "posting_canceled",
ChangedStateDate: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-01-26T06:56:36.294Z"),
Reason: Reason{Id: 1, Message: "message"},
WarehouseId: 1,
SellerId: 15,
},
raw: `{
"message_type": "TYPE_POSTING_CANCELLED",
"posting_number": "24219509-0020-1",
"products": [
{
"sku": 147451959,
"quantity": 1
}
],
"old_state": "posting_transferred_to_courier_service",
"new_state": "posting_canceled",
"changed_state_date": "2021-01-26T06:56:36.294Z",
"reason": {
"id": 1,
"message": "message"
},
"warehouse_id": 1,
"seller_id": 15
}`,
}
}
func cutoffDateChangedTest(t *testing.T) testData {
return testData{
object: &CutoffDateChanged{
Common: Common{MessageType: CutoffDateChangedType},
PostingNumber: "24219509-0020-2",
NewCutoffDate: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-11-24T07:00:00Z"),
OldCutoffDate: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-11-21T10:00:00Z"),
WarehouseId: 1,
SellerId: 15,
},
raw: `{
"message_type": "TYPE_CUTOFF_DATE_CHANGED",
"posting_number": "24219509-0020-2",
"new_cutoff_date": "2021-11-24T07:00:00Z",
"old_cutoff_date": "2021-11-21T10:00:00Z",
"warehouse_id": 1,
"seller_id": 15
}`,
}
}
func deliveryDateChangedTest(t *testing.T) testData {
return testData{
object: &DeliveryDateChanged{
Common: Common{MessageType: DeliveryDateChangedType},
PostingNumber: "24219509-0020-2",
NewDeliveryDateBegin: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-11-24T07:00:00Z"),
NewDeliveryDateEnd: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-11-24T16:00:00Z"),
OldDeliveryDateBegin: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-11-21T10:00:00Z"),
OldDeliveryDateEnd: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-11-21T19:00:00Z"),
WarehouseId: 1,
SellerId: 15,
},
raw: `{
"message_type": "TYPE_DELIVERY_DATE_CHANGED",
"posting_number": "24219509-0020-2",
"new_delivery_date_begin": "2021-11-24T07:00:00Z",
"new_delivery_date_end": "2021-11-24T16:00:00Z",
"old_delivery_date_begin": "2021-11-21T10:00:00Z",
"old_delivery_date_end": "2021-11-21T19:00:00Z",
"warehouse_id": 1,
"seller_id": 15
}`,
}
}
func priceIndexChangedTest(t *testing.T) testData {
return testData{
object: &PriceIndexChanged{
Common: Common{MessageType: PriceIndexChangedType},
UpdatedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2022-06-21T05:52:46.648533678Z"),
SKU: 147451959,
ProductId: 1234,
PriceIndex: 5678,
SellerId: 15,
},
raw: `{
"seller_id": 15,
"message_type": "TYPE_PRICE_INDEX_CHANGED",
"updated_at":"2022-06-21T05:52:46.648533678Z",
"sku": 147451959,
"product_id": 1234,
"price_index": 5678
}`,
}
}
func stocksChangedTest(t *testing.T) testData {
return testData{
object: &StocksChanged{
Common: Common{MessageType: StocksChangedType},
Items: []Item{
{
UpdatedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-09-01T14:15:22Z"),
SKU: 5678,
ProductId: 1234,
Stocks: []Stock{
{
WarehouseId: 10,
Present: 50,
Reserved: 5,
},
},
},
},
SellerId: 15,
},
raw: `{
"message_type": "TYPE_STOCKS_CHANGED",
"seller_id": 15,
"items": [
{
"product_id": 1234,
"sku": 5678,
"updated_at": "2021-09-01T14:15:22Z",
"stocks": [
{
"warehouse_id": 10,
"present": 50,
"reserved": 5
}
]
}
]
}`,
}
}
func newMessageTest(t *testing.T) testData {
return testData{
object: &NewMessage{
Common: Common{MessageType: NewMessageType},
ChatId: "b646d975-0c9c-4872-9f41-8b1e57181063",
ChatType: "Buyer_Seller",
MessageId: "3000000000817031942",
CreatedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2022-07-18T20:58:04.528Z"),
User: User{Id: "115568", Type: "Customer"},
Data: []string{"Message text"},
SellerId: 7,
},
raw: `{
"message_type": "TYPE_NEW_MESSAGE",
"chat_id": "b646d975-0c9c-4872-9f41-8b1e57181063",
"chat_type": "Buyer_Seller",
"message_id": "3000000000817031942",
"created_at": "2022-07-18T20:58:04.528Z",
"user": {
"id": "115568",
"type": "Customer"
},
"data": [
"Message text"
],
"seller_id": 7
}`,
}
}
func updateMessageTest(t *testing.T) testData {
return testData{
object: &UpdateMessage{
NewMessage: NewMessage{
Common: Common{MessageType: UpdateMessageType},
ChatId: "b646d975-0c9c-4872-9f41-8b1e57181063",
ChatType: "Buyer_Seller",
MessageId: "3000000000817031942",
CreatedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2022-07-18T20:58:04.528Z"),
User: User{
Id: "115568",
Type: "Сustomer",
},
Data: []string{"Message text"},
SellerId: 7,
},
UpdatedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2022-07-18T20:59:04.528Z"),
},
raw: `{
"message_type": "TYPE_UPDATE_MESSAGE",
"chat_id": "b646d975-0c9c-4872-9f41-8b1e57181063",
"chat_type": "Buyer_Seller",
"message_id": "3000000000817031942",
"created_at": "2022-07-18T20:58:04.528Z",
"updated_at": "2022-07-18T20:59:04.528Z",
"user": {
"id": "115568",
"type": "Сustomer"
},
"data": [
"Message text"
],
"seller_id": 7
}`,
}
}
func createUpdateItemTest(t *testing.T) testData {
return testData{
object: &CreateOrUpdateItem{
Common: Common{MessageType: "TYPE_CREATE_OR_UPDATE_ITEM"},
OfferId: "1234",
ProductId: 5678,
IsError: false,
ChangedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2022-09-01T14:15:22Z"),
SellerId: 15,
},
raw: `{
"message_type": "TYPE_CREATE_OR_UPDATE_ITEM",
"seller_id": 15,
"offer_id": "1234",
"product_id": 5678,
"is_error": false,
"changed_at": "2022-09-01T14:15:22Z"
}`,
}
}
func stateChangedTest(t *testing.T) testData {
return testData{
object: &StateChanged{
Common: Common{MessageType: "TYPE_STATE_CHANGED"},
PostingNumber: "24219509-0020-2",
NewState: "posting_delivered",
ChangedStateDate: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2021-02-02T15:07:46.765Z"),
WarehouseId: 1,
SellerId: 15,
},
raw: `{
"message_type": "TYPE_STATE_CHANGED",
"posting_number": "24219509-0020-2",
"new_state": "posting_delivered",
"changed_state_date": "2021-02-02T15:07:46.765Z",
"warehouse_id": 1,
"seller_id": 15
}`,
}
}
func messageReadTest(t *testing.T) testData {
return testData{
object: &MessageRead{
LastReadMessageId: "3000000000817031942",
NewMessage: NewMessage{
Common: Common{MessageType: "TYPE_MESSAGE_READ"},
ChatId: "b646d975-0c9c-4872-9f41-8b1e57181063",
ChatType: "Buyer_Seller",
MessageId: "3000000000817031942",
CreatedAt: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2022-07-18T20:58:04.528Z"),
User: User{
Id: "115568",
Type: "Сustomer",
},
SellerId: 7,
},
},
raw: `{
"message_type": "TYPE_MESSAGE_READ",
"chat_id": "b646d975-0c9c-4872-9f41-8b1e57181063",
"chat_type": "Buyer_Seller",
"message_id": "3000000000817031942",
"created_at": "2022-07-18T20:58:04.528Z",
"user": {
"id": "115568",
"type": "Сustomer"
},
"last_read_message_id": "3000000000817031942",
"seller_id": 7
}`,
}
}
func chatClosedTest(t *testing.T) testData {
return testData{
object: &ChatClosed{
Common: Common{MessageType: ChatClosedType},
ChatId: "b646d975-0c9c-4872-9f41-8b1e57181063",
ChatType: "Buyer_Seller",
User: User{Id: "115568", Type: "Customer"},
SellerId: 7,
},
raw: `{
"message_type": "TYPE_CHAT_CLOSED",
"chat_id": "b646d975-0c9c-4872-9f41-8b1e57181063",
"chat_type": "Buyer_Seller",
"user": {
"id": "115568",
"type": "Customer"
},
"seller_id": 7
}`,
}
}
func TestNotificationServer(t *testing.T) {
testCases := []struct {
request testData
response string
}{
{
pingTest(t),
`{
"version": "1.0",
"name": "Ozon Seller API"
}`,
},
{
newPostingTest(t),
`{
"result": true
}`,
},
{
postingCancelledTest(t),
`{
"result": true
}`,
},
{
stateChangedTest(t),
`{
"result": true
}`,
},
{
cutoffDateChangedTest(t),
`{
"result": true
}`,
},
{
deliveryDateChangedTest(t),
`{
"result": true
}`,
},
{
createUpdateItemTest(t),
`{
"result": true
}`,
},
{
priceIndexChangedTest(t),
`{
"result": true
}`,
},
{
stocksChangedTest(t),
`{
"result": true
}`,
},
{
newMessageTest(t),
`{
"result": true
}`,
},
{
updateMessageTest(t),
`{
"result": true
}`,
},
{
messageReadTest(t),
`{
"result": true
}`,
},
{
chatClosedTest(t),
`{
"result": true
}`,
},
}
port := getFreePort()
client := http.Client{}
server := NewNotificationServer(port)
server.Register(NewPostingType, comparatorWith(newPostingTest(t).object))
server.Register(PostingCancelledType, comparatorWith(postingCancelledTest(t).object))
server.Register(StateChangedType, comparatorWith(stateChangedTest(t).object))
server.Register(CutoffDateChangedType, comparatorWith(cutoffDateChangedTest(t).object))
server.Register(DeliveryDateChangedType, comparatorWith(deliveryDateChangedTest(t).object))
server.Register(CreateOrUpdateType, comparatorWith(createUpdateItemTest(t).object))
server.Register(PriceIndexChangedType, comparatorWith(priceIndexChangedTest(t).object))
server.Register(StocksChangedType, comparatorWith(stocksChangedTest(t).object))
server.Register(NewMessageType, comparatorWith(newMessageTest(t).object))
server.Register(UpdateMessageType, comparatorWith(updateMessageTest(t).object))
server.Register(MessageReadType, comparatorWith(messageReadTest(t).object))
server.Register(ChatClosedType, comparatorWith(chatClosedTest(t).object))
go func() {
if err := server.Run(); err != nil {
t.Fatalf("notification server is down: %s", err)
}
}()
// TODO: get rid of it
// Needed to make sure server is running
time.Sleep(3 * time.Second)
for _, testCase := range testCases {
httpResp, err := client.Post(fmt.Sprintf("http://0.0.0.0:%d/", port), "application/json", strings.NewReader(testCase.request.raw))
if err != nil {
t.Error(err)
continue
}
gotJson, err := ioutil.ReadAll(httpResp.Body)
if err != nil {
t.Error(err)
continue
}
expected := map[string]interface{}{}
got := map[string]interface{}{}
err = json.Unmarshal(gotJson, &got)
if err != nil {
t.Error(err)
continue
}
err = json.Unmarshal([]byte(testCase.response), &expected)
if err != nil {
t.Error(err)
continue
}
if err := compare(expected, got); err != nil {
t.Error(err)
continue
}
}
}
func TestNotificationServerErrors(t *testing.T) {
testCases := []struct {
request testData
response string
}{
{
testData{
raw: `{
"message_type": "string"
}`,
},
`
{
"error": {
"code": "500",
"message": "unsupported type: string",
"details": ""
}
}`,
},
{
testData{
raw: `invalid json`,
},
`{
"error": {
"code": "400",
"message": "invalid character 'i' looking for beginning of value",
"details": ""
}
}`,
},
{
testData{
raw: `{
"message_type": "TYPE_NEW_POSTING",
"field": [[
}`,
},
`{
"error": {
"code": "400",
"message": "invalid character '}' looking for beginning of value",
"details": ""
}
}`,
},
{
testData{
raw: `{
"message_type": "TYPE_NEW_POSTING"
}`,
},
`{
"result": true
}`,
},
{
testData{
raw: `{
"message_type": "TYPE_PING",
"time": "2019-08-24T14:15:22Z",
}`,
},
`{
"error": {
"code": "400",
"message": "invalid character '}' looking for beginning of object key string",
"details": ""
}
}`,
},
{
testData{
raw: `{
"message_type": "TYPE_CHAT_CLOSED"
}`,
},
`{
"result": true
}`,
},
}
port := getFreePort()
client := http.Client{}
server := NewNotificationServer(port)
server.Register(NewPostingType, func(req interface{}) error {
return fmt.Errorf("just error")
})
go func() {
if err := server.Run(); err != nil {
t.Fatalf("notification server is down: %s", err)
}
}()
// TODO: get rid of it
// Needed to make sure server is running
time.Sleep(3 * time.Second)
for _, testCase := range testCases {
httpResp, err := client.Post(fmt.Sprintf("http://0.0.0.0:%d/", port), "application/json", strings.NewReader(testCase.request.raw))
if err != nil {
t.Error(err)
continue
}
gotJson, err := ioutil.ReadAll(httpResp.Body)
if err != nil {
t.Error(err)
continue
}
expected := map[string]interface{}{}
got := map[string]interface{}{}
err = json.Unmarshal(gotJson, &got)
if err != nil {
t.Error(err)
continue
}
err = json.Unmarshal([]byte(testCase.response), &expected)
if err != nil {
t.Error(err)
continue
}
if err := compare(expected, got); err != nil {
t.Error(err)
continue
}
}
}
func compare(expected map[string]interface{}, got map[string]interface{}) error {
for k, v := range expected {
if gotValue, ok := got[k]; !ok {
return fmt.Errorf("key %s is expected to present", k)
} else if !reflect.DeepEqual(gotValue, v) {
return fmt.Errorf("key %s is not equal, got: %v, want: %v", k, gotValue, v)
}
}
return nil
}
func getFreePort() int {
listener, _ := net.Listen("tcp", ":0")
defer listener.Close()
return listener.Addr().(*net.TCPAddr).Port
}
func comparatorWith(v1 interface{}) func(v2 interface{}) error {
return func(v2 interface{}) error {
if !reflect.DeepEqual(v1, v2) {
return fmt.Errorf("objects are not equal:\n got: %#v,\n want: %#v", v2, v1)
}
return nil
}
}

321
ozon/notifications/types.go Normal file
View File

@@ -0,0 +1,321 @@
package notifications
import "time"
// Checking if the service is ready at initial connection and periodically after it
type pingRequest struct {
Common
// Date and time when the notification was sent in UTC format
Time time.Time `json:"time"`
}
type pingResponse struct {
// Application version
Version string `json:"version"`
// Application name
Name string `json:"name"`
// Date and time when notification processing started in UTC format
Time time.Time `json:"time"`
}
type Common struct {
MessageType MessageType `json:"message_type"`
}
// New shipment
type NewPosting struct {
Common
// Shipment number
PostingNumber string `json:"posting_number"`
// Products information
Products []Product `json:"products"`
// Date and time when the shipment processing started in the UTC format
InProccessAt time.Time `json:"in_process_at"`
// Warehouse identifier where the products for this shipment are stored
WarehouseId int64 `json:"warehouse_id"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
type Product struct {
// Product SKU
SKU int64 `json:"sku"`
// Product quantity
Quantity int64 `json:"quantity"`
}
// Shipment cancellation
type PostingCancelled struct {
Common
// Shipment number
PostingNumber string `json:"posting_number"`
// Products information
Products []Product `json:"products"`
// Previous shipment status
OldState string `json:"old_state"`
// New shipment status: posting_canceled—canceled
NewState string `json:"new_state"`
// Date and time when the shipment status was changed in UTC format
ChangedStateDate time.Time `json:"changed_state_date"`
// Information about cancellation reason
Reason Reason `json:"reason"`
// Warehouse identifier where the products for this shipment are stored
WarehouseId int64 `json:"warehouse_id"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
type Reason struct {
// Cancellation reason identifier
Id int64 `json:"id"`
// Cancellation reason
Message string `json:"message"`
}
// Shipment status change
type StateChanged struct {
Common
// Shipment number
PostingNumber string `json:"posting_number"`
// New shipment status
NewState string `json:"new_state"`
// Date and time when the shipment status was changed in UTC format
ChangedStateDate time.Time `json:"changed_state_date"`
// Warehouse identifier where the products for this shipment are stored
WarehouseId int64 `json:"warehouse_id"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
// Shipment shipping date change
type CutoffDateChanged struct {
Common
// Shipment number
PostingNumber string `json:"posting_number"`
// New shipping date and time in UTC format
NewCutoffDate time.Time `json:"new_cutoff_date"`
// Previous shipping date and time in UTC format
OldCutoffDate time.Time `json:"old_cutoff_date"`
// Warehouse identifier where the products for this shipment are stored
WarehouseId int64 `json:"warehouse_id"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
// Shipment delivery date change
type DeliveryDateChanged struct {
Common
// Shipment number
PostingNumber string `json:"posting_number"`
// New delivery start date and time in UTC format
NewDeliveryDateBegin time.Time `json:"new_delivery_date_begin"`
// New delivery end date and time in UTC format
NewDeliveryDateEnd time.Time `json:"new_delivery_date_end"`
// Previous delivery start date and time in UTC format
OldDeliveryDateBegin time.Time `json:"old_delivery_date_begin"`
// Previous delivery end date and time in UTC format
OldDeliveryDateEnd time.Time `json:"old_delivery_date_end"`
// Warehouse identifier where the products for this shipment are stored
WarehouseId int64 `json:"warehouse_id"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
// Product creation and update or processing error
type CreateOrUpdateItem struct {
Common
// Product identifier in the seller's system
OfferId string `json:"offer_id"`
// Product identifier
ProductId int64 `json:"product_id"`
// An indication that errors occurred during the product creation or update
IsError bool `json:"is_error"`
// Update date and time
ChangedAt time.Time `json:"changed_at"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
// Product price index change
type PriceIndexChanged struct {
Common
// Date and time of price index change
UpdatedAt time.Time `json:"updated_at"`
// Product SKU
SKU int64 `json:"sku"`
// Product identifier
ProductId int64 `json:"product_id"`
// Price index
PriceIndex int64 `json:"price_index"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
// Stock change at the seller's warehouse
type StocksChanged struct {
Common
// Array with products data
Items []Item `json:"items"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
type Item struct {
// Update date and time
UpdatedAt time.Time `json:"updated_at"`
// Product SKU when working under the FBS or rFBS schemes
SKU int64 `json:"sku"`
// Product identifier
ProductId int64 `json:"product_id"`
// Array with product stocks data
Stocks []Stock `json:"stocks"`
}
type Stock struct {
// Warehouse identifier
WarehouseId int64 `json:"warehouse_id"`
// Total product stocks at the warehouse
Present int64 `json:"present"`
// Number of reserved products at the warehouse
Reserved int64 `json:"reserved"`
}
// New message in chat
type NewMessage struct {
Common
// Chat identifier
ChatId string `json:"chat_id"`
// Chat type
ChatType string `json:"chat_type"`
// Message identifier
MessageId string `json:"message_id"`
// Message creation date
CreatedAt time.Time `json:"created_at"`
// Information about message sender
User User `json:"user"`
// Array with message content in Markdown format
Data []string `json:"data"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
type User struct {
// Sender identifier
Id string `json:"id"`
// Sender type
Type string `json:"type"`
}
// Message in chat has changed
type UpdateMessage struct {
NewMessage
// Message update date
UpdatedAt time.Time `json:"updated_at"`
}
// Customer or support read your message
type MessageRead struct {
NewMessage
// Last read message identifier
LastReadMessageId string `json:"last_read_message_id"`
}
// Chat is closed
type ChatClosed struct {
Common
// Chat identifier
ChatId string `json:"chat_id"`
// Chat type
ChatType string `json:"chat_type"`
// Information about the user who closed the chat
User User `json:"user"`
// Seller identifier
SellerId int64 `json:"seller_id"`
}
type Response struct {
// Notification is received
Result bool `json:"result"`
}
type errorResponse struct {
// Information about the error
Data errorData `json:"error"`
}
type errorData struct {
// Error code
Code string `json:"code"`
// Detailed error description
Message string `json:"message"`
// Additional information
Details string `json:"details"`
}

View File

@@ -105,8 +105,8 @@ func (c Client) Strategies() *Strategies {
return c.strategies return c.strategies
} }
func NewClient(clientId, apiKey string) *Client { func NewClient(httpClient core.HttpClient, clientId, apiKey string) *Client {
coreClient := core.NewClient(DefaultAPIBaseUrl, map[string]string{ coreClient := core.NewClient(httpClient, DefaultAPIBaseUrl, map[string]string{
"Client-Id": clientId, "Client-Id": clientId,
"Api-Key": apiKey, "Api-Key": apiKey,
}) })

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
core "github.com/diphantxm/ozon-api-client" core "github.com/diphantxm/ozon-api-client"
@@ -25,12 +26,12 @@ type CreateDeliveryPolygonResponse struct {
// You can link a polygon to the delivery method. // You can link a polygon to the delivery method.
// //
// Create a polygon getting its coordinates on https://geojson.io: mark at least 3 points on the map and connect them // Create a polygon getting its coordinates on https://geojson.io: mark at least 3 points on the map and connect them
func (c Polygons) CreateDelivery(params *CreateDeliveryPolygonParams) (*CreateDeliveryPolygonResponse, error) { func (c Polygons) CreateDelivery(ctx context.Context, params *CreateDeliveryPolygonParams) (*CreateDeliveryPolygonResponse, error) {
url := "/v1/polygon/create" url := "/v1/polygon/create"
resp := &CreateDeliveryPolygonResponse{} resp := &CreateDeliveryPolygonResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -71,12 +72,12 @@ type LinkDeliveryMethodToPolygonResponse struct {
} }
// Link delivery method to a delivery polygon // Link delivery method to a delivery polygon
func (c Polygons) Link(params *LinkDeliveryMethodToPolygonParams) (*LinkDeliveryMethodToPolygonResponse, error) { func (c Polygons) Link(ctx context.Context, params *LinkDeliveryMethodToPolygonParams) (*LinkDeliveryMethodToPolygonResponse, error) {
url := "/v1/polygon/bind" url := "/v1/polygon/bind"
resp := &LinkDeliveryMethodToPolygonResponse{} resp := &LinkDeliveryMethodToPolygonResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -95,12 +96,12 @@ type DeletePolygonResponse struct {
} }
// Delete polygon // Delete polygon
func (c Polygons) Delete(params *DeletePolygonParams) (*DeletePolygonResponse, error) { func (c Polygons) Delete(ctx context.Context, params *DeletePolygonParams) (*DeletePolygonResponse, error) {
url := "/v1/polygon/delete" url := "/v1/polygon/delete"
resp := &DeletePolygonResponse{} resp := &DeletePolygonResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -42,7 +43,8 @@ func TestCreateDeliveryPolygon(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Polygons().CreateDelivery(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Polygons().CreateDelivery(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -96,7 +98,8 @@ func TestLinkDeliveryMethodToPolygon(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Polygons().Link(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Polygons().Link(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -140,7 +143,8 @@ func TestDeletePolygon(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Polygons().Delete(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Polygons().Delete(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"fmt" "fmt"
"net/http" "net/http"
"testing" "testing"
@@ -70,7 +71,8 @@ func TestGetStocksInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetStocksInfo(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetStocksInfo(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -267,7 +269,8 @@ func TestGetProductDetails(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetProductDetails(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetProductDetails(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -341,7 +344,8 @@ func TestUpdateStocks(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UpdateStocks(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UpdateStocks(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -380,12 +384,12 @@ func TestStocksInSellersWarehouse(t *testing.T) {
http.StatusOK, http.StatusOK,
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&StocksInSellersWarehouseParams{ &StocksInSellersWarehouseParams{
FBSSKU: []string{"123"}, SKU: []string{"123"},
}, },
`{ `{
"result": [ "result": [
{ {
"fbs_sku": 12, "sku": 12,
"present": 34, "present": 34,
"product_id": 548761, "product_id": 548761,
"reserved": 5, "reserved": 5,
@@ -410,7 +414,8 @@ func TestStocksInSellersWarehouse(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().StocksInSellersWarehouse(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().StocksInSellersWarehouse(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -420,11 +425,11 @@ func TestStocksInSellersWarehouse(t *testing.T) {
} }
if resp.StatusCode == http.StatusOK { if resp.StatusCode == http.StatusOK {
if len(resp.Result) != len(test.params.FBSSKU) { if len(resp.Result) != len(test.params.SKU) {
t.Errorf("Length of skus in request and response must be equal") t.Errorf("Length of skus in request and response must be equal")
} }
if len(resp.Result) > 0 { if len(resp.Result) > 0 {
if fmt.Sprint(resp.Result[0].FBSSKU) == test.params.FBSSKU[0] { if fmt.Sprint(resp.Result[0].SKU) == test.params.SKU[0] {
t.Errorf("fbs sku in request and response are not equal") t.Errorf("fbs sku in request and response are not equal")
} }
} }
@@ -454,6 +459,7 @@ func TestUpdatePrices(t *testing.T) {
OldPrice: "0", OldPrice: "0",
Price: "1448", Price: "1448",
ProductId: 1386, ProductId: 1386,
PriceStrategyEnabled: PriceStrategyUnknown,
}, },
}, },
}, },
@@ -483,7 +489,8 @@ func TestUpdatePrices(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UpdatePrices(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UpdatePrices(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -555,7 +562,8 @@ func TestUpdateQuantityStockProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UpdateQuantityStockProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UpdateQuantityStockProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -689,7 +697,8 @@ func TestCreateOrUpdateProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().CreateOrUpdateProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().CreateOrUpdateProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -756,7 +765,8 @@ func TestGetListOfProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetListOfProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetListOfProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1002,7 +1012,8 @@ func TestGetProductsRatingBySKU(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetProductsRatingBySKU(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetProductsRatingBySKU(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1069,7 +1080,8 @@ func TestGetProductImportStatus(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetProductImportStatus(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetProductImportStatus(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1140,7 +1152,8 @@ func TestCreateProductByOzonID(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().CreateProductByOzonID(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().CreateProductByOzonID(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1208,7 +1221,8 @@ func TestUpdateProductImages(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UpdateProductImages(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UpdateProductImages(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1276,7 +1290,8 @@ func TestCheckImageUploadingStatus(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().CheckImageUploadingStatus(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().CheckImageUploadingStatus(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1471,7 +1486,8 @@ func TestListProductsByIDs(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().ListProductsByIDs(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().ListProductsByIDs(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1705,7 +1721,8 @@ func TestGetDescriptionOfProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetDescriptionOfProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetDescriptionOfProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1763,7 +1780,8 @@ func TestGetProductDescription(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetProductDescription(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetProductDescription(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1826,7 +1844,8 @@ func TestGetProductRangeLimit(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetProductRangeLimit() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetProductRangeLimit(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1882,7 +1901,8 @@ func TestChangeProductIDs(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().ChangeProductIDs(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().ChangeProductIDs(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1928,7 +1948,8 @@ func TestArchiveProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().ArchiveProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().ArchiveProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -1974,7 +1995,8 @@ func TestUnarchiveProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UnarchiveProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UnarchiveProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2030,7 +2052,8 @@ func TestRemoveProductWithoutSKU(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().RemoveProductWithoutSKU(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().RemoveProductWithoutSKU(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2107,7 +2130,8 @@ func TestListGeoRestrictions(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().ListGeoRestrictions(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().ListGeoRestrictions(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2156,7 +2180,8 @@ func TestUploadActivationCodes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UploadActivationCodes(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UploadActivationCodes(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2204,7 +2229,8 @@ func TestStatusOfUploadingActivationCodes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().StatusOfUploadingActivationCodes(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().StatusOfUploadingActivationCodes(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2239,6 +2265,7 @@ func TestGetProductPriceInfo(t *testing.T) {
"result": { "result": {
"items": [ "items": [
{ {
"acquiring": 0,
"product_id": 243686911, "product_id": 243686911,
"offer_id": "356792", "offer_id": "356792",
"price": { "price": {
@@ -2254,9 +2281,28 @@ func TestGetProductPriceInfo(t *testing.T) {
"marketing_seller_price": "", "marketing_seller_price": "",
"auto_action_enabled": true "auto_action_enabled": true
}, },
"price_index": "0.00", "price_indexes": {
"external_index_data": {
"minimal_price": "string",
"minimal_price_currency": "string",
"price_index_value": 0
},
"ozon_index_data": {
"minimal_price": "string",
"minimal_price_currency": "string",
"price_index_value": 0
},
"price_index": "WITHOUT_INDEX",
"self_marketplaces_index_data": {
"minimal_price": "string",
"minimal_price_currency": "string",
"price_index_value": 0
}
},
"commissions": { "commissions": {
"sales_percent": 15, "sales_percent": 15,
"sales_percent_fbo": 15,
"sales_percent_fbs": 0,
"fbo_fulfillment_amount": 0, "fbo_fulfillment_amount": 0,
"fbo_direct_flow_trans_min_amount": 31, "fbo_direct_flow_trans_min_amount": 31,
"fbo_direct_flow_trans_max_amount": 46.5, "fbo_direct_flow_trans_max_amount": 46.5,
@@ -2265,7 +2311,7 @@ func TestGetProductPriceInfo(t *testing.T) {
"fbo_return_flow_trans_min_amount": 21.7, "fbo_return_flow_trans_min_amount": 21.7,
"fbo_return_flow_trans_max_amount": 21.7, "fbo_return_flow_trans_max_amount": 21.7,
"fbs_first_mile_min_amount": 0, "fbs_first_mile_min_amount": 0,
"fbs_first_mile_max_amount": 0, "fbs_first_mile_max_amount": 25,
"fbs_direct_flow_trans_min_amount": 41, "fbs_direct_flow_trans_min_amount": 41,
"fbs_direct_flow_trans_max_amount": 61.5, "fbs_direct_flow_trans_max_amount": 61.5,
"fbs_deliv_to_customer_amount": 60, "fbs_deliv_to_customer_amount": 60,
@@ -2297,7 +2343,8 @@ func TestGetProductPriceInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetProductPriceInfo(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetProductPriceInfo(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2359,7 +2406,8 @@ func TestGetMarkdownInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().GetMarkdownInfo(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().GetMarkdownInfo(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2414,7 +2462,8 @@ func TestSetDiscountOnMarkdownProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().SetDiscountOnMarkdownProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().SetDiscountOnMarkdownProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2465,7 +2514,8 @@ func TestNumberOfSubsToProductAvailability(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().NumberOfSubsToProductAvailability(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().NumberOfSubsToProductAvailability(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -2539,7 +2589,8 @@ func TestUpdateCharacteristics(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Products().UpdateCharacteristics(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Products().UpdateCharacteristics(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -15,7 +16,10 @@ type GetAvailablePromotionsResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result []struct { Result []GetAvailablePromotionsResult `json:"result"`
}
type GetAvailablePromotionsResult struct {
// Promotion identifier // Promotion identifier
Id float64 `json:"id"` Id float64 `json:"id"`
@@ -67,16 +71,15 @@ type GetAvailablePromotionsResponse struct {
// Discount size // Discount size
DiscountValue float64 `json:"discount_value"` DiscountValue float64 `json:"discount_value"`
} `json:"result"`
} }
// A method for getting a list of promotions that you can participate in // A method for getting a list of promotions that you can participate in
func (c Promotions) GetAvailablePromotions() (*GetAvailablePromotionsResponse, error) { func (c Promotions) GetAvailablePromotions(ctx context.Context) (*GetAvailablePromotionsResponse, error) {
url := "/v1/actions" url := "/v1/actions"
resp := &GetAvailablePromotionsResponse{} resp := &GetAvailablePromotionsResponse{}
response, err := c.client.Request(http.MethodGet, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodGet, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -108,28 +111,32 @@ type AddProductToPromotionResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result AddProductToPromotionResult `json:"result"`
}
type AddProductToPromotionResult struct {
// List of product identifiers that were added to the promotion // List of product identifiers that were added to the promotion
ProductIds []float64 `json:"product_ids"` ProductIds []float64 `json:"product_ids"`
// List of products that weren't added to the promotion // List of products that weren't added to the promotion
Rejected []struct { Rejected []AddProductToPromotionResultRejected `json:"rejected"`
}
type AddProductToPromotionResultRejected struct {
// Product identifier // Product identifier
ProductId float64 `json:"product_id"` ProductId float64 `json:"product_id"`
// Reason why the product wasn't added to the promotion // Reason why the product wasn't added to the promotion
Reason string `json:"reason"` Reason string `json:"reason"`
} `json:"rejected"`
} `json:"result"`
} }
// A method for adding products to an available promotion // A method for adding products to an available promotion
func (c Promotions) AddToPromotion(params *AddProductToPromotionParams) (*AddProductToPromotionResponse, error) { func (c Promotions) AddToPromotion(ctx context.Context, params *AddProductToPromotionParams) (*AddProductToPromotionResponse, error) {
url := "/v1/actions/products/activate" url := "/v1/actions/products/activate"
resp := &AddProductToPromotionResponse{} resp := &AddProductToPromotionResponse{}
response, err := c.client.Request(http.MethodGet, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -154,13 +161,15 @@ type ProductsAvailableForPromotionResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ProductsAvailableForPromotionResult `json:"result"`
}
type ProductsAvailableForPromotionResult struct {
// Products list // Products list
Products []PromotionProduct `json:"products"` Products []PromotionProduct `json:"products"`
// Total number of products that can participate in the promotion // Total number of products that can participate in the promotion
Total float64 `json:"total"` Total float64 `json:"total"`
} `json:"result"`
} }
type PromotionProduct struct { type PromotionProduct struct {
@@ -187,12 +196,12 @@ type PromotionProduct struct {
} }
// A method for getting a list of products that can participate in the promotion by the promotion identifier // A method for getting a list of products that can participate in the promotion by the promotion identifier
func (c Promotions) ProductsAvailableForPromotion(params *ProductsAvailableForPromotionParams) (*ProductsAvailableForPromotionResponse, error) { func (c Promotions) ProductsAvailableForPromotion(ctx context.Context, params *ProductsAvailableForPromotionParams) (*ProductsAvailableForPromotionResponse, error) {
url := "/v1/actions/candidates" url := "/v1/actions/candidates"
resp := &ProductsAvailableForPromotionResponse{} resp := &ProductsAvailableForPromotionResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -216,22 +225,24 @@ type ProductsInPromotionResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ProductsInPromotionResult `json:"reuslt"`
}
type ProductsInPromotionResult struct {
// Products list // Products list
Products []PromotionProduct `json:"products"` Products []PromotionProduct `json:"products"`
// Total number of products that can participate in the promotion // Total number of products that can participate in the promotion
Total float64 `json:"total"` Total float64 `json:"total"`
} `json:"reuslt"`
} }
// A method for getting the list of products participating in the promotion by its identifier // A method for getting the list of products participating in the promotion by its identifier
func (c Promotions) ProductsInPromotion(params *ProductsInPromotionParams) (*ProductsInPromotionResponse, error) { func (c Promotions) ProductsInPromotion(ctx context.Context, params *ProductsInPromotionParams) (*ProductsInPromotionResponse, error) {
url := "/v1/actions/products" url := "/v1/actions/products"
resp := &ProductsInPromotionResponse{} resp := &ProductsInPromotionResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -252,28 +263,32 @@ type RemoveProductFromPromotionResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result RemoveProductFromPromotionResult `json:"result"`
}
type RemoveProductFromPromotionResult struct {
// List of product identifiers that were removed from the promotion // List of product identifiers that were removed from the promotion
ProductIds []float64 `json:"product_ids"` ProductIds []float64 `json:"product_ids"`
// List of product identifiers that weren't removed from the promotion // List of product identifiers that weren't removed from the promotion
Rejected []struct { Rejected []RemoveProductFromPromotionResultRejected `json:"rejected"`
}
type RemoveProductFromPromotionResultRejected struct {
// Product identifier // Product identifier
ProductId float64 `json:"product_id"` ProductId float64 `json:"product_id"`
// Reason why the product wasn't removed from the promotion // Reason why the product wasn't removed from the promotion
Reason string `json:"reason"` Reason string `json:"reason"`
} `json:"rejected"`
} `json:"result"`
} }
// A method for removing products from the promotion // A method for removing products from the promotion
func (c Promotions) RemoveProduct(params *RemoveProductFromPromotionParams) (*RemoveProductFromPromotionResponse, error) { func (c Promotions) RemoveProduct(ctx context.Context, params *RemoveProductFromPromotionParams) (*RemoveProductFromPromotionResponse, error) {
url := "/v1/actions/products/deactivate" url := "/v1/actions/products/deactivate"
resp := &RemoveProductFromPromotionResponse{} resp := &RemoveProductFromPromotionResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -286,7 +301,10 @@ type ListHotSalePromotionsResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result []struct { Result []ListHotSalePromotionsResult `json:"result"`
}
type ListHotSalePromotionsResult struct {
// Promotion end date // Promotion end date
DateEnd string `json:"date_end"` DateEnd string `json:"date_end"`
@@ -312,16 +330,15 @@ type ListHotSalePromotionsResponse struct {
// Promotion name // Promotion name
Title string `json:"title"` Title string `json:"title"`
} `json:"result"`
} }
// List of available Hot Sale promotions // List of available Hot Sale promotions
func (c Promotions) ListHotSalePromotions() (*ListHotSalePromotionsResponse, error) { func (c Promotions) ListHotSalePromotions(ctx context.Context) (*ListHotSalePromotionsResponse, error) {
url := "/v1/actions/hotsales/list" url := "/v1/actions/hotsales/list"
resp := &ListHotSalePromotionsResponse{} resp := &ListHotSalePromotionsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -345,9 +362,18 @@ type ProductsAvailableForHotSalePromotionResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ProductsAvailableForHotSalePromotionResult `json:"result"`
}
type ProductsAvailableForHotSalePromotionResult struct {
// Products list // Products list
Products []struct { Products []ProductsAvailableForHotSalePromotionResultProduct `json:"products"`
// Total number of products that are available for the promotion
Total float64 `json:"total"`
}
type ProductsAvailableForHotSalePromotionResultProduct struct {
// Promotional product price // Promotional product price
ActionPrice float64 `json:"action_price"` ActionPrice float64 `json:"action_price"`
@@ -368,20 +394,15 @@ type ProductsAvailableForHotSalePromotionResponse struct {
// Number of product units in a stock discount type promotion // Number of product units in a stock discount type promotion
Stock float64 `json:"stock"` Stock float64 `json:"stock"`
} `json:"products"`
// Total number of products that are available for the promotion
Total float64 `json:"total"`
} `json:"result"`
} }
// Method for getting a list of products that can participate or are already participating in the Hot Sale promotion // Method for getting a list of products that can participate or are already participating in the Hot Sale promotion
func (c Promotions) ProductsAvailableForHotSalePromotion(params *ProductsAvailableForHotSalePromotionParams) (*ProductsAvailableForHotSalePromotionResponse, error) { func (c Promotions) ProductsAvailableForHotSalePromotion(ctx context.Context, params *ProductsAvailableForHotSalePromotionParams) (*ProductsAvailableForHotSalePromotionResponse, error) {
url := "/v1/actions/hotsales/products" url := "/v1/actions/hotsales/products"
resp := &ProductsAvailableForHotSalePromotionResponse{} resp := &ProductsAvailableForHotSalePromotionResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -413,24 +434,28 @@ type ProductsToHotSaleResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result ProductsToHotSaleResult `json:"result"`
}
type ProductsToHotSaleResult struct {
// List of products that haven't been added to the promotion // List of products that haven't been added to the promotion
Rejected []struct { Rejected []ProductsToHotSaleResultRejected `json:"rejected"`
}
type ProductsToHotSaleResultRejected struct {
//Product identifier //Product identifier
ProductId float64 `json:"product_id"` ProductId float64 `json:"product_id"`
// Reason why the product hasn't been added to the promotion // Reason why the product hasn't been added to the promotion
Reason string `json:"reason"` Reason string `json:"reason"`
} `json:"rejected"`
} `json:"result"`
} }
func (c Promotions) AddProductsToHotSale(params *AddProductsToHotSaleParams) (*ProductsToHotSaleResponse, error) { func (c Promotions) AddProductsToHotSale(ctx context.Context, params *AddProductsToHotSaleParams) (*ProductsToHotSaleResponse, error) {
url := "/v1/actions/hotsales/activate" url := "/v1/actions/hotsales/activate"
resp := &ProductsToHotSaleResponse{} resp := &ProductsToHotSaleResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -448,12 +473,12 @@ type RemoveProductsToHotSaleParams struct {
} }
// Remove product from the Hot Sale promotion // Remove product from the Hot Sale promotion
func (c Promotions) RemoveProductsToHotSale(params *RemoveProductsToHotSaleParams) (*ProductsToHotSaleResponse, error) { func (c Promotions) RemoveProductsToHotSale(ctx context.Context, params *RemoveProductsToHotSaleParams) (*ProductsToHotSaleResponse, error) {
url := "/v1/actions/hotsales/activate" url := "/v1/actions/hotsales/activate"
resp := &ProductsToHotSaleResponse{} resp := &ProductsToHotSaleResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -477,7 +502,10 @@ type ListDiscountRequestsResponse struct {
core.CommonResponse core.CommonResponse
// List of requests // List of requests
Result []struct { Result []ListDiscountRequestsResult `json:"result"`
}
type ListDiscountRequestsResult struct {
// Request ID // Request ID
Id uint64 `json:"id"` Id uint64 `json:"id"`
@@ -582,16 +610,15 @@ type ListDiscountRequestsResponse struct {
// Approved price fee percent // Approved price fee percent
ApprovedPriceFeePercent float64 `json:"approved_price_fee_percent"` ApprovedPriceFeePercent float64 `json:"approved_price_fee_percent"`
} `json:"result"`
} }
// Method for getting a list of products that customers want to buy with discount // Method for getting a list of products that customers want to buy with discount
func (c Promotions) ListDiscountRequests(params *ListDiscountRequestsParams) (*ListDiscountRequestsResponse, error) { func (c Promotions) ListDiscountRequests(ctx context.Context, params *ListDiscountRequestsParams) (*ListDiscountRequestsResponse, error) {
url := "/v1/actions/discounts-task/list" url := "/v1/actions/discounts-task/list"
resp := &ListDiscountRequestsResponse{} resp := &ListDiscountRequestsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -626,33 +653,37 @@ type DiscountRequestResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result DiscountRequestResult `json:"result"`
// Errors when creating a request }
FailDetails []struct {
// Request ID
TaskId uint64 `json:"task_id"`
// Error message type DiscountRequestResult struct {
ErrorForUser string `json:"error_for_user"` // Errors when creating a request
} `json:"fail_details"` FailDetails []DiscountRequestResultFailDetail `json:"fail_details"`
// The number of requests with a successful status change // The number of requests with a successful status change
SuccessCount int32 `json:"success_count"` SuccessCount int32 `json:"success_count"`
// The number of requests that failed to change their status // The number of requests that failed to change their status
FailCount int32 `json:"fail_count"` FailCount int32 `json:"fail_count"`
} `json:"result"` }
type DiscountRequestResultFailDetail struct {
// Request ID
TaskId uint64 `json:"task_id"`
// Error message
ErrorForUser string `json:"error_for_user"`
} }
// You can approve applications in statuses: // You can approve applications in statuses:
// - NEW — new // - NEW — new
// - SEEN — viewed // - SEEN — viewed
func (c Promotions) ApproveDiscountRequest(params *DiscountRequestParams) (*DiscountRequestResponse, error) { func (c Promotions) ApproveDiscountRequest(ctx context.Context, params *DiscountRequestParams) (*DiscountRequestResponse, error) {
url := "/v1/actions/discounts-task/approve" url := "/v1/actions/discounts-task/approve"
resp := &DiscountRequestResponse{} resp := &DiscountRequestResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -664,12 +695,12 @@ func (c Promotions) ApproveDiscountRequest(params *DiscountRequestParams) (*Disc
// You can decline applications in statuses: // You can decline applications in statuses:
// - NEW—new // - NEW—new
// - SEEN—viewed // - SEEN—viewed
func (c Promotions) DeclineDiscountRequest(params *DiscountRequestParams) (*DiscountRequestResponse, error) { func (c Promotions) DeclineDiscountRequest(ctx context.Context, params *DiscountRequestParams) (*DiscountRequestResponse, error) {
url := "/v1/actions/discounts-task/decline" url := "/v1/actions/discounts-task/decline"
resp := &DiscountRequestResponse{} resp := &DiscountRequestResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -56,7 +57,8 @@ func TestGetAvailablePromotions(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().GetAvailablePromotions() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().GetAvailablePromotions(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -125,7 +127,8 @@ func TestAddToPromotion(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().AddToPromotion(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().AddToPromotion(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -201,7 +204,8 @@ func TestProductsAvailableForPromotion(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().ProductsAvailableForPromotion(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().ProductsAvailableForPromotion(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -262,7 +266,8 @@ func TestProductsInPromotion(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().ProductsInPromotion(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().ProductsInPromotion(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -314,7 +319,8 @@ func TestRemoveProduct(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().RemoveProduct(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().RemoveProduct(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -373,7 +379,8 @@ func TestListHotSalePromotions(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().ListHotSalePromotions() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().ListHotSalePromotions(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -434,7 +441,8 @@ func TestProductsAvailableForHotSalePromotion(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().ProductsAvailableForHotSalePromotion(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().ProductsAvailableForHotSalePromotion(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -494,7 +502,8 @@ func TestAddProductsToHotSale(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().AddProductsToHotSale(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().AddProductsToHotSale(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -548,7 +557,8 @@ func TestRemoveProductsToHotSale(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().RemoveProductsToHotSale(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().RemoveProductsToHotSale(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -634,7 +644,8 @@ func TestListDiscountRequests(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().ListDiscountRequests(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().ListDiscountRequests(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -697,7 +708,8 @@ func TestApproveDiscountRequest(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().ApproveDiscountRequest(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().ApproveDiscountRequest(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -760,7 +772,8 @@ func TestDeclineDiscountRequest(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Promotions().DeclineDiscountRequest(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Promotions().DeclineDiscountRequest(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -15,29 +16,27 @@ type GetCurrentSellerRatingInfoResponse struct {
core.CommonResponse core.CommonResponse
// Rating groups list // Rating groups list
Groups []struct { Groups []GetCurrentSellerRatingInfoGroup `json:"groups"`
}
type GetCurrentSellerRatingInfoGroup struct {
// Ratings group name // Ratings group name
GroupName string `json:"group_name"` GroupName string `json:"group_name"`
// Ratings list // Ratings list
Items []struct { Items []GetCurrentSellerRatingInfoGroupItem `json:"items"`
// An indication that the penalty points balance is exceeded
PenaltyScoreExceeded bool `json:"penalty_score_exceeded"`
// An indication that you participate in the Premium program
Premium bool `json:"premium"`
}
type GetCurrentSellerRatingInfoGroupItem struct {
// Rating change: the ratio of the previous value to the current one // Rating change: the ratio of the previous value to the current one
Change struct { Change GetCurrentSellerRatingInfoGroupItemChange `json:"change"`
// How the rating value has changed:
// - DIRECTION_UNKNOWN — unknown.
// - DIRECTION_NONE — has not changed.
// - DIRECTION_RISE — has increased.
// - DIRECTION_FALL — has dropped.
Direction string `json:"direction"`
// What the change means:
// - MEANING_UNKNOWN — unknown.
// - MEANING_NONE — neutral.
// - MEANING_GOOD — the indicator is improving, everything is good.
// - MEANING_BAD — the indicator is dropping, you should do something.
Meaning string `json:"meaning"`
} `json:"change"`
// Current rating value // Current rating value
CurrentValue float64 `json:"current_value"` CurrentValue float64 `json:"current_value"`
@@ -74,22 +73,30 @@ type GetCurrentSellerRatingInfoResponse struct {
// - REVIEW_SCORE — score, // - REVIEW_SCORE — score,
// - COUNT // - COUNT
ValueType string `json:"value_type"` ValueType string `json:"value_type"`
} `json:"items"`
// An indication that the penalty points balance is exceeded
PenaltyScoreExceeded bool `json:"penalty_score_exceeded"`
// An indication that you participate in the Premium program
Premium bool `json:"premium"`
} `json:"groups"`
} }
func (c Rating) GetCurrentSellerRatingInfo() (*GetCurrentSellerRatingInfoResponse, error) { type GetCurrentSellerRatingInfoGroupItemChange struct {
// How the rating value has changed:
// - DIRECTION_UNKNOWN — unknown.
// - DIRECTION_NONE — has not changed.
// - DIRECTION_RISE — has increased.
// - DIRECTION_FALL — has dropped.
Direction string `json:"direction"`
// What the change means:
// - MEANING_UNKNOWN — unknown.
// - MEANING_NONE — neutral.
// - MEANING_GOOD — the indicator is improving, everything is good.
// - MEANING_BAD — the indicator is dropping, you should do something.
Meaning string `json:"meaning"`
}
func (c Rating) GetCurrentSellerRatingInfo(ctx context.Context) (*GetCurrentSellerRatingInfoResponse, error) {
url := "/v1/rating/summary" url := "/v1/rating/summary"
resp := &GetCurrentSellerRatingInfoResponse{} resp := &GetCurrentSellerRatingInfoResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -116,12 +123,21 @@ type GetSellerRatingInfoPeriodResponse struct {
core.CommonResponse core.CommonResponse
// Information on the Premium program penalty points // Information on the Premium program penalty points
PremiumScores []struct { PremiumScores []GetSellerRatingInfoPeriodPremiumScores `json:"premium_scores"`
// Information on the seller ratings
Ratings []GetSellerRatingInfoPeriodRating `json:"ratings"`
}
type GetSellerRatingInfoPeriodPremiumScores struct {
// Rating name // Rating name
Rating string `json:"rating"` Rating string `json:"rating"`
// Information on penalty points // Information on penalty points
Scores []struct { Scores []GetSellerRatingInfoPeriodPremiumScore `json:"scores"`
}
type GetSellerRatingInfoPeriodPremiumScore struct {
// Date when the penalty points were received // Date when the penalty points were received
Date time.Time `json:"date"` Date time.Time `json:"date"`
@@ -130,11 +146,9 @@ type GetSellerRatingInfoPeriodResponse struct {
// Number of received penalty points // Number of received penalty points
Value int32 `json:"value"` Value int32 `json:"value"`
} `json:"scores"` }
} `json:"premium_scores"`
// Information on the seller ratings type GetSellerRatingInfoPeriodRating struct {
Ratings []struct {
// Rating threshold, after which sales will be blocked // Rating threshold, after which sales will be blocked
DangerThreshold float64 `json:"danger_threshold"` DangerThreshold float64 `json:"danger_threshold"`
@@ -145,7 +159,13 @@ type GetSellerRatingInfoPeriodResponse struct {
Rating string `json:"rating"` Rating string `json:"rating"`
// Rating values list // Rating values list
Values []struct { Values []GetSellerRatingInfoPeriodRatingValue `json:"values"`
// Rating threshold, after which a warning about possible blocking appears
WarningThreshold float64 `json:"warning_threshold"`
}
type GetSellerRatingInfoPeriodRatingValue struct {
// Rating calculation start date // Rating calculation start date
DateFrom time.Time `json:"date_from"` DateFrom time.Time `json:"date_from"`
@@ -153,7 +173,13 @@ type GetSellerRatingInfoPeriodResponse struct {
DateTo time.Time `json:"date_to"` DateTo time.Time `json:"date_to"`
// Rating status // Rating status
Status struct { Status GetSellerRatingInfoPeriodRatingValueStatus `json:"status"`
// Rating value
Value float64 `json:"value"`
}
type GetSellerRatingInfoPeriodRatingValueStatus struct {
// Indication if the rating threshold for blocking is exceeded // Indication if the rating threshold for blocking is exceeded
Danger bool `json:"danger"` Danger bool `json:"danger"`
@@ -162,23 +188,14 @@ type GetSellerRatingInfoPeriodResponse struct {
// Indication of a warning that the threshold for blocking may be exceeded // Indication of a warning that the threshold for blocking may be exceeded
Warning bool `json:"warning"` Warning bool `json:"warning"`
} `json:"status"`
// Rating value
Value float64 `json:"value"`
} `json:"values"`
// Rating threshold, after which a warning about possible blocking appears
WarningThreshold float64 `json:"warning_threshold"`
} `json:"ratings"`
} }
func (c Rating) GetSellerRatingInfoForPeriod(params *GetSellerRatingInfoForPeriodParams) (*GetSellerRatingInfoPeriodResponse, error) { func (c Rating) GetSellerRatingInfoForPeriod(ctx context.Context, params *GetSellerRatingInfoForPeriodParams) (*GetSellerRatingInfoPeriodResponse, error) {
url := "/v1/rating/history" url := "/v1/rating/history"
resp := &GetSellerRatingInfoPeriodResponse{} resp := &GetSellerRatingInfoPeriodResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -58,7 +59,8 @@ func TestGetCurrentRatingInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Rating().GetCurrentSellerRatingInfo() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Rating().GetCurrentSellerRatingInfo(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -146,7 +148,8 @@ func TestGetRatingInfoForPeriod(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Rating().GetSellerRatingInfoForPeriod(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Rating().GetSellerRatingInfoForPeriod(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -38,9 +39,18 @@ type GetReportsListResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetReportsListResult `json:"result"`
}
type GetReportsListResult struct {
// Array with generated reports // Array with generated reports
Reports []struct { Reports []GetReportsListResultReport `json:"reports"`
// Total number of reports
Total int32 `json:"total"`
}
type GetReportsListResultReport struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
@@ -54,8 +64,7 @@ type GetReportsListResponse struct {
File string `json:"file"` File string `json:"file"`
// Array with the filters specified when the seller created the report // Array with the filters specified when the seller created the report
Params struct { Params map[string]string `json:"params"`
} `json:"params"`
// Report type: // Report type:
// - SELLER_PRODUCTS — products report, // - SELLER_PRODUCTS — products report,
@@ -72,20 +81,15 @@ type GetReportsListResponse struct {
// - `success` // - `success`
// - `failed` // - `failed`
Status string `json:"status"` Status string `json:"status"`
} `json:"reports"`
// Total number of reports
Total int32 `json:"total"`
} `json:"result"`
} }
// Returns the list of reports that have been generated before // Returns the list of reports that have been generated before
func (c Reports) GetList(params *GetReportsListParams) (*GetReportsListResponse, error) { func (c Reports) GetList(ctx context.Context, params *GetReportsListParams) (*GetReportsListResponse, error) {
url := "/v1/report/list" url := "/v1/report/list"
resp := &GetReportsListResponse{} resp := &GetReportsListResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -103,7 +107,10 @@ type GetReportDetailsResponse struct {
core.CommonResponse core.CommonResponse
// Report details // Report details
Result struct { Result GetReportDetailResult `json:"result"`
}
type GetReportDetailResult struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
@@ -134,16 +141,15 @@ type GetReportDetailsResponse struct {
// - success // - success
// - failed // - failed
Status string `json:"status"` Status string `json:"status"`
} `json:"result"`
} }
// Returns information about a created report by its identifier // Returns information about a created report by its identifier
func (c Reports) GetReportDetails(params *GetReportDetailsParams) (*GetReportDetailsResponse, error) { func (c Reports) GetReportDetails(ctx context.Context, params *GetReportDetailsParams) (*GetReportDetailsResponse, error) {
url := "/v1/report/info" url := "/v1/report/info"
resp := &GetReportDetailsResponse{} resp := &GetReportDetailsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -178,20 +184,23 @@ type GetFinancialReportResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetFinancialResultResult `json:"result"`
}
type GetFinancialResultResult struct {
// Reports list // Reports list
CashFlows []struct { CashFlows []GetFinancialResultResultCashflow `json:"cash_flows"`
// Detailed info
Details GetFinancialResultResultDetail `json:"details"`
// Number of pages with reports
PageCount int64 `json:"page_count"`
}
type GetFinancialResultResultCashflow struct {
// Period data // Period data
Period struct { Period GetFinancialResultResultCashflowPeriod `json:"period"`
// Period identifier
Id int64 `json:"id"`
// Period start
Begin time.Time `json:"begin"`
// Period end
End time.Time `json:"end"`
} `json:"period"`
// Sum of sold products prices // Sum of sold products prices
OrdersAmount float64 `json:"order_amount"` OrdersAmount float64 `json:"order_amount"`
@@ -210,113 +219,186 @@ type GetFinancialReportResponse struct {
// Code of the currency used to calculate the commissions // Code of the currency used to calculate the commissions
CurrencyCode string `json:"currency_code"` CurrencyCode string `json:"currency_code"`
} `json:"cash_flows"` }
// Detailed info type GetFinancialResultResultCashflowPeriod struct {
Details struct { // Period identifier
Id int64 `json:"id"`
// Period start
Begin time.Time `json:"begin"`
// Period end
End time.Time `json:"end"`
}
type GetFinancialResultResultDetail struct {
// Balance on the beginning of period // Balance on the beginning of period
BeginBalanceAmount float64 `json:"begin_balance_amount"` BeginBalanceAmount float64 `json:"begin_balance_amount"`
// Orders // Orders
Delivery struct { Delivery GetFinancialResultResultDetailDelivery `json:"delivery"`
Total float64 `json:"total"`
Amount float64 `json:"amount"`
DeliveryServices struct {
Total float64 `json:"total"`
Items []struct {
Name DetailsDeliveryItemName `json:"name"`
Price float64 `json:"price"`
} `json:"items"`
} `json:"delivery_services"`
} `json:"delivery"`
// Amount to be paid for the period
InvoiceTransfer float64 `json:"invoice_transfer"` InvoiceTransfer float64 `json:"invoice_transfer"`
// Transfer under loan agreements
Loan float64 `json:"loan"` Loan float64 `json:"loan"`
Payments []struct { // Paid for the period
CurrencyCode string `json:"currency_code"` Payments []GetFinancialResultResultDetailPayment `json:"payments"`
Payment float64 `json:"payment"` // Period data
} `json:"payments"` Period GetFinancialResultResultDetailPeriod `json:"period"`
Period struct { // Returns and cancellations
Begin time.Time `json:"begin"` Return GetFinancialResultResultDetailReturn `json:"return"`
End time.Time `json:"end"` // rFBS transfers
RFBS GetFinancialResultResultDetailRFBS `json:"rfbs"`
Id int64 `json:"id"` // Services
} `json:"period"` Services GetFinancialResultResultDetailService `json:"services"`
Return struct { // Compensation and other accruals
Others GetFinancialResultResultDetailOthers `json:"others"`
// Balance at the end of the period
EndBalanceAmount float64 `json:"end_balance_amount"`
}
type GetFinancialResultResultDetailDelivery struct {
// Total amount
Total float64 `json:"total"` Total float64 `json:"total"`
// Amount for which products were purchased, including commission fees
Amount float64 `json:"amount"` Amount float64 `json:"amount"`
ReturnServices struct { // Processing and delivery fees
DeliveryServices GetFinancialResultResultDetailDeliveryServices `json:"delivery_services"`
}
type GetFinancialResultResultDetailDeliveryServices struct {
// Total amount
Total float64 `json:"total"` Total float64 `json:"total"`
Items []struct { // Details
Items []GetFinancialResultResultDetailDeliveryServicesItem `json:"items"`
}
type GetFinancialResultResultDetailDeliveryServicesItem struct {
// Operation name
Name DetailsDeliveryItemName `json:"name"`
// Amount by operation
Price float64 `json:"price"`
}
type GetFinancialResultResultDetailPayment struct {
// Currency
CurrencyCode string `json:"currency_code"`
// Payment amount
Payment float64 `json:"payment"`
}
type GetFinancialResultResultDetailPeriod struct {
// Period start
Begin time.Time `json:"begin"`
// Period end
End time.Time `json:"end"`
// Period identifier
Id int64 `json:"id"`
}
type GetFinancialResultResultDetailReturn struct {
// Total amount
Total float64 `json:"total"`
// Amount of returns received, including commission fees
Amount float64 `json:"amount"`
// Returns and cancellation fees
ReturnServices GetFinancialResultResultDetailReturnServices `json:"return_services"`
}
type GetFinancialResultResultDetailReturnServices struct {
// Total amount
Total float64 `json:"total"`
// Details
Items []GetFinancialResultResultDetailReturnServicesItem `json:"items"`
}
type GetFinancialResultResultDetailReturnServicesItem struct {
// Operation name
Name DetailsReturnServiceName `json:"name"` Name DetailsReturnServiceName `json:"name"`
// Amount by operation
Price float64 `json:"price"` Price float64 `json:"price"`
} `json:"items"` }
} `json:"return_services"`
} `json:"return"`
RFBS struct { type GetFinancialResultResultDetailRFBS struct {
// Total amount
Total float64 `json:"total"` Total float64 `json:"total"`
// Transfers from customers
TransferDelivery float64 `json:"transfer_delivery"` TransferDelivery float64 `json:"transfer_delivery"`
// Return of transfers to customers
TransferDeliveryReturn float64 `json:"transfer_delivery_return"` TransferDeliveryReturn float64 `json:"transfer_delivery_return"`
// Compensation of delivery fees
CompensationDeliveryReturn float64 `json:"compensation_delivery_return"` CompensationDeliveryReturn float64 `json:"compensation_delivery_return"`
// Transfers of partial refunds to customers
PartialCompensation float64 `json:"partial_compensation"` PartialCompensation float64 `json:"partial_compensation"`
// Compensation of partial refunds
PartialCompensationReturn float64 `json:"partial_compensation_return"` PartialCompensationReturn float64 `json:"partial_compensation_return"`
} `json:"rfbs"` }
Services struct { type GetFinancialResultResultDetailService struct {
// Total amount
Total float64 `json:"total"` Total float64 `json:"total"`
Items []struct { // Details
Items []GetFinancialResultResultDetailServiceItem `json:"items"`
}
type GetFinancialResultResultDetailServiceItem struct {
// Operation name
Name DetailsServiceItemName `json:"name"` Name DetailsServiceItemName `json:"name"`
// Amount by operation
Price float64 `json:"price"` Price float64 `json:"price"`
} `json:"items"` }
} `json:"services"`
Others struct { type GetFinancialResultResultDetailOthers struct {
// Total amount
Total float64 `json:"total"` Total float64 `json:"total"`
Items []struct { // Details
Items []GetFinancialResultResultDetailOthersItem `json:"items"`
}
type GetFinancialResultResultDetailOthersItem struct {
// Operation name
Name DetailsOtherItemName `json:"name"` Name DetailsOtherItemName `json:"name"`
// Amount by operation
Price float64 `json:"price"` Price float64 `json:"price"`
} `json:"items"`
} `json:"others"`
EndBalanceAmount float64 `json:"end_balance_amount"`
} `json:"details"`
// Number of pages with reports
PageCount int64 `json:"page_count"`
} `json:"result"`
} }
// Returns information about a created report by its identifier // Returns information about a created report by its identifier
func (c Reports) GetFinancial(params *GetFinancialReportParams) (*GetFinancialReportResponse, error) { func (c Reports) GetFinancial(ctx context.Context, params *GetFinancialReportParams) (*GetFinancialReportResponse, error) {
url := "/v1/finance/cash-flow-statement/list" url := "/v1/finance/cash-flow-statement/list"
resp := &GetFinancialReportResponse{} resp := &GetFinancialReportResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -350,19 +432,21 @@ type GetProductsReportResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetProductsReportResult `json:"result"`
}
type GetProductsReportResult struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
} `json:"result"`
} }
// Method for getting a report with products data. For example, Ozon ID, number of products, prices, status // Method for getting a report with products data. For example, Ozon ID, number of products, prices, status
func (c Reports) GetProducts(params *GetProductsReportParams) (*GetProductsReportResponse, error) { func (c Reports) GetProducts(ctx context.Context, params *GetProductsReportParams) (*GetProductsReportResponse, error) {
url := "/v1/report/products/create" url := "/v1/report/products/create"
resp := &GetProductsReportResponse{} resp := &GetProductsReportResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -383,19 +467,21 @@ type GetStocksReportResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetStocksReportResult `json:"result"`
}
type GetStocksReportResult struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
} `json:"result"`
} }
// Report with information about the number of available and reserved products in stock // Report with information about the number of available and reserved products in stock
func (c Reports) GetStocks(params *GetStocksReportParams) (*GetStocksReportResponse, error) { func (c Reports) GetStocks(ctx context.Context, params *GetStocksReportParams) (*GetStocksReportResponse, error) {
url := "/v1/report/stock/create" url := "/v1/report/stock/create"
resp := &GetStocksReportResponse{} resp := &GetStocksReportResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -422,10 +508,12 @@ type GetProductsMovementReportResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetProductsMovementReportResult `json:"result"`
}
type GetProductsMovementReportResult struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
} `json:"result"`
} }
// Report with complete information on products, as well as the number of products with statuses: // Report with complete information on products, as well as the number of products with statuses:
@@ -433,12 +521,12 @@ type GetProductsMovementReportResponse struct {
// - products in transit between the fulfillment centers, // - products in transit between the fulfillment centers,
// - products in delivery, // - products in delivery,
// - products to be sold // - products to be sold
func (c Reports) GetProductsMovement(params *GetProductsMovementReportParams) (*GetProductsMovementReportResponse, error) { func (c Reports) GetProductsMovement(ctx context.Context, params *GetProductsMovementReportParams) (*GetProductsMovementReportResponse, error) {
url := "/v1/report/products/movement/create" url := "/v1/report/products/movement/create"
resp := &GetProductsMovementReportResponse{} resp := &GetProductsMovementReportResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -473,21 +561,23 @@ type GetReturnsReportResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetReturnReportResult `json:"result"`
}
type GetReturnReportResult struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
} `json:"result"`
} }
// The report contains information about returned products that were accepted from the customer, ready for pickup, or delivered to the seller. // The report contains information about returned products that were accepted from the customer, ready for pickup, or delivered to the seller.
// //
// The method is only suitable for orders shipped from the seller's warehouse // The method is only suitable for orders shipped from the seller's warehouse
func (c Reports) GetReturns(params *GetReturnsReportParams) (*GetReturnsReportResponse, error) { func (c Reports) GetReturns(ctx context.Context, params *GetReturnsReportParams) (*GetReturnsReportResponse, error) {
url := "/v1/report/returns/create" url := "/v1/report/returns/create"
resp := &GetReturnsReportResponse{} resp := &GetReturnsReportResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -542,10 +632,12 @@ type GetShipmentReportResponse struct {
core.CommonResponse core.CommonResponse
// Method result // Method result
Result struct { Result GetShipmentReportResult `json:"result"`
}
type GetShipmentReportResult struct {
// Unique report identifier // Unique report identifier
Code string `json:"code"` Code string `json:"code"`
} `json:"result"`
} }
// Shipment report with orders details: // Shipment report with orders details:
@@ -555,12 +647,12 @@ type GetShipmentReportResponse struct {
// - shipment numbers // - shipment numbers
// - shipment costs // - shipment costs
// - shipments contents // - shipments contents
func (c Reports) GetShipment(params *GetShipmentReportParams) (*GetShipmentReportResponse, error) { func (c Reports) GetShipment(ctx context.Context, params *GetShipmentReportParams) (*GetShipmentReportResponse, error) {
url := "/v1/report/postings/create" url := "/v1/report/postings/create"
resp := &GetShipmentReportResponse{} resp := &GetShipmentReportResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -580,12 +672,12 @@ type IssueOnDiscountedProductsResponse struct {
// For example, Ozon can discount a product due to damage when delivering. // For example, Ozon can discount a product due to damage when delivering.
// //
// Returns report identifier. To get the report, send the identifier in the request body of a method `/v1/report/discounted/info` // Returns report identifier. To get the report, send the identifier in the request body of a method `/v1/report/discounted/info`
func (c Reports) IssueOnDiscountedProducts() (*IssueOnDiscountedProductsResponse, error) { func (c Reports) IssueOnDiscountedProducts(ctx context.Context) (*IssueOnDiscountedProductsResponse, error) {
url := "/v1/report/discounted/create" url := "/v1/report/discounted/create"
resp := &IssueOnDiscountedProductsResponse{} resp := &IssueOnDiscountedProductsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -603,7 +695,10 @@ type ReportOnDiscountedProductsResponse struct {
core.CommonResponse core.CommonResponse
// Report information // Report information
Report struct { Report ReportonDiscountedProductsReport `json:"report"`
}
type ReportonDiscountedProductsReport struct {
// Report creation date // Report creation date
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
@@ -619,16 +714,15 @@ type ReportOnDiscountedProductsResponse struct {
// Report generation error code // Report generation error code
Error string `json:"error"` Error string `json:"error"`
} `json:"report"`
} }
// By report identifier, returns information about the report generated earlier // By report identifier, returns information about the report generated earlier
func (c Reports) ReportOnDiscountedProducts(params *ReportOnDiscountedProductsParams) (*ReportOnDiscountedProductsResponse, error) { func (c Reports) ReportOnDiscountedProducts(ctx context.Context, params *ReportOnDiscountedProductsParams) (*ReportOnDiscountedProductsResponse, error) {
url := "/v1/report/discounted/info" url := "/v1/report/discounted/info"
resp := &ReportOnDiscountedProductsResponse{} resp := &ReportOnDiscountedProductsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -638,12 +732,12 @@ func (c Reports) ReportOnDiscountedProducts(params *ReportOnDiscountedProductsPa
} }
// By report identifier, returns information about the report generated earlier // By report identifier, returns information about the report generated earlier
func (c Reports) ListReportsOnDiscountedProducts() (*ReportOnDiscountedProductsResponse, error) { func (c Reports) ListReportsOnDiscountedProducts(ctx context.Context) (*ReportOnDiscountedProductsResponse, error) {
url := "/v1/report/discounted/list" url := "/v1/report/discounted/list"
resp := &ReportOnDiscountedProductsResponse{} resp := &ReportOnDiscountedProductsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -69,7 +70,8 @@ func TestGetList(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetList(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetList(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -130,7 +132,8 @@ func TestGetReportDetails(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetReportDetails(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetReportDetails(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -274,7 +277,8 @@ func TestGetFinancialReport(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetFinancial(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetFinancial(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -328,7 +332,8 @@ func TestGetProductsReport(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -380,7 +385,8 @@ func TestGetStocksReport(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetStocks(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetStocks(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -435,7 +441,8 @@ func TestGetProductsMovementReport(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetProductsMovement(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetProductsMovement(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -491,7 +498,8 @@ func TestGetReturnsReport(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetReturns(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetReturns(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -549,7 +557,8 @@ func TestGetShipmentReport(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().GetShipment(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().GetShipment(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -596,7 +605,8 @@ func TestIssueOnDiscountedProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().IssueOnDiscountedProducts() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().IssueOnDiscountedProducts(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -653,7 +663,8 @@ func TestReportOnDiscountedProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().ReportOnDiscountedProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().ReportOnDiscountedProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -701,7 +712,8 @@ func TestListReportsOnDiscountedProducts(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Reports().ListReportsOnDiscountedProducts() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Reports().ListReportsOnDiscountedProducts(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -28,7 +29,8 @@ type GetFBOReturnsFilter struct {
// Shipment number // Shipment number
PostingNumber string `json:"posting_number"` PostingNumber string `json:"posting_number"`
Status []string `json:"status"` // Return status
Status []GetFBOReturnsFilterStatus `json:"status"`
} }
type GetFBOReturnsResponse struct { type GetFBOReturnsResponse struct {
@@ -38,7 +40,10 @@ type GetFBOReturnsResponse struct {
LastId int64 `json:"last_id"` LastId int64 `json:"last_id"`
// Returns information // Returns information
Returns []struct { Returns []GetFBOReturnsReturn `json:"returns"`
}
type GetFBOReturnsReturn struct {
// Time when a return was received from the customer // Time when a return was received from the customer
AcceptedFromCustomerMoment time.Time `json:"accepted_from_customer_moment"` AcceptedFromCustomerMoment time.Time `json:"accepted_from_customer_moment"`
@@ -70,17 +75,16 @@ type GetFBOReturnsResponse struct {
SKU int64 `json:"sku"` SKU int64 `json:"sku"`
// Return status // Return status
Status string `json:"status_name"` Status GetFBOReturnsReturnStatus `json:"status_name"`
} `json:"returns"`
} }
// Method for getting information on returned products that are sold from the Ozon warehouse // Method for getting information on returned products that are sold from the Ozon warehouse
func (c Returns) GetFBOReturns(params *GetFBOReturnsParams) (*GetFBOReturnsResponse, error) { func (c Returns) GetFBOReturns(ctx context.Context, params *GetFBOReturnsParams) (*GetFBOReturnsResponse, error) {
url := "/v3/returns/company/fbo" url := "/v3/returns/company/fbo"
resp := &GetFBOReturnsResponse{} resp := &GetFBOReturnsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -98,9 +102,10 @@ type GetFBSReturnsParams struct {
// - minimum — 1 // - minimum — 1
Limit int64 `json:"limit"` Limit int64 `json:"limit"`
// Number of elements that will be skipped in the response. // Return identifier that was loaded the last time.
// For example, if offset=10, the response will start with the 11th element found // Return identifiers with the higher value than `last_id`
Offset int64 `json:"offset"` // will be returned in the response.
LastId int64 `json:"offset"`
} }
type GetFBSReturnsFilter struct { type GetFBSReturnsFilter struct {
@@ -108,7 +113,7 @@ type GetFBSReturnsFilter struct {
AcceptedFromCustomerMoment GetFBSReturnsFilterTimeRange `json:"accepted_from_customer_moment"` AcceptedFromCustomerMoment GetFBSReturnsFilterTimeRange `json:"accepted_from_customer_moment"`
// Last day of free storage // Last day of free storage
LastFreeWaitingDay []GetFBSReturnsFilterTimeRange `json:"last_free_waiting_dat"` LastFreeWaitingDay GetFBSReturnsFilterTimeRange `json:"last_free_waiting_dat"`
// Order ID // Order ID
OrderId int64 `json:"order_id"` OrderId int64 `json:"order_id"`
@@ -122,13 +127,8 @@ type GetFBSReturnsFilter struct {
// Product ID // Product ID
ProductOfferId string `json:"product_offer_id"` ProductOfferId string `json:"product_offer_id"`
// Return status: // Return status
// - returned_to_seller — returned to seller, Status GetFBSReturnsFilterStatus `json:"status"`
// - 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 { type GetFBSReturnsFilterTimeRange struct {
@@ -150,12 +150,16 @@ type GetFBSReturnsFilterTimeRange struct {
type GetFBSReturnsResponse struct { type GetFBSReturnsResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Return identifier that was loaded the last time.
// Elements counter in the response // Return identifiers with the higher value than `last_id`
Count int64 `json:"count"` // will be returned in the response
LastId int64 `json:"last_id"`
// Returns information // Returns information
Returns []struct { Returns []GetFBSReturnResultReturn `json:"returns"`
}
type GetFBSReturnResultReturn struct {
// Time of receiving the return from the customer // Time of receiving the return from the customer
AcceptedFromCustomerAmount string `json:"accepted_from_customer_amount"` AcceptedFromCustomerAmount string `json:"accepted_from_customer_amount"`
@@ -168,7 +172,10 @@ type GetFBSReturnsResponse struct {
// Commission percentage // Commission percentage
CommissionPercent float64 `json:"commission_percent"` CommissionPercent float64 `json:"commission_percent"`
// Return identifier // Product item identifier in the Ozon logistics system
ExemplarId int64 `json:"exemplar_id"`
// Return identifier in the Ozon accounting system
Id int64 `json:"id"` Id int64 `json:"id"`
// If the product is in transit — true // If the product is in transit — true
@@ -192,6 +199,8 @@ type GetFBSReturnsResponse struct {
// Shipment number // Shipment number
PostingNumber string `json:"posting_number"` PostingNumber string `json:"posting_number"`
PickingTag string `json:"picking_tag"`
// Current product price without a discount // Current product price without a discount
Price float64 `json:"price"` Price float64 `json:"price"`
@@ -207,6 +216,12 @@ type GetFBSReturnsResponse struct {
// Product quantity // Product quantity
Quantity int64 `json:"quantity"` Quantity int64 `json:"quantity"`
// Barcode on the return label. Use this parameter value to work with the return label
ReturnBarcode string `json:"return_barcode"`
// Package unit identifier in the Ozon logistics system
ReturnClearingId int64 `json:"return_clearing_id"`
// Product return date // Product return date
ReturnDate string `json:"return_date"` ReturnDate string `json:"return_date"`
@@ -230,17 +245,15 @@ type GetFBSReturnsResponse struct {
// Return status // Return status
Status string `json:"status"` Status string `json:"status"`
} `json:"returns"`
} `json:"result"`
} }
// Method for getting information on returned products that are sold from the seller's warehouse // Method for getting information on returned products that are sold from the seller's warehouse
func (c Returns) GetFBSReturns(params *GetFBSReturnsParams) (*GetFBSReturnsResponse, error) { func (c Returns) GetFBSReturns(ctx context.Context, params *GetFBSReturnsParams) (*GetFBSReturnsResponse, error) {
url := "/v2/returns/company/fbs" url := "/v3/returns/company/fbs"
resp := &GetFBSReturnsResponse{} resp := &GetFBSReturnsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -61,7 +62,8 @@ func TestGetFBOReturns(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Returns().GetFBOReturns(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Returns().GetFBOReturns(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -105,42 +107,43 @@ func TestGetFBSReturns(t *testing.T) {
Status: "returned_to_seller", Status: "returned_to_seller",
}, },
Limit: 1000, Limit: 1000,
Offset: 0, LastId: 0,
}, },
`{ `{
"result": { "last_id": 0,
"returns": [ "returns": [
{ {
"id": 19166541735000, "accepted_from_customer_moment": "string",
"clearing_id": 19166541725000, "clearing_id": 23,
"posting_number": "07402477-0022-2", "commission": 21,
"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_percent": 0,
"commission": 0, "exemplar_id": 42,
"id": 123,
"is_moving": true,
"is_opened": true,
"last_free_waiting_day": "string",
"place_id": 122,
"moving_to_place_name": "string",
"picking_amount": 0,
"posting_number": "string",
"picking_tag": "string",
"price": 0,
"price_without_commission": 0, "price_without_commission": 0,
"is_moving": false, "product_id": 2222,
"moving_to_place_name": "МОСКВА_ХАБ", "product_name": "string",
"waiting_for_seller_days": 2, "quantity": 0,
"picking_amount": null, "return_barcode": "string",
"accepted_from_customer_moment": null, "return_clearing_id": 0,
"picking_tag": null "return_date": "string",
} "return_reason_name": "string",
], "waiting_for_seller_date_time": "string",
"count": 1 "returned_to_seller_date_time": "string",
"waiting_for_seller_days": 0,
"returns_keeping_cost": 0,
"sku": 33332,
"status": "string"
} }
]
}`, }`,
}, },
// Test No Client-Id or Api-Key // Test No Client-Id or Api-Key
@@ -158,7 +161,8 @@ func TestGetFBSReturns(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Returns().GetFBSReturns(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Returns().GetFBSReturns(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -168,20 +172,17 @@ func TestGetFBSReturns(t *testing.T) {
} }
if resp.StatusCode == http.StatusOK { if resp.StatusCode == http.StatusOK {
if int(resp.Result.Count) != len(resp.Result.Returns) { if len(resp.Returns) > 0 {
t.Errorf("Count must equal to length of returns") if resp.Returns[0].Id == 0 {
}
if len(resp.Result.Returns) > 0 {
if resp.Result.Returns[0].Id == 0 {
t.Errorf("Id cannot be 0") t.Errorf("Id cannot be 0")
} }
if resp.Result.Returns[0].ProductId == 0 { if resp.Returns[0].ProductId == 0 {
t.Errorf("Product id cannot be 0") t.Errorf("Product id cannot be 0")
} }
if resp.Result.Returns[0].SKU == 0 { if resp.Returns[0].SKU == 0 {
t.Errorf("SKU cannot be 0") t.Errorf("SKU cannot be 0")
} }
if resp.Result.Returns[0].Status == "" { if resp.Returns[0].Status == "" {
t.Errorf("Status cannot be empty") t.Errorf("Status cannot be empty")
} }
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
core "github.com/diphantxm/ozon-api-client" core "github.com/diphantxm/ozon-api-client"
@@ -11,29 +12,39 @@ type Strategies struct {
} }
type ListCompetitorsParams struct { type ListCompetitorsParams struct {
// Page number from which you want to download the list of competitors.
// The minimum value is 1
Page int64 `json:"page"` Page int64 `json:"page"`
// Maximum number of competitors on the page. Allowed values: 150
Limit int64 `json:"limit"` Limit int64 `json:"limit"`
} }
type ListCompetitorsResponse struct { type ListCompetitorsResponse struct {
core.CommonResponse core.CommonResponse
Competitors []struct { // List of competitors
Name string `json:"name"` Competitors []ListCompetitorsCompetitor `json:"competitors"`
Id int64 `json:"id"`
} `json:"competitors"`
// Total number of competitors
Total int32 `json:"total"` Total int32 `json:"total"`
} }
func (c Strategies) ListCompetitors(params *ListCompetitorsParams) (*ListCompetitorsResponse, error) { type ListCompetitorsCompetitor struct {
// Competitor's name
Name string `json:"name"`
// Competitor identifier
Id int64 `json:"id"`
}
// Method for getting a list of competitors—sellers with similar products in other online stores and marketplaces
func (c Strategies) ListCompetitors(ctx context.Context, params *ListCompetitorsParams) (*ListCompetitorsResponse, error) {
url := "/v1/pricing-strategy/competitors/list" url := "/v1/pricing-strategy/competitors/list"
resp := &ListCompetitorsResponse{} resp := &ListCompetitorsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -43,41 +54,56 @@ func (c Strategies) ListCompetitors(params *ListCompetitorsParams) (*ListCompeti
} }
type ListStrategiesParams struct { type ListStrategiesParams struct {
// Page number from which you want to download the list of competitors.
// The minimum value is 1
Page int64 `json:"page"` Page int64 `json:"page"`
// Maximum number of competitors on the page. Allowed values: 150
Limit int64 `json:"limit"` Limit int64 `json:"limit"`
} }
type ListStrategiesResponse struct { type ListStrategiesResponse struct {
core.CommonResponse core.CommonResponse
Strategies []struct { // List of strategies
Id string `json:"id"` Strategies []ListStrategiesStrategy `json:"strategies"`
Name string `json:"name"`
Type StrategyType `json:"type"`
UpdateType StrategyUpdateType `json:"update_type"`
UpdatedAt string `json:"updated_at"`
ProductsCount int64 `json:"products_count"`
CompetitorsCount int64 `json:"competitors_count"`
Enabled bool `json:"enabled"`
} `json:"strategies"`
// Total number of strategies
Total int32 `json:"total"` Total int32 `json:"total"`
} }
func (c Strategies) List(params *ListStrategiesParams) (*ListStrategiesResponse, error) { type ListStrategiesStrategy struct {
// Strategy identifier
Id string `json:"id"`
// Strategy name
Name string `json:"name"`
// Strategy type
Type StrategyType `json:"type"`
// Type of the last strategy change
UpdateType StrategyUpdateType `json:"update_type"`
// Date of last change
UpdatedAt string `json:"updated_at"`
// Number of products in the strategy
ProductsCount int64 `json:"products_count"`
// Number of selected competitors
CompetitorsCount int64 `json:"competitors_count"`
// Strategy status
Enabled bool `json:"enabled"`
}
func (c Strategies) List(ctx context.Context, params *ListStrategiesParams) (*ListStrategiesResponse, error) {
url := "/v1/pricing-strategy/list" url := "/v1/pricing-strategy/list"
resp := &ListStrategiesResponse{} resp := &ListStrategiesResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -87,31 +113,40 @@ func (c Strategies) List(params *ListStrategiesParams) (*ListStrategiesResponse,
} }
type CreateStrategyParams struct { type CreateStrategyParams struct {
// List of competitors
Competitors []CreateStrategyCompetitor `json:"competitors"` Competitors []CreateStrategyCompetitor `json:"competitors"`
// Strategy name
StrategyName string `json:"strategy_name"` StrategyName string `json:"strategy_name"`
} }
type CreateStrategyCompetitor struct { type CreateStrategyCompetitor struct {
// Coefficient by which the minimum price among competitors will be multiplied.
// The allowed range is from 0.5 to 1.2
Coefficient float32 `json:"coefficient"` Coefficient float32 `json:"coefficient"`
// Competitor identifier
CompetitorId int64 `json:"competitor_id"` CompetitorId int64 `json:"competitor_id"`
} }
type CreateStrategyResponse struct { type CreateStrategyResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
StrategyId string `json:"strategy_id"` Result CreateStrategyResult `json:"result"`
} `json:"result"`
} }
func (c Strategies) Create(params *CreateStrategyParams) (*CreateStrategyResponse, error) { type CreateStrategyResult struct {
// Strategy identifier
StrategyId string `json:"strategy_id"`
}
func (c Strategies) Create(ctx context.Context, params *CreateStrategyParams) (*CreateStrategyResponse, error) {
url := "/v1/pricing-strategy/create" url := "/v1/pricing-strategy/create"
resp := &CreateStrategyResponse{} resp := &CreateStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -121,31 +156,40 @@ func (c Strategies) Create(params *CreateStrategyParams) (*CreateStrategyRespons
} }
type InfoStrategyParams struct { type InfoStrategyParams struct {
// Strategy identifier
StrategyId string `json:"strategy_id"` StrategyId string `json:"strategy_id"`
} }
type InfoStrategyResponse struct { type InfoStrategyResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
Competitors []CreateStrategyCompetitor `json:"competitors"` Result InfoStrategyResult `json:"result"`
Enabled bool `json:"enabled"`
Name string `json:"name"`
Type StrategyType `json:"type"`
UpdateType StrategyUpdateType `json:"update_type"`
} `json:"result"`
} }
func (c Strategies) Info(params *InfoStrategyParams) (*InfoStrategyResponse, error) { type InfoStrategyResult struct {
// List of competitors
Competitors []CreateStrategyCompetitor `json:"competitors"`
// Strategy status
Enabled bool `json:"enabled"`
// Strategy name
Name string `json:"name"`
// Strategy type
Type StrategyType `json:"type"`
// Type of the last strategy change
UpdateType StrategyUpdateType `json:"update_type"`
}
func (c Strategies) Info(ctx context.Context, params *InfoStrategyParams) (*InfoStrategyResponse, error) {
url := "/v1/pricing-strategy/info" url := "/v1/pricing-strategy/info"
resp := &InfoStrategyResponse{} resp := &InfoStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -155,10 +199,13 @@ func (c Strategies) Info(params *InfoStrategyParams) (*InfoStrategyResponse, err
} }
type UpdateStrategyParams struct { type UpdateStrategyParams struct {
// List of competitors
Competitors []CreateStrategyCompetitor `json:"competitors"` Competitors []CreateStrategyCompetitor `json:"competitors"`
// Product identifier
StrategyId string `json:"strategy_id"` StrategyId string `json:"strategy_id"`
// Strategy name
StrategyName string `json:"strategy_name"` StrategyName string `json:"strategy_name"`
} }
@@ -166,12 +213,12 @@ type UpdateStrategyResponse struct {
core.CommonResponse core.CommonResponse
} }
func (c Strategies) Update(params *UpdateStrategyParams) (*UpdateStrategyResponse, error) { func (c Strategies) Update(ctx context.Context, params *UpdateStrategyParams) (*UpdateStrategyResponse, error) {
url := "/v1/pricing-strategy/update" url := "/v1/pricing-strategy/update"
resp := &UpdateStrategyResponse{} resp := &UpdateStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -181,33 +228,45 @@ func (c Strategies) Update(params *UpdateStrategyParams) (*UpdateStrategyRespons
} }
type AddProductsToStrategyParams struct { type AddProductsToStrategyParams struct {
// List of product identifiers. The maximum number is 50
ProductId []int64 `json:"product_id"` ProductId []int64 `json:"product_id"`
// Product identifier
StrategyId string `json:"strategy_id"` StrategyId string `json:"strategy_id"`
} }
type AddProductsToStrategyResponse struct { type AddProductsToStrategyResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
Errors []struct { Result AddProductsToStrategyResult `json:"result"`
Code string `json:"code"`
Error string `json:"error"`
ProductId int64 `json:"product_id"`
} `json:"errors"`
FailedProductCount int32 `json:"failed_product_count"`
} `json:"result"`
} }
func (c Strategies) AddProducts(params *AddProductsToStrategyParams) (*AddProductsToStrategyResponse, error) { type AddProductsToStrategyResult struct {
// Products with errors
Errors []AddProductsToStrategyResultError `json:"errors"`
// Number of products with errors
FailedProductCount int32 `json:"failed_product_count"`
}
type AddProductsToStrategyResultError struct {
// Error code
Code string `json:"code"`
// Error message
Error string `json:"error"`
// Product identifier
ProductId int64 `json:"product_id"`
}
func (c Strategies) AddProducts(ctx context.Context, params *AddProductsToStrategyParams) (*AddProductsToStrategyResponse, error) {
url := "/v1/pricing-strategy/products/add" url := "/v1/pricing-strategy/products/add"
resp := &AddProductsToStrategyResponse{} resp := &AddProductsToStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -217,27 +276,36 @@ func (c Strategies) AddProducts(params *AddProductsToStrategyParams) (*AddProduc
} }
type GetStrategiesByProductIdsParams struct { type GetStrategiesByProductIdsParams struct {
// List of product identifiers. The maximum number is 50
ProductId []int64 `json:"product_id"` ProductId []int64 `json:"product_id"`
} }
type GetStrategiesByProductIdsResponse struct { type GetStrategiesByProductIdsResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
ProductsInfo []struct { Result GetStrategiesByProductIdsResult `json:"result"`
ProductId int64 `json:"product_id"`
StrategyId string `json:"strategy_id"`
} `json:"products_info"`
} `json:"result"`
} }
func (c Strategies) GetByProductIds(params *GetStrategiesByProductIdsParams) (*GetStrategiesByProductIdsResponse, error) { type GetStrategiesByProductIdsResult struct {
// Product information
ProductsInfo []GetStrategiesByProductIdsResultProductInfo `json:"products_info"`
}
type GetStrategiesByProductIdsResultProductInfo struct {
// Product identifier
ProductId int64 `json:"product_id"`
// Strategy identifier to which the product is bounded
StrategyId string `json:"strategy_id"`
}
func (c Strategies) GetByProductIds(ctx context.Context, params *GetStrategiesByProductIdsParams) (*GetStrategiesByProductIdsResponse, error) {
url := "/v1/pricing-strategy/strategy-ids-by-product-ids" url := "/v1/pricing-strategy/strategy-ids-by-product-ids"
resp := &GetStrategiesByProductIdsResponse{} resp := &GetStrategiesByProductIdsResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -247,23 +315,28 @@ func (c Strategies) GetByProductIds(params *GetStrategiesByProductIdsParams) (*G
} }
type ListProductsInStrategyParams struct { type ListProductsInStrategyParams struct {
// Strategy identifier
StrategyId string `json:"strategy_id"` StrategyId string `json:"strategy_id"`
} }
type ListProductsInStrategyResponse struct { type ListProductsInStrategyResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
ProductId []string `json:"product_id"` Result ListProductsInStrategyResult `json:"result"`
} `json:"result"`
} }
func (c Strategies) ListProducts(params *ListProductsInStrategyParams) (*ListProductsInStrategyResponse, error) { type ListProductsInStrategyResult struct {
// Product identifier
ProductId []string `json:"product_id"`
}
func (c Strategies) ListProducts(ctx context.Context, params *ListProductsInStrategyParams) (*ListProductsInStrategyResponse, error) {
url := "/v1/pricing-strategy/products/list" url := "/v1/pricing-strategy/products/list"
resp := &ListProductsInStrategyResponse{} resp := &ListProductsInStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -273,33 +346,43 @@ func (c Strategies) ListProducts(params *ListProductsInStrategyParams) (*ListPro
} }
type GetCompetitorPriceParams struct { type GetCompetitorPriceParams struct {
// Product identifier
ProductId int64 `json:"product_id"` ProductId int64 `json:"product_id"`
} }
type GetCompetitorPriceResponse struct { type GetCompetitorPriceResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
StrategyId string `json:"strategy_id"` Result GetCompetitorPriceResult `json:"result"`
IsEnabled bool `json:"is_enabled"`
StrategyProductPrice int32 `json:"strategy_product_price"`
PriceDownloadedAt string `json:"price_downloaded_at"`
StrategyCompetitorId int64 `json:"strategy_competitor_id"`
StrategyCompetitorProductURL string `json:"strategy_competitor_product_url"`
} `json:"result"`
} }
func (c Strategies) GetCompetitorPrice(params *GetCompetitorPriceParams) (*GetCompetitorPriceResponse, error) { type GetCompetitorPriceResult struct {
// Product identifier
StrategyId string `json:"strategy_id"`
// true if the product is in the pricing strategy
IsEnabled bool `json:"is_enabled"`
// Price of product in the strategy
StrategyProductPrice int32 `json:"strategy_product_price"`
// Price setting date
PriceDownloadedAt string `json:"price_downloaded_at"`
// Competitor identifier
StrategyCompetitorId int64 `json:"strategy_competitor_id"`
// Link to a competitor's product
StrategyCompetitorProductURL string `json:"strategy_competitor_product_url"`
}
func (c Strategies) GetCompetitorPrice(ctx context.Context, params *GetCompetitorPriceParams) (*GetCompetitorPriceResponse, error) {
url := "/v1/pricing-strategy/product/info" url := "/v1/pricing-strategy/product/info"
resp := &GetCompetitorPriceResponse{} resp := &GetCompetitorPriceResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -309,23 +392,28 @@ func (c Strategies) GetCompetitorPrice(params *GetCompetitorPriceParams) (*GetCo
} }
type RemoveProductsFromStrategyParams struct { type RemoveProductsFromStrategyParams struct {
// List of product identifiers. The maximum number is 50
ProductId []int64 `json:"product_id"` ProductId []int64 `json:"product_id"`
} }
type RemoveProductsFromStrategyResponse struct { type RemoveProductsFromStrategyResponse struct {
core.CommonResponse core.CommonResponse
Result struct { // Method result
FailedProductCount int32 `json:"failed_product_count"` Result RemoveProductsFromStrategyResult `json:"result"`
} `json:"result"`
} }
func (c Strategies) RemoveProducts(params *RemoveProductsFromStrategyParams) (*RemoveProductsFromStrategyResponse, error) { type RemoveProductsFromStrategyResult struct {
// Number of products with errors
FailedProductCount int32 `json:"failed_product_count"`
}
func (c Strategies) RemoveProducts(ctx context.Context, params *RemoveProductsFromStrategyParams) (*RemoveProductsFromStrategyResponse, error) {
url := "/v1/pricing-strategy/products/delete" url := "/v1/pricing-strategy/products/delete"
resp := &RemoveProductsFromStrategyResponse{} resp := &RemoveProductsFromStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -335,8 +423,10 @@ func (c Strategies) RemoveProducts(params *RemoveProductsFromStrategyParams) (*R
} }
type ChangeStrategyStatusParams struct { type ChangeStrategyStatusParams struct {
// Strategy status
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
// Product identifier
StrategyId string `json:"strategy_id"` StrategyId string `json:"strategy_id"`
} }
@@ -344,12 +434,12 @@ type ChangeStrategyStatusResponse struct {
core.CommonResponse core.CommonResponse
} }
func (c Strategies) ChangeStatus(params *ChangeStrategyStatusParams) (*ChangeStrategyStatusResponse, error) { func (c Strategies) ChangeStatus(ctx context.Context, params *ChangeStrategyStatusParams) (*ChangeStrategyStatusResponse, error) {
url := "/v1/pricing-strategy/status" url := "/v1/pricing-strategy/status"
resp := &ChangeStrategyStatusResponse{} resp := &ChangeStrategyStatusResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -359,6 +449,7 @@ func (c Strategies) ChangeStatus(params *ChangeStrategyStatusParams) (*ChangeStr
} }
type RemoveStrategyParams struct { type RemoveStrategyParams struct {
// Strategy identifier
StrategyId string `json:"strategy_id"` StrategyId string `json:"strategy_id"`
} }
@@ -366,12 +457,12 @@ type RemoveStrategyResponse struct {
core.CommonResponse core.CommonResponse
} }
func (c Strategies) Remove(params *RemoveStrategyParams) (*RemoveStrategyResponse, error) { func (c Strategies) Remove(ctx context.Context, params *RemoveStrategyParams) (*RemoveStrategyResponse, error) {
url := "/v1/pricing-strategy/delete" url := "/v1/pricing-strategy/delete"
resp := &RemoveStrategyResponse{} resp := &RemoveStrategyResponse{}
response, err := c.client.Request(http.MethodPost, url, params, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -49,7 +50,8 @@ func TestListCompetitors(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().ListCompetitors(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().ListCompetitors(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -108,7 +110,8 @@ func TestListStrategies(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().List(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().List(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -174,7 +177,8 @@ func TestCreateStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().Create(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().Create(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -235,7 +239,8 @@ func TestInfoStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().Info(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().Info(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -302,7 +307,8 @@ func TestUpdateStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().Update(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().Update(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -351,7 +357,8 @@ func TestAddProductsToStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().AddProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().AddProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -404,7 +411,8 @@ func TestGetStrategiesByProductIds(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().GetByProductIds(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().GetByProductIds(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -466,7 +474,8 @@ func TestListProductsInStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().ListProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().ListProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -519,7 +528,8 @@ func TestGetCompetitorPrice(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().GetCompetitorPrice(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().GetCompetitorPrice(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -567,7 +577,8 @@ func TestRemoveProductsFromStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().RemoveProducts(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().RemoveProducts(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -612,7 +623,8 @@ func TestChangeStrategyStatus(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().ChangeStatus(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().ChangeStatus(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -656,7 +668,8 @@ func TestRemoveStrategy(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Strategies().Remove(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Strategies().Remove(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"time" "time"
@@ -14,7 +15,10 @@ type Warehouses struct {
type GetListOfWarehousesResponse struct { type GetListOfWarehousesResponse struct {
core.CommonResponse core.CommonResponse
Result []struct { Result []GetListOfWarehousesResult `json:"result"`
}
type GetListOfWarehousesResult struct {
// Trusted acceptance attribute. `true` if trusted acceptance is enabled in the warehouse // Trusted acceptance attribute. `true` if trusted acceptance is enabled in the warehouse
HasEntrustedAcceptance bool `json:"has_entrusted_acceptance"` HasEntrustedAcceptance bool `json:"has_entrusted_acceptance"`
@@ -33,23 +37,7 @@ type GetListOfWarehousesResponse struct {
CanPrintActInAdvance bool `json:"can_print_act_in_advance"` CanPrintActInAdvance bool `json:"can_print_act_in_advance"`
// FBS first mile // FBS first mile
FirstMileType struct { FirstMileType GetListOfWarehousesResultFirstMile `json:"first_mile_type"`
// DropOff point identifier
DropoffPointId string `json:"dropoff_point_id"`
// DropOff timeslot identifier
DropoffTimeslotId int64 `json:"dropoff_timeslot_id"`
// Indication that the warehouse settings are being updated
FirstMileIsChanging bool `json:"first_mile_is_changing"`
// First mile type:
//
// Enum: "DropOff" "Pickup"
// - DropOff
// - Pickup
FirstMileType string `json:"first_mile_type"`
} `json:"first_mile_type"`
// Indication if there is a limit on the minimum number of orders. `true` if there is such a limit // Indication if there is a limit on the minimum number of orders. `true` if there is such a limit
HasPostingsLimit bool `json:"has_postings_limit"` HasPostingsLimit bool `json:"has_postings_limit"`
@@ -77,16 +65,33 @@ type GetListOfWarehousesResponse struct {
// Warehouse working days // Warehouse working days
WorkingDays []WorkingDay `json:"working_days"` WorkingDays []WorkingDay `json:"working_days"`
} `json:"resulCommonResponse"` }
type GetListOfWarehousesResultFirstMile struct {
// DropOff point identifier
DropoffPointId string `json:"dropoff_point_id"`
// DropOff timeslot identifier
DropoffTimeslotId int64 `json:"dropoff_timeslot_id"`
// Indication that the warehouse settings are being updated
FirstMileIsChanging bool `json:"first_mile_is_changing"`
// First mile type:
//
// Enum: "DropOff" "Pickup"
// - DropOff
// - Pickup
FirstMileType string `json:"first_mile_type"`
} }
// You do not need to specify any parameters in the request. Your company will be identified by the Warehouses ID // You do not need to specify any parameters in the request. Your company will be identified by the Warehouses ID
func (c Warehouses) GetListOfWarehouses() (*GetListOfWarehousesResponse, error) { func (c Warehouses) GetListOfWarehouses(ctx context.Context) (*GetListOfWarehousesResponse, error) {
url := "/v1/warehouse/list" url := "/v1/warehouse/list"
resp := &GetListOfWarehousesResponse{} resp := &GetListOfWarehousesResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -131,7 +136,10 @@ type GetListOfDeliveryMethodsResponse struct {
HasNext bool `json:"has_next"` HasNext bool `json:"has_next"`
// Method result // Method result
Result []struct { Result []GetListOfDeliveryMethodsResult `json:"result"`
}
type GetListOfDeliveryMethodsResult struct {
// Company identifier // Company identifier
CompanyId int64 `json:"company_id"` CompanyId int64 `json:"company_id"`
@@ -165,16 +173,15 @@ type GetListOfDeliveryMethodsResponse struct {
// Warehouse identifier // Warehouse identifier
WarehouseId int64 `json:"warehouse_id"` WarehouseId int64 `json:"warehouse_id"`
} `json:"result"`
} }
// This methods allows you to get list of all delivery methods that can be applied for this warehouse // This methods allows you to get list of all delivery methods that can be applied for this warehouse
func (c Warehouses) GetListOfDeliveryMethods(params *GetListOfDeliveryMethodsParams) (*GetListOfDeliveryMethodsResponse, error) { func (c Warehouses) GetListOfDeliveryMethods(ctx context.Context, params *GetListOfDeliveryMethodsParams) (*GetListOfDeliveryMethodsResponse, error) {
url := "/v1/delivery-method/list" url := "/v1/delivery-method/list"
resp := &GetListOfDeliveryMethodsResponse{} resp := &GetListOfDeliveryMethodsResponse{}
response, err := c.client.Request(http.MethodPost, url, nil, resp, nil) response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,7 @@
package ozon package ozon
import ( import (
"context"
"net/http" "net/http"
"testing" "testing"
@@ -58,7 +59,8 @@ func TestGetListOfWarehouses(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Warehouses().GetListOfWarehouses() ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Warehouses().GetListOfWarehouses(ctx)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -133,7 +135,8 @@ func TestGetListOfDeliveryMethods(t *testing.T) {
for _, test := range tests { for _, test := range tests {
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers)) c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
resp, err := c.Warehouses().GetListOfDeliveryMethods(test.params) ctx, _ := context.WithTimeout(context.Background(), testTimeout)
resp, err := c.Warehouses().GetListOfDeliveryMethods(ctx, test.params)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }