Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89aeba12d4 | |||
| 1e2c591a70 | |||
| 3e6c8fbc05 | |||
| c6c3030925 | |||
| c9ca89e364 | |||
| dcff4ba1e3 | |||
|
|
25e5e568b5 | ||
|
|
a9d7a5c6d3 | ||
|
|
bac3c04f59 | ||
|
|
851e7a2819 | ||
|
|
94119c0f39 | ||
|
|
1c42f6b3a6 | ||
|
|
dc69b67f0f | ||
|
|
bd280b54f4 |
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
A Ozon Seller API client written in Golang
|
A Ozon Seller API client written in Golang
|
||||||
|
|
||||||
[](https://coveralls.io/github/diPhantxm/ozon-api-client)
|
[](https://coveralls.io/github/diPhantxm/ozon-api-client)
|
||||||

|

|
||||||
|
|
||||||
[Ozon](https://ozon.ru) is a marketplace for small and medium enterprises to launch and grow their businesses in Russia.
|
[Ozon](https://ozon.ru) is a marketplace for small and medium enterprises to launch and grow their businesses in Russia.
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ Get Client-Id and Api-Key in your seller profile [here](https://seller.ozon.ru/a
|
|||||||
|
|
||||||
Just add dependency to your project and you're ready to go.
|
Just add dependency to your project and you're ready to go.
|
||||||
```bash
|
```bash
|
||||||
go get github.com/diphantxm/ozon-api-client
|
go get git.denco.store/fakz9/ozon-api-client
|
||||||
```
|
```
|
||||||
A simple example on how to use this library:
|
A simple example on how to use this library:
|
||||||
```Golang
|
```Golang
|
||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/diphantxm/ozon-api-client/ozon"
|
"git.denco.store/fakz9/ozon-api-client/ozon"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -65,7 +65,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/diphantxm/ozon-api-client/ozon/notifications"
|
"git.denco.store/fakz9/ozon-api-client/ozon/notifications"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,4 +1,4 @@
|
|||||||
module github.com/diphantxm/ozon-api-client
|
module git.denco.store/fakz9/ozon-api-client
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Analytics struct {
|
type Analytics struct {
|
||||||
@@ -200,12 +200,9 @@ type GetStocksOnWarehousesResultRow 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"`
|
||||||
|
|
||||||
// Number of days the stock will last based on your average daily sales
|
|
||||||
IDC float64 `json:"idc"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report on stocks and products movement at Ozon warehouses
|
// Method for getting a report on leftover stocks and products movement at Ozon warehouses
|
||||||
func (c Analytics) GetStocksOnWarehouses(ctx context.Context, 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"
|
||||||
|
|
||||||
@@ -340,3 +337,114 @@ func (c Analytics) Stock(ctx context.Context, params *GetStockManagementParams)
|
|||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetProductQueriesParams struct {
|
||||||
|
// Date when analytics generation starts
|
||||||
|
DateFrom string `json:"date_from"`
|
||||||
|
|
||||||
|
//Date when analytics generation ends
|
||||||
|
DateTo string `json:"date_to"`
|
||||||
|
|
||||||
|
// Number of page returned in the request
|
||||||
|
Page int32 `json:"page"`
|
||||||
|
|
||||||
|
// Number of items on the pag
|
||||||
|
PageSize int32 `json:"page_size"`
|
||||||
|
|
||||||
|
// List of SKUs—product identifiers in the Ozon system.
|
||||||
|
// Analytics on requests is returned for them.
|
||||||
|
// Maximum value is 1,000 SKUs
|
||||||
|
SKUs []string `json:"skus"`
|
||||||
|
|
||||||
|
// Parameter by which products are sorted
|
||||||
|
SortBy string `json:"sort_by"`
|
||||||
|
|
||||||
|
// Sorting direction
|
||||||
|
SortDir string `json:"sort_dir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProductQueriesResponse struct {
|
||||||
|
core.CommonResponse
|
||||||
|
|
||||||
|
// Period for which the analytics is generated
|
||||||
|
AnalyticsPeriod AnalyticsPeriod `json:"analytics_period"`
|
||||||
|
|
||||||
|
// Product list
|
||||||
|
Items []GetProductQueriesItem `json:"items"`
|
||||||
|
|
||||||
|
// Number of pages
|
||||||
|
PageCount int64 `json:"page_count"`
|
||||||
|
|
||||||
|
// Total number of queries
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnalyticsPeriod struct {
|
||||||
|
// Date when analytics generation starts
|
||||||
|
DateFrom string `json:"date_from"`
|
||||||
|
|
||||||
|
// Date when analytics generation ends
|
||||||
|
DateTo string `json:"date_to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProductQueriesItem struct {
|
||||||
|
// Category name
|
||||||
|
Category string `json:"category"`
|
||||||
|
|
||||||
|
// Currency
|
||||||
|
Currency string `json:"currency"`
|
||||||
|
|
||||||
|
// Sales by queries
|
||||||
|
GMV float64 `json:"gmv"`
|
||||||
|
|
||||||
|
// Product name
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Product identifier in the seller's system
|
||||||
|
OfferId string `json:"offer_id"`
|
||||||
|
|
||||||
|
// Average product position. Available only with the Premium or Premium Plus subscription, otherwise the field returns empty
|
||||||
|
Position float64 `json:"position"`
|
||||||
|
|
||||||
|
// Product identifier in the Ozon system, SKU
|
||||||
|
SKU int64 `json:"sku"`
|
||||||
|
|
||||||
|
// Number of customers who searched for your product on Ozon
|
||||||
|
UniqueSearchUsers int64 `json:"unique_search_users"`
|
||||||
|
|
||||||
|
// Number of customers who have seen your product on Ozon.
|
||||||
|
// Available only with the Premium or Premium Plus subscription,
|
||||||
|
// otherwise the field returns empty
|
||||||
|
UniqueViewUsers int64 `json:"unique_view_users"`
|
||||||
|
|
||||||
|
// Conversion from product views.
|
||||||
|
// Available only with the Premium or Premium Plus subscription,
|
||||||
|
// otherwise the field returns empty
|
||||||
|
ViewConversion float64 `json:"view_conversion"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the method to get data about your product queries.
|
||||||
|
// Full analytics is available with the Premium and Premium Plus subscription.
|
||||||
|
// Without subscription, you can see a part of the metrics.
|
||||||
|
// The method is similar to the Products in Search → Queries for my product tab in your personal account.
|
||||||
|
//
|
||||||
|
// You can view analytics by queries for certain dates.
|
||||||
|
// To do this, specify the interval in the date_from and date_to fields.
|
||||||
|
// Data for the last month are available in any interval except for
|
||||||
|
// three days from the current date because these days the calculation is performed.
|
||||||
|
// Analytics for dates later than a month ago is available only with
|
||||||
|
// the Premium and Premium Plus subscription, and only by weeks.
|
||||||
|
// Specify the date_from parameter in the request
|
||||||
|
func (c Analytics) GetProductQueries(ctx context.Context, params *GetProductQueriesParams) (*GetProductQueriesResponse, error) {
|
||||||
|
url := "/v1/analytics/product-queries"
|
||||||
|
|
||||||
|
resp := &GetProductQueriesResponse{}
|
||||||
|
|
||||||
|
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
response.CopyCommonResponse(&resp.CommonResponse)
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetAnalyticsData(t *testing.T) {
|
func TestGetAnalyticsData(t *testing.T) {
|
||||||
@@ -277,3 +277,74 @@ func TestGetStock(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetProductQueries(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
statusCode int
|
||||||
|
headers map[string]string
|
||||||
|
params *GetProductQueriesParams
|
||||||
|
response string
|
||||||
|
}{
|
||||||
|
// Test Ok
|
||||||
|
{
|
||||||
|
http.StatusOK,
|
||||||
|
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
||||||
|
&GetProductQueriesParams{
|
||||||
|
Page: 1,
|
||||||
|
PageSize: 10,
|
||||||
|
SKUs: []string{"string"},
|
||||||
|
},
|
||||||
|
`{
|
||||||
|
"analytics_period": {
|
||||||
|
"date_from": "string",
|
||||||
|
"date_to": "string"
|
||||||
|
},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"category": "string",
|
||||||
|
"currency": "string",
|
||||||
|
"gmv": 0,
|
||||||
|
"name": "string",
|
||||||
|
"offer_id": "string",
|
||||||
|
"position": 0,
|
||||||
|
"sku": 0,
|
||||||
|
"unique_search_users": 0,
|
||||||
|
"unique_view_users": 0,
|
||||||
|
"view_conversion": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"page_count": 0,
|
||||||
|
"total": 0
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
// Test No Client-Id or Api-Key
|
||||||
|
{
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
map[string]string{},
|
||||||
|
&GetProductQueriesParams{},
|
||||||
|
`{
|
||||||
|
"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.Analytics().GetProductQueries(ctx, test.params)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
compareJsonResponse(t, test.response, &GetProductQueriesResponse{})
|
||||||
|
|
||||||
|
if resp.StatusCode != test.statusCode {
|
||||||
|
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Barcodes struct {
|
type Barcodes struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenerateBarcodes(t *testing.T) {
|
func TestGenerateBarcodes(t *testing.T) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Brands struct {
|
type Brands struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListCertifiedBrands(t *testing.T) {
|
func TestListCertifiedBrands(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cancellations struct {
|
type Cancellations struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetCancellationInfo(t *testing.T) {
|
func TestGetCancellationInfo(t *testing.T) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Categories struct {
|
type Categories struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetProductTree(t *testing.T) {
|
func TestGetProductTree(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Certificates struct {
|
type Certificates struct {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListOfAccordanceTypes(t *testing.T) {
|
func TestListOfAccordanceTypes(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Chats struct {
|
type Chats struct {
|
||||||
@@ -164,6 +164,8 @@ type ChatHistoryParams struct {
|
|||||||
// The default value is `Backward`. You can set the number of messages in the limit parameter
|
// The default value is `Backward`. You can set the number of messages in the limit parameter
|
||||||
Direction string `json:"direction" default:"Backward"`
|
Direction string `json:"direction" default:"Backward"`
|
||||||
|
|
||||||
|
Filter *ChatHistoryFilter `json:"filter,omitempty"`
|
||||||
|
|
||||||
// Identifier of the message from which the chat history will be displayed.
|
// Identifier of the message from which the chat history will be displayed.
|
||||||
// Default value is the last visible message
|
// Default value is the last visible message
|
||||||
FromMessageId string `json:"from_message_id"`
|
FromMessageId string `json:"from_message_id"`
|
||||||
@@ -172,6 +174,10 @@ type ChatHistoryParams struct {
|
|||||||
Limit int64 `json:"limit" default:"50"`
|
Limit int64 `json:"limit" default:"50"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChatHistoryFilter struct {
|
||||||
|
MessageIds []string `json:"message_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
type ChatHistoryResponse struct {
|
type ChatHistoryResponse struct {
|
||||||
core.CommonResponse
|
core.CommonResponse
|
||||||
|
|
||||||
@@ -183,22 +189,33 @@ type ChatHistoryResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ChatHistoryMessage struct {
|
type ChatHistoryMessage struct {
|
||||||
|
Context *ChatHistoryContext `json:"context,omitempty"`
|
||||||
|
|
||||||
// Message creation date
|
// Message creation date
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
// Array with message content in Markdown format
|
// Array with message content in Markdown format
|
||||||
Data []string `json:"data"`
|
Data []string `json:"data"`
|
||||||
|
|
||||||
|
IsImage bool `json:"is_image"`
|
||||||
|
|
||||||
// Indication of the read message
|
// Indication of the read message
|
||||||
IsRead bool `json:"is_read"`
|
IsRead bool `json:"is_read"`
|
||||||
|
|
||||||
// Message identifier
|
// Message identifier
|
||||||
MessageId string `json:"message_id"`
|
MessageId string `json:"message_id"`
|
||||||
|
|
||||||
|
ModarateImageStatus string `json:"moderate_image_status"`
|
||||||
|
|
||||||
// Chat participant identifier
|
// Chat participant identifier
|
||||||
User ChatHistoryMessageUser `json:"user"`
|
User ChatHistoryMessageUser `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChatHistoryContext struct {
|
||||||
|
OrderNumber string `json:"order_number"`
|
||||||
|
SKU string `json:"sku"`
|
||||||
|
}
|
||||||
|
|
||||||
type ChatHistoryMessageUser struct {
|
type ChatHistoryMessageUser struct {
|
||||||
// Chat participant identifier
|
// Chat participant identifier
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
@@ -214,7 +231,7 @@ type ChatHistoryMessageUser struct {
|
|||||||
|
|
||||||
// Returns the history of chat messages. By default messages are shown from newest to oldest.
|
// Returns the history of chat messages. By default messages are shown from newest to oldest.
|
||||||
func (c Chats) History(ctx context.Context, params *ChatHistoryParams) (*ChatHistoryResponse, error) {
|
func (c Chats) History(ctx context.Context, params *ChatHistoryParams) (*ChatHistoryResponse, error) {
|
||||||
url := "/v2/chat/history"
|
url := "/v3/chat/history"
|
||||||
|
|
||||||
resp := &ChatHistoryResponse{}
|
resp := &ChatHistoryResponse{}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListChats(t *testing.T) {
|
func TestListChats(t *testing.T) {
|
||||||
@@ -212,16 +212,22 @@ func TestChatHistory(t *testing.T) {
|
|||||||
"has_next": true,
|
"has_next": true,
|
||||||
"messages": [
|
"messages": [
|
||||||
{
|
{
|
||||||
|
"context": {
|
||||||
|
"order_number": "123456789",
|
||||||
|
"sku": "987654321"
|
||||||
|
},
|
||||||
|
"created_at": "2019-08-24T14:15:22Z",
|
||||||
|
"data": [
|
||||||
|
"Здравствуйте, у меня вопрос по вашему товару \"Стекло защитное для смартфонов\", артикул 11223. Подойдет ли он на данную [ модель ](https://www.ozon.ru/product/smartfon-samsung-galaxy-a03s-4-64-gb-chernyy) телефона?"
|
||||||
|
],
|
||||||
|
"is_image": true,
|
||||||
|
"is_read": true,
|
||||||
"message_id": "3000000000817031942",
|
"message_id": "3000000000817031942",
|
||||||
|
"moderate_image_status": "SUCCESS",
|
||||||
"user": {
|
"user": {
|
||||||
"id": "115568",
|
"id": "115568",
|
||||||
"type": "Сustomer"
|
"type": "Сustomer"
|
||||||
},
|
}
|
||||||
"created_at": "2022-07-18T20:58:04.528Z",
|
|
||||||
"is_read": true,
|
|
||||||
"data": [
|
|
||||||
"Здравствуйте, у меня вопрос по вашему товару \"Стекло защитное для смартфонов\", артикул 11223. Подойдет ли он на данную [ модель ](https://www.ozon.ru/product/smartfon-samsung-galaxy-a03s-4-64-gb-chernyy) телефона?"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`,
|
}`,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Clusters struct {
|
type Clusters struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListClusters(t *testing.T) {
|
func TestListClusters(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FBO struct {
|
type FBO struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetFBOShipmentsList(t *testing.T) {
|
func TestGetFBOShipmentsList(t *testing.T) {
|
||||||
|
|||||||
294
ozon/fbs.go
294
ozon/fbs.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FBS struct {
|
type FBS struct {
|
||||||
@@ -195,6 +195,14 @@ type FBSPosting struct {
|
|||||||
|
|
||||||
// Economy product identifier
|
// Economy product identifier
|
||||||
QuantumId int64 `json:"quantum_id"`
|
QuantumId int64 `json:"quantum_id"`
|
||||||
|
|
||||||
|
// List of products with additional characteristics
|
||||||
|
Optional FBSPostingOptional `json:"optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FBSPostingOptional struct {
|
||||||
|
// List of products with optional labeling
|
||||||
|
ProductsWithPossibleMandatoryMark []int `json:"products_with_possible_mandatory_mark"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FBSPostingTariffication struct {
|
type FBSPostingTariffication struct {
|
||||||
@@ -240,7 +248,7 @@ type FBSPostingAddressee struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FBSPostingAnalyticsData struct {
|
type FBSPostingAnalyticsData struct {
|
||||||
// Delivery city. Only for rFBS shipments
|
// Delivery city. Only for rFBS shipments and sellers from CIS countries
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
|
|
||||||
// Delivery start date and time
|
// Delivery start date and time
|
||||||
@@ -373,9 +381,6 @@ type FBSRequirements struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PostingProduct struct {
|
type PostingProduct struct {
|
||||||
// Mandatory product labeling
|
|
||||||
MandatoryMark []string `json:"mandatory_mark"`
|
|
||||||
|
|
||||||
// Product name
|
// Product name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
@@ -393,6 +398,9 @@ type PostingProduct struct {
|
|||||||
|
|
||||||
// Product identifier in the Ozon system, SKU
|
// Product identifier in the Ozon system, SKU
|
||||||
SKU int64 `json:"sku"`
|
SKU int64 `json:"sku"`
|
||||||
|
|
||||||
|
// Product traceability attribute
|
||||||
|
IsBLRTraceable bool `json:"is_blr_traceable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FBSCustomer struct {
|
type FBSCustomer struct {
|
||||||
@@ -769,7 +777,7 @@ type ValidateLabelingCodesExemplar struct {
|
|||||||
GTD string `json:"gtd"`
|
GTD string `json:"gtd"`
|
||||||
|
|
||||||
// Mandatory “Chestny ZNAK” labeling
|
// Mandatory “Chestny ZNAK” labeling
|
||||||
MandatoryMark string `json:"mandatory_mark"`
|
Marks []SetProductItemsDataProductMark `json:"marks"`
|
||||||
|
|
||||||
// Product batch registration number
|
// Product batch registration number
|
||||||
RNPT string `json:"rnpt"`
|
RNPT string `json:"rnpt"`
|
||||||
@@ -778,11 +786,6 @@ type ValidateLabelingCodesExemplar struct {
|
|||||||
type ValidateLabelingCodesResponse struct {
|
type ValidateLabelingCodesResponse struct {
|
||||||
core.CommonResponse
|
core.CommonResponse
|
||||||
|
|
||||||
// Method result
|
|
||||||
Result ValidateLabelingCodesResult `json:"result"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ValidateLabelingCodesResult struct {
|
|
||||||
// Products list
|
// Products list
|
||||||
Products []ValidateLabelingCodesResultProduct `json:"products"`
|
Products []ValidateLabelingCodesResultProduct `json:"products"`
|
||||||
}
|
}
|
||||||
@@ -792,7 +795,7 @@ type ValidateLabelingCodesResultProduct struct {
|
|||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
|
|
||||||
// Product items data
|
// Product items data
|
||||||
Exemplars []FBSProductExemplar `json:"exemplars"`
|
Exemplars []ValidateLabelingCodesResultExemplar `json:"exemplars"`
|
||||||
|
|
||||||
// Product identifier
|
// Product identifier
|
||||||
ProductId int64 `json:"product_id"`
|
ProductId int64 `json:"product_id"`
|
||||||
@@ -801,11 +804,43 @@ type ValidateLabelingCodesResultProduct struct {
|
|||||||
Valid bool `json:"valid"`
|
Valid bool `json:"valid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ValidateLabelingCodesResultExemplar struct {
|
||||||
|
// Product item validation errors
|
||||||
|
Errors []string `json:"errors"`
|
||||||
|
|
||||||
|
// Сustoms cargo declaration (CCD) number
|
||||||
|
GTD string `json:"gtd"`
|
||||||
|
|
||||||
|
// List of Control Identification Marks in one copy
|
||||||
|
Marks []ValidateLabelingCodesMark `json:"marks"`
|
||||||
|
|
||||||
|
// Product batch registration number
|
||||||
|
RNPT string `json:"rnpt"`
|
||||||
|
|
||||||
|
// Check result. true if the labeling codes of all product items meet the requirements
|
||||||
|
Valid bool `json:"valid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValidateLabelingCodesMark struct {
|
||||||
|
// Errors that appeared during verification of Control Identification Marks
|
||||||
|
Errors []string `json:"errors"`
|
||||||
|
|
||||||
|
// Labeling code meaning
|
||||||
|
Mark string `json:"mark"`
|
||||||
|
|
||||||
|
// Labeling code type
|
||||||
|
MarkType string `json:"mark_type"`
|
||||||
|
|
||||||
|
// Check result. true if the labeling
|
||||||
|
// codes of all product items meet the requirements
|
||||||
|
Valid bool `json:"valid"`
|
||||||
|
}
|
||||||
|
|
||||||
// Method for checking whether labeling codes meet the "Chestny ZNAK" system requirements on length and symbols.
|
// Method for checking whether labeling codes meet the "Chestny ZNAK" system requirements on length and symbols.
|
||||||
//
|
//
|
||||||
// If you don't have the customs cargo declaration (CCD) number, you don't have to specify it
|
// If you don't have the customs cargo declaration (CCD) number, you don't have to specify it
|
||||||
func (c FBS) ValidateLabelingCodes(ctx context.Context, params *ValidateLabelingCodesParams) (*ValidateLabelingCodesResponse, error) {
|
func (c FBS) ValidateLabelingCodes(ctx context.Context, params *ValidateLabelingCodesParams) (*ValidateLabelingCodesResponse, error) {
|
||||||
url := "/v4/fbs/posting/product/exemplar/validate"
|
url := "/v5/fbs/posting/product/exemplar/validate"
|
||||||
|
|
||||||
resp := &ValidateLabelingCodesResponse{}
|
resp := &ValidateLabelingCodesResponse{}
|
||||||
|
|
||||||
@@ -1016,6 +1051,9 @@ type GetShipmentDataByIdentifierResult struct {
|
|||||||
// Number of the parent shipment which split resulted in the current shipment
|
// Number of the parent shipment which split resulted in the current shipment
|
||||||
ParentPostingNumber string `json:"parent_posting_number"`
|
ParentPostingNumber string `json:"parent_posting_number"`
|
||||||
|
|
||||||
|
// List of products with additional characteristics
|
||||||
|
Optional GetShipmentDataByIdentifierOptional `json:"optional"`
|
||||||
|
|
||||||
// Shipment number
|
// Shipment number
|
||||||
PostingNumber string `json:"posting_number"`
|
PostingNumber string `json:"posting_number"`
|
||||||
|
|
||||||
@@ -1067,6 +1105,11 @@ type GetShipmentDataByIdentifierResult struct {
|
|||||||
Tariffication []FBSPostingTariffication `json:"tariffication"`
|
Tariffication []FBSPostingTariffication `json:"tariffication"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetShipmentDataByIdentifierOptional struct {
|
||||||
|
// List of products with optional labeling
|
||||||
|
ProductsWithPossibleMandatoryMark []int `json:"products_with_possible_mandatory_mark"`
|
||||||
|
}
|
||||||
|
|
||||||
type GetShipmentDataByIdentifierResultAdditionalData struct {
|
type GetShipmentDataByIdentifierResultAdditionalData struct {
|
||||||
// Key
|
// Key
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
@@ -1086,7 +1129,7 @@ type GetShipmentDataByIdentifierResultAddressee struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetShipmentDataByIdentifierResultAnalyticsData struct {
|
type GetShipmentDataByIdentifierResultAnalyticsData struct {
|
||||||
// Delivery city. Only for rFBS shipments
|
// Delivery city. Only for rFBS shipments and sellers from CIS countries
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
|
|
||||||
// Delivery start date and time
|
// Delivery start date and time
|
||||||
@@ -1194,39 +1237,23 @@ type ProductDimension struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FBSProductExemplar struct {
|
type FBSProductExemplar struct {
|
||||||
// Product item validation errors
|
// Item identifier
|
||||||
Errors []string `json:"errors"`
|
ExemplarId int64 `json:"exemplar_id"`
|
||||||
|
|
||||||
// Mandatory “Chestny ZNAK” labeling
|
// Mandatory “Chestny ZNAK” labeling
|
||||||
MandatoryMark string `json:"mandatory_mark"`
|
MandatoryMark string `json:"mandatory_mark"`
|
||||||
|
|
||||||
// "Chestny ZNAK" labeling check status
|
|
||||||
MandatoryMarkCheckStatus MandatoryMarkStatus `json:"mandatory_mark_check_status"`
|
|
||||||
|
|
||||||
// "Chestny ZNAK" labeling check error codes
|
|
||||||
MandatoryMarkErrorCodes []string `json:"mandatory_mark_error_codes"`
|
|
||||||
|
|
||||||
// Сustoms cargo declaration (CCD) number
|
// Сustoms cargo declaration (CCD) number
|
||||||
GTD string `json:"gtd"`
|
GTD string `json:"gtd"`
|
||||||
|
|
||||||
// Сustoms cargo declaration (CCD) check status
|
|
||||||
GTDCheckStatus string `json:"gtd_check_status"`
|
|
||||||
|
|
||||||
// Indication that a сustoms cargo declaration (CCD) number hasn't been specified
|
// Indication that a сustoms cargo declaration (CCD) number hasn't been specified
|
||||||
IsGTDAbsest bool `json:"is_gtd_absent"`
|
IsGTDAbsest bool `json:"is_gtd_absent"`
|
||||||
|
|
||||||
// Сustoms cargo declaration (CCD) check error codes
|
|
||||||
GTDErrorCodes []string `json:"gtd_error_codes"`
|
|
||||||
|
|
||||||
// Product batch registration number
|
// Product batch registration number
|
||||||
RNPT string `json:"rnpt"`
|
RNPT string `json:"rnpt"`
|
||||||
|
|
||||||
// Indication that a product batch registration number hasn't been specified
|
// Indication that a product batch registration number hasn't been specified
|
||||||
IsRNPTAbsent bool `json:"is_rnpt_absent"`
|
IsRNPTAbsent bool `json:"is_rnpt_absent"`
|
||||||
|
|
||||||
// Check result.
|
|
||||||
// `true` if the labeling code of product item meets the requirements
|
|
||||||
Valid bool `json:"valid"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method for getting shipment details by identifier
|
// Method for getting shipment details by identifier
|
||||||
@@ -1803,7 +1830,7 @@ func (c FBS) GetDropOffPointRestrictions(ctx context.Context, params *GetDropOff
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckProductItemsDataParams struct {
|
type SetProductItemsDataParams struct {
|
||||||
// Quantity of boxes the product is packed in
|
// Quantity of boxes the product is packed in
|
||||||
MultiBoxQuantity int32 `json:"multi_box_qty"`
|
MultiBoxQuantity int32 `json:"multi_box_qty"`
|
||||||
|
|
||||||
@@ -1811,20 +1838,26 @@ type CheckProductItemsDataParams struct {
|
|||||||
PostingNumber string `json:"posting_number"`
|
PostingNumber string `json:"posting_number"`
|
||||||
|
|
||||||
// Product list
|
// Product list
|
||||||
Products []CheckProductItemsDataProduct `json:"products"`
|
Products []SetProductItemsDataProduct `json:"products"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckProductItemsDataProduct struct {
|
type SetProductItemsDataProduct struct {
|
||||||
// Product items data
|
// Product items data
|
||||||
Exemplars []CheckProductItemsDataProductExemplar `json:"exemplars"`
|
Exemplars []SetProductItemsDataProductExemplar `json:"exemplars"`
|
||||||
|
|
||||||
// Indication that you need to pass the сustoms cargo declaration
|
// Indication that you need to pass the сustoms cargo declaration
|
||||||
// (CCD) number for the product and shipment
|
// (CCD) number for the product and shipment
|
||||||
IsGTDNeeded bool `json:"is_gtd_needed"`
|
IsGTDNeeded bool `json:"is_gtd_needed"`
|
||||||
|
|
||||||
|
// Indication that you need to pass the unique identifier of charges of the jewelry
|
||||||
|
IsJwUINNeeded bool `json:"is_jw_uin_needed"`
|
||||||
|
|
||||||
// Indication that you need to pass the "Chestny ZNAK" labeling
|
// Indication that you need to pass the "Chestny ZNAK" labeling
|
||||||
IsMandatoryMarkNeeded bool `json:"is_mandatory_mark_needed"`
|
IsMandatoryMarkNeeded bool `json:"is_mandatory_mark_needed"`
|
||||||
|
|
||||||
|
// Indication that you can pass the "Chestny ZNAK" labeling, but it's not mandatory
|
||||||
|
IsMandatoryMarkPossible bool `json:"is_mandatory_mark_possible"`
|
||||||
|
|
||||||
// Indication that you need to pass the product batch registration number
|
// Indication that you need to pass the product batch registration number
|
||||||
IsRNPTNeeded bool `json:"is_rnpt_needed"`
|
IsRNPTNeeded bool `json:"is_rnpt_needed"`
|
||||||
|
|
||||||
@@ -1835,48 +1868,35 @@ type CheckProductItemsDataProduct struct {
|
|||||||
Quantity int32 `json:"quantity"`
|
Quantity int32 `json:"quantity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckProductItemsDataProductExemplar struct {
|
type SetProductItemsDataProductExemplar struct {
|
||||||
// Item identifier
|
// Item identifier
|
||||||
ExemplarId int64 `json:"exemplar_id"`
|
ExemplarId int64 `json:"exemplar_id"`
|
||||||
|
|
||||||
// Customs cargo declaration (CCD) number
|
// Customs cargo declaration (CCD) number
|
||||||
GTD string `json:"gtd"`
|
GTD string `json:"gtd"`
|
||||||
|
|
||||||
// Сustoms cargo declaration (CCD) check status
|
|
||||||
GTDCheckStatus string `json:"gtd_check_status"`
|
|
||||||
|
|
||||||
// Сustoms cargo declaration (CCD) check error codes
|
|
||||||
GTDErrorCodes []string `json:"gtd_error_codes"`
|
|
||||||
|
|
||||||
// Indication that the customs cargo declaration (CCD) number isn't specified
|
// Indication that the customs cargo declaration (CCD) number isn't specified
|
||||||
IsGTDAbsent bool `json:"is_gtd_absent"`
|
IsGTDAbsent bool `json:"is_gtd_absent"`
|
||||||
|
|
||||||
// "Chestny ZNAK" labeling check status
|
|
||||||
MandatoryMarkCheckStatus MandatoryMarkStatus `json:"mandatory_mark_check_status"`
|
|
||||||
|
|
||||||
// "Chestny ZNAK" labeling check error codes
|
|
||||||
MandatoryMarkErrorCodes []string `json:"mandatory_mark_error_codes"`
|
|
||||||
|
|
||||||
// Indication that the product batch registration number isn't specified
|
// Indication that the product batch registration number isn't specified
|
||||||
IsRNPTAbsent bool `json:"is_rnpt_absent"`
|
IsRNPTAbsent bool `json:"is_rnpt_absent"`
|
||||||
|
|
||||||
// Mandatory "Chestny ZNAK" labeling
|
|
||||||
MandatoryMark string `json:"mandatory_mark"`
|
|
||||||
|
|
||||||
// Product batch registration number
|
// Product batch registration number
|
||||||
RNPT string `json:"rnpt"`
|
RNPT string `json:"rnpt"`
|
||||||
|
|
||||||
// Product batch registration number check status
|
// Errors that appeared during verification of Control Identification Marks
|
||||||
RNPTCheckStatus string `json:"rnpt_check_status"`
|
Marks []SetProductItemsDataProductMark `json:"marks"`
|
||||||
|
|
||||||
// Product batch registration number check error codes
|
|
||||||
RNPTErrorCodes []string `json:"rnpt_error_codes"`
|
|
||||||
|
|
||||||
// Unique identifier of charges of the jewelry
|
|
||||||
JWUIN string `json:"jw_uin"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckProductItemsDataResponse struct {
|
type SetProductItemsDataProductMark struct {
|
||||||
|
// Labeling code meaning
|
||||||
|
Mark string `json:"mark"`
|
||||||
|
|
||||||
|
// Labeling code type
|
||||||
|
MarkType string `json:"mark_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetProductItemsDataResponse struct {
|
||||||
core.CommonResponse
|
core.CommonResponse
|
||||||
|
|
||||||
// Method result. true if the request was processed successfully
|
// Method result. true if the request was processed successfully
|
||||||
@@ -1887,37 +1907,19 @@ type CheckProductItemsDataResponse struct {
|
|||||||
//
|
//
|
||||||
// for checking the availability of product items in the “Chestny ZNAK” labeling system;
|
// for checking the availability of product items in the “Chestny ZNAK” labeling system;
|
||||||
// for saving product items data.
|
// for saving product items data.
|
||||||
|
// To get the checks results, use the /v5/fbs/posting/product/exemplar/status method. To get data about created items, use the /v6/fbs/posting/product/exemplar/create-or-get method.
|
||||||
//
|
//
|
||||||
// To get the checks results,
|
// If you have multiple identical products in a shipment, specify one product_id and exemplars array for each product in the shipment.
|
||||||
// use the /v4/fbs/posting/product/exemplar/status method.
|
|
||||||
// To get data about created items,
|
|
||||||
// use the /v5/fbs/fbs/posting/product/exemplar/create-or-get method.
|
|
||||||
//
|
|
||||||
// If necessary, specify the number of the cargo customs declaration
|
|
||||||
// in the gtd parameter. If it is missing,
|
|
||||||
// pass the value is_gtd_absent = true.
|
|
||||||
//
|
|
||||||
// If you have multiple identical products in a shipment,
|
|
||||||
// specify one product_id and exemplars array for each product in the shipment.
|
|
||||||
//
|
//
|
||||||
// Always pass a complete set of product items data.
|
// Always pass a complete set of product items data.
|
||||||
//
|
//
|
||||||
// For example, you have 10 product items in your system.
|
// For example, you have 10 product items in your system. You pass them for checking and saving. Then you add another 60 product items to your system. When you pass product items for checking and saving again, pass all of them: both old and newly added.
|
||||||
// You've passed them for checking and saving.
|
|
||||||
// Then you added another 60 product items to your system.
|
|
||||||
// When you pass product items for checking and saving again,
|
|
||||||
// pass all of them: both old and newly added.
|
|
||||||
//
|
//
|
||||||
// Unlike /v4/fbs/posting/product/exemplar/set,
|
// The 200 response code doesn't guarantee that instance data has been received. It indicates that a task for adding the information has been created. To check the task status, use the /v5/fbs/posting/product/exemplar/status method.
|
||||||
// you can pass more item information in the request.
|
func (c FBS) SetProductItemsData(ctx context.Context, params *SetProductItemsDataParams) (*SetProductItemsDataResponse, error) {
|
||||||
//
|
url := "/v6/fbs/posting/product/exemplar/set"
|
||||||
// The 200 response code doesn't guarantee that instance data has been received.
|
|
||||||
// It indicates that a task for adding the information has been created.
|
|
||||||
// To check the task status, use the /v4/fbs/posting/product/exemplar/status method.
|
|
||||||
func (c FBS) CheckProductItemsData(ctx context.Context, params *CheckProductItemsDataParams) (*CheckProductItemsDataResponse, error) {
|
|
||||||
url := "/v5/fbs/posting/product/exemplar/set"
|
|
||||||
|
|
||||||
resp := &CheckProductItemsDataResponse{}
|
resp := &SetProductItemsDataResponse{}
|
||||||
|
|
||||||
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1940,19 +1942,71 @@ type GetProductItemsCheckStatusesResponse struct {
|
|||||||
PostingNumber string `json:"posting_number"`
|
PostingNumber string `json:"posting_number"`
|
||||||
|
|
||||||
// Products list
|
// Products list
|
||||||
Products []CheckProductItemsDataProduct `json:"products"`
|
Products []GetProductItemsCheckStatusProduct `json:"products"`
|
||||||
|
|
||||||
// Product items check statuses and order collection availability:
|
// Product items check statuses and order collection availability
|
||||||
// - ship_available — order collection is available,
|
|
||||||
// - ship_not_available — order collection is unavailable,
|
|
||||||
// - validation_in_process — product items validation is in progress
|
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method for getting check statuses of product items that were passed in the `/fbs/posting/product/exemplar/set` method.
|
type GetProductItemsCheckStatusProduct struct {
|
||||||
|
// Product identifier
|
||||||
|
ProductId int64 `json:"product_id"`
|
||||||
|
|
||||||
|
// Product items data
|
||||||
|
Exemplars []GetProductItemsCheckStatusExemplar `json:"exemplars"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProductItemsCheckStatusExemplar struct {
|
||||||
|
// Item identifier
|
||||||
|
ExemplarId int64 `json:"exemplar_id"`
|
||||||
|
|
||||||
|
// Customs cargo declaration (CCD) number
|
||||||
|
GTD string `json:"gtd"`
|
||||||
|
|
||||||
|
// Сustoms cargo declaration (CCD) check status
|
||||||
|
GTDCheckStatus string `json:"gtd_check_status"`
|
||||||
|
|
||||||
|
// Сustoms cargo declaration (CCD) check error codes
|
||||||
|
GTDErrorCodes []string `json:"gtd_error_codes"`
|
||||||
|
|
||||||
|
// Indication that the customs cargo declaration (CCD) number isn't specified
|
||||||
|
IsGTDAbsent bool `json:"is_gtd_absent"`
|
||||||
|
|
||||||
|
// Indication that the product batch registration number isn't specified
|
||||||
|
IsRNPTAbsent bool `json:"is_rnpt_absent"`
|
||||||
|
|
||||||
|
// List of Control Identification Marks in one copy
|
||||||
|
Marks []GetProductItemsCheckStatusMark `json:"marks"`
|
||||||
|
|
||||||
|
// Product batch registration number
|
||||||
|
RNPT string `json:"rnpt"`
|
||||||
|
|
||||||
|
// Product batch registration number check status
|
||||||
|
RNPTCheckStatus string `json:"rnpt_check_status"`
|
||||||
|
|
||||||
|
// Product batch registration number check error codes
|
||||||
|
RNPTErrorCodes []string `json:"rnpt_error_codes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProductItemsCheckStatusMark struct {
|
||||||
|
// Check status
|
||||||
|
CheckStatus string `json:"check_status"`
|
||||||
|
|
||||||
|
// Errors that appeared during verification of Control Identification Marks
|
||||||
|
ErrorCodes []string `json:"error_codes"`
|
||||||
|
|
||||||
|
// Labeling code meaning
|
||||||
|
Mark string `json:"mark"`
|
||||||
|
|
||||||
|
// Labeling code type
|
||||||
|
MarkType string `json:"mark_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method for getting product items addition statuses
|
||||||
|
// that were passed in the /v6/fbs/posting/product/exemplar/set method.
|
||||||
// Also returns data on these product items.
|
// Also returns data on these product items.
|
||||||
func (c FBS) GetProductItemsCheckStatuses(ctx context.Context, params *GetProductItemsCheckStatusesParams) (*GetProductItemsCheckStatusesResponse, error) {
|
func (c FBS) GetProductItemsCheckStatuses(ctx context.Context, params *GetProductItemsCheckStatusesParams) (*GetProductItemsCheckStatusesResponse, error) {
|
||||||
url := "/v4/fbs/posting/product/exemplar/status"
|
url := "/v5/fbs/posting/product/exemplar/status"
|
||||||
|
|
||||||
resp := &GetProductItemsCheckStatusesResponse{}
|
resp := &GetProductItemsCheckStatusesResponse{}
|
||||||
|
|
||||||
@@ -2938,11 +2992,37 @@ type CreateOrGetProductExemplarResponse struct {
|
|||||||
Products []CheckProductItemsDataProduct `json:"products"`
|
Products []CheckProductItemsDataProduct `json:"products"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CheckProductItemsDataProduct struct {
|
||||||
|
// Data about items
|
||||||
|
Exemplars []SetProductItemsDataProductExemplar `json:"exemplars"`
|
||||||
|
|
||||||
|
// Indication that you need to pass the сustoms cargo declaration (CCD) number for the product and shipment
|
||||||
|
IsGTDNeeded bool `json:"is_gtd_needed"`
|
||||||
|
|
||||||
|
// Indication that you need to pass the unique identifier of charges of the jewelry
|
||||||
|
IsJwUINNeeded bool `json:"is_jw_uin_needed"`
|
||||||
|
|
||||||
|
// Indication that you need to pass the "Chestny ZNAK" labeling
|
||||||
|
IsMandatoryMarkNeeded bool `json:"is_mandatory_mark_needed"`
|
||||||
|
|
||||||
|
// Indication that you can pass the "Chestny ZNAK" labeling, but it's not mandatory
|
||||||
|
IsMandatoryMarkPossible bool `json:"is_mandatory_mark_possible"`
|
||||||
|
|
||||||
|
// Indication that you need to pass the product batch registration number
|
||||||
|
IsRNPTNeeded bool `json:"is_rnpt_needed"`
|
||||||
|
|
||||||
|
// Product ID
|
||||||
|
ProductId int64 `json:"product_id"`
|
||||||
|
|
||||||
|
// Items quantity
|
||||||
|
Quantity int32 `json:"quantity"`
|
||||||
|
}
|
||||||
|
|
||||||
// Method returns the created items data passed in the `/v5/fbs/posting/product/exemplar/set` method.
|
// Method returns the created items data passed in the `/v5/fbs/posting/product/exemplar/set` method.
|
||||||
//
|
//
|
||||||
// Use this method to get the `exemplar_id`
|
// Use this method to get the `exemplar_id`
|
||||||
func (c FBS) CreateOrGetProductExemplar(ctx context.Context, params *CreateOrGetProductExemplarParams) (*CreateOrGetProductExemplarResponse, error) {
|
func (c FBS) CreateOrGetProductExemplar(ctx context.Context, params *CreateOrGetProductExemplarParams) (*CreateOrGetProductExemplarResponse, error) {
|
||||||
url := "/v5/fbs/posting/product/exemplar/create-or-get"
|
url := "/v6/fbs/posting/product/exemplar/create-or-get"
|
||||||
|
|
||||||
resp := &CreateOrGetProductExemplarResponse{}
|
resp := &CreateOrGetProductExemplarResponse{}
|
||||||
|
|
||||||
@@ -3310,3 +3390,29 @@ func (c FBS) VerifyCourierCode(ctx context.Context, params *VerifyCourierCodePar
|
|||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateProductsDataParams struct {
|
||||||
|
// Shipment number
|
||||||
|
PostingNumber string `json:"posting_number"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateProductsDataResponse struct {
|
||||||
|
core.CommonResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the method after passing item data using the
|
||||||
|
// /v6/fbs/posting/product/exemplar/set method to
|
||||||
|
// save updated item data for shipments in the “Awaiting shipment” status
|
||||||
|
func (c FBS) UpdateProductsData(ctx context.Context, params *UpdateProductsDataParams) (*UpdateProductsDataResponse, error) {
|
||||||
|
url := "/v1/fbs/posting/product/exemplar/update"
|
||||||
|
|
||||||
|
resp := &UpdateProductsDataResponse{}
|
||||||
|
|
||||||
|
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
response.CopyCommonResponse(&resp.CommonResponse)
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|||||||
202
ozon/fbs_test.go
202
ozon/fbs_test.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListUnprocessedShipments(t *testing.T) {
|
func TestListUnprocessedShipments(t *testing.T) {
|
||||||
@@ -58,6 +58,11 @@ func TestListUnprocessedShipments(t *testing.T) {
|
|||||||
"in_process_at": "2021-08-25T10:48:38Z",
|
"in_process_at": "2021-08-25T10:48:38Z",
|
||||||
"shipment_date": "2021-08-26T10:00:00Z",
|
"shipment_date": "2021-08-26T10:00:00Z",
|
||||||
"delivering_date": null,
|
"delivering_date": null,
|
||||||
|
"optional": {
|
||||||
|
"products_with_possible_mandatory_mark": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
"cancellation": {
|
"cancellation": {
|
||||||
"cancel_reason_id": 0,
|
"cancel_reason_id": 0,
|
||||||
"cancel_reason": "",
|
"cancel_reason": "",
|
||||||
@@ -71,12 +76,12 @@ func TestListUnprocessedShipments(t *testing.T) {
|
|||||||
"products": [
|
"products": [
|
||||||
{
|
{
|
||||||
"currency_code": "RUB",
|
"currency_code": "RUB",
|
||||||
|
"is_blr_traceable": true,
|
||||||
"price": "1259",
|
"price": "1259",
|
||||||
"offer_id": "УТ-0001365",
|
"offer_id": "УТ-0001365",
|
||||||
"name": "Мяч, цвет: черный, 5 кг",
|
"name": "Мяч, цвет: черный, 5 кг",
|
||||||
"sku": 140048123,
|
"sku": 140048123,
|
||||||
"quantity": 1,
|
"quantity": 1
|
||||||
"mandatory_mark": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addressee": null,
|
"addressee": null,
|
||||||
@@ -255,6 +260,11 @@ func TestGetFBSShipmentsList(t *testing.T) {
|
|||||||
"in_process_at": "2022-05-13T07:07:32Z",
|
"in_process_at": "2022-05-13T07:07:32Z",
|
||||||
"shipment_date": "2022-05-13T10:00:00Z",
|
"shipment_date": "2022-05-13T10:00:00Z",
|
||||||
"delivering_date": null,
|
"delivering_date": null,
|
||||||
|
"optional": {
|
||||||
|
"products_with_possible_mandatory_mark": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
"cancellation": {
|
"cancellation": {
|
||||||
"cancel_reason_id": 0,
|
"cancel_reason_id": 0,
|
||||||
"cancel_reason": "",
|
"cancel_reason": "",
|
||||||
@@ -267,12 +277,12 @@ func TestGetFBSShipmentsList(t *testing.T) {
|
|||||||
"products": [
|
"products": [
|
||||||
{
|
{
|
||||||
"currency_code": "RUB",
|
"currency_code": "RUB",
|
||||||
|
"is_blr_traceable": true,
|
||||||
"price": "1390.000000",
|
"price": "1390.000000",
|
||||||
"offer_id": "205953",
|
"offer_id": "205953",
|
||||||
"name": " Электронный конструктор PinLab Позитроник",
|
"name": " Электронный конструктор PinLab Позитроник",
|
||||||
"sku": 358924380,
|
"sku": 358924380,
|
||||||
"quantity": 1,
|
"quantity": 1
|
||||||
"mandatory_mark": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addressee": null,
|
"addressee": null,
|
||||||
@@ -424,7 +434,6 @@ func TestValidateLabelingCodes(t *testing.T) {
|
|||||||
Exemplars: []ValidateLabelingCodesExemplar{
|
Exemplars: []ValidateLabelingCodesExemplar{
|
||||||
{
|
{
|
||||||
GTD: "",
|
GTD: "",
|
||||||
MandatoryMark: "010290000151642731tVMohkbfFgunB",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ProductId: 476925391,
|
ProductId: 476925391,
|
||||||
@@ -432,23 +441,33 @@ func TestValidateLabelingCodes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
`{
|
`{
|
||||||
"result": {
|
|
||||||
"products": [
|
"products": [
|
||||||
{
|
{
|
||||||
"product_id": 476925391,
|
"error": "string",
|
||||||
"exemplars": [
|
"exemplars": [
|
||||||
{
|
{
|
||||||
"mandatory_mark": "010290000151642731tVMohkbfFgunB",
|
"errors": [
|
||||||
"gtd": "",
|
"string"
|
||||||
"valid": true,
|
],
|
||||||
"errors": []
|
"gtd": "string",
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"errors": [
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"mark": "string",
|
||||||
|
"mark_type": "string",
|
||||||
|
"valid": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"valid": true,
|
"rnpt": "string",
|
||||||
"error": ""
|
"valid": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"product_id": 476925391,
|
||||||
|
"valid": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
// Test No Client-Id or Api-Key
|
// Test No Client-Id or Api-Key
|
||||||
@@ -480,11 +499,11 @@ func TestValidateLabelingCodes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode == http.StatusOK {
|
if resp.StatusCode == http.StatusOK {
|
||||||
if len(resp.Result.Products) != len(test.params.Products) {
|
if len(resp.Products) != len(test.params.Products) {
|
||||||
t.Errorf("Length of products in request and response are not equal")
|
t.Errorf("Length of products in request and response are not equal")
|
||||||
}
|
}
|
||||||
if len(resp.Result.Products) > 0 {
|
if len(resp.Products) > 0 {
|
||||||
if resp.Result.Products[0].ProductId != test.params.Products[0].ProductId {
|
if resp.Products[0].ProductId != test.params.Products[0].ProductId {
|
||||||
t.Errorf("Product ids in request and response are not equal")
|
t.Errorf("Product ids in request and response are not equal")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -522,8 +541,7 @@ func TestGetShipmentDataByBarcode(t *testing.T) {
|
|||||||
"offer_id": "250-7898-1",
|
"offer_id": "250-7898-1",
|
||||||
"name": "Кофе ароматизированный \"Шоколадный апельсин\" 250 гр",
|
"name": "Кофе ароматизированный \"Шоколадный апельсин\" 250 гр",
|
||||||
"sku": 180550365,
|
"sku": 180550365,
|
||||||
"quantity": 1,
|
"quantity": 1
|
||||||
"mandatory_mark": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"barcodes": null,
|
"barcodes": null,
|
||||||
@@ -612,6 +630,11 @@ func TestGetShipmentDataByIdentifier(t *testing.T) {
|
|||||||
"delivering_date": null,
|
"delivering_date": null,
|
||||||
"provider_status": "",
|
"provider_status": "",
|
||||||
"delivery_price": "",
|
"delivery_price": "",
|
||||||
|
"optional": {
|
||||||
|
"products_with_possible_mandatory_mark": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
"cancellation": {
|
"cancellation": {
|
||||||
"cancel_reason_id": 0,
|
"cancel_reason_id": 0,
|
||||||
"cancel_reason": "",
|
"cancel_reason": "",
|
||||||
@@ -625,12 +648,12 @@ func TestGetShipmentDataByIdentifier(t *testing.T) {
|
|||||||
"products": [
|
"products": [
|
||||||
{
|
{
|
||||||
"currency_code": "RUB",
|
"currency_code": "RUB",
|
||||||
|
"is_blr_traceable": true,
|
||||||
"price": "279.0000",
|
"price": "279.0000",
|
||||||
"offer_id": "250-7898-1",
|
"offer_id": "250-7898-1",
|
||||||
"name": "Кофе ароматизированный \"Шоколадный апельсин\" 250 гр",
|
"name": "Кофе ароматизированный \"Шоколадный апельсин\" 250 гр",
|
||||||
"sku": 180550365,
|
"sku": 180550365,
|
||||||
"quantity": 1,
|
"quantity": 1,
|
||||||
"mandatory_mark": [],
|
|
||||||
"dimensions": {
|
"dimensions": {
|
||||||
"height": "40.00",
|
"height": "40.00",
|
||||||
"length": "240.00",
|
"length": "240.00",
|
||||||
@@ -1380,52 +1403,52 @@ func TestGetDropOffPointRestrictions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckProductItemsData(t *testing.T) {
|
func TestSetProductItemsData(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
statusCode int
|
statusCode int
|
||||||
headers map[string]string
|
headers map[string]string
|
||||||
params *CheckProductItemsDataParams
|
params *SetProductItemsDataParams
|
||||||
response string
|
response string
|
||||||
}{
|
}{
|
||||||
// Test Ok
|
// Test Ok
|
||||||
{
|
{
|
||||||
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"},
|
||||||
&CheckProductItemsDataParams{
|
&SetProductItemsDataParams{
|
||||||
MultiBoxQuantity: 0,
|
MultiBoxQuantity: 0,
|
||||||
PostingNumber: "1234",
|
PostingNumber: "1234",
|
||||||
Products: []CheckProductItemsDataProduct{
|
Products: []SetProductItemsDataProduct{
|
||||||
{
|
{
|
||||||
Exemplars: []CheckProductItemsDataProductExemplar{
|
Exemplars: []SetProductItemsDataProductExemplar{
|
||||||
{
|
{
|
||||||
ExemplarId: 1,
|
ExemplarId: 1,
|
||||||
GTD: "string",
|
GTD: "string",
|
||||||
IsGTDAbsent: true,
|
IsGTDAbsent: true,
|
||||||
IsRNPTAbsent: true,
|
|
||||||
MandatoryMark: "string",
|
|
||||||
RNPT: "string",
|
RNPT: "string",
|
||||||
JWUIN: "string",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
IsGTDNeeded: true,
|
|
||||||
IsMandatoryMarkNeeded: true,
|
|
||||||
IsRNPTNeeded: true,
|
|
||||||
ProductId: 22,
|
ProductId: 22,
|
||||||
Quantity: 11,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
`{
|
`{
|
||||||
"result": true
|
"code": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"typeUrl": "string",
|
||||||
|
"value": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"message": "string"
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
// Test No Client-Id or Api-Key
|
// Test No Client-Id or Api-Key
|
||||||
{
|
{
|
||||||
http.StatusUnauthorized,
|
http.StatusUnauthorized,
|
||||||
map[string]string{},
|
map[string]string{},
|
||||||
&CheckProductItemsDataParams{},
|
&SetProductItemsDataParams{},
|
||||||
`{
|
`{
|
||||||
"code": 16,
|
"code": 16,
|
||||||
"message": "Client-Id and Api-Key headers are required"
|
"message": "Client-Id and Api-Key headers are required"
|
||||||
@@ -1437,13 +1460,13 @@ func TestCheckProductItemsData(t *testing.T) {
|
|||||||
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
|
c := NewMockClient(core.NewMockHttpHandler(test.statusCode, test.response, test.headers))
|
||||||
|
|
||||||
ctx, _ := context.WithTimeout(context.Background(), testTimeout)
|
ctx, _ := context.WithTimeout(context.Background(), testTimeout)
|
||||||
resp, err := c.FBS().CheckProductItemsData(ctx, test.params)
|
resp, err := c.FBS().SetProductItemsData(ctx, test.params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
compareJsonResponse(t, test.response, &CheckProductItemsDataResponse{})
|
compareJsonResponse(t, test.response, &SetProductItemsDataResponse{})
|
||||||
|
|
||||||
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)
|
||||||
@@ -1471,21 +1494,37 @@ func TestGetProductItemsCheckStatuses(t *testing.T) {
|
|||||||
"posting_number": "23281294-0063-2",
|
"posting_number": "23281294-0063-2",
|
||||||
"products": [
|
"products": [
|
||||||
{
|
{
|
||||||
"product_id": 476925391,
|
|
||||||
"exemplars": [
|
"exemplars": [
|
||||||
{
|
{
|
||||||
"mandatory_mark": "010290000151642731tVMohkbfFgunB",
|
"exemplar_id": 0,
|
||||||
"gtd": "",
|
"gtd": "string",
|
||||||
|
"gtd_check_status": "string",
|
||||||
|
"gtd_error_codes": [
|
||||||
|
"string"
|
||||||
|
],
|
||||||
"is_gtd_absent": true,
|
"is_gtd_absent": true,
|
||||||
"mandatory_mark_check_status": "passed",
|
"is_rnpt_absent": true,
|
||||||
"mandatory_mark_error_codes": [],
|
"marks": [
|
||||||
"gtd_check_status": "passed",
|
{
|
||||||
"gtd_error_codes": []
|
"check_status": "string",
|
||||||
|
"error_codes": [
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"mark": "string",
|
||||||
|
"mark_type": "string"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"rnpt": "string",
|
||||||
|
"rnpt_check_status": "string",
|
||||||
|
"rnpt_error_codes": [
|
||||||
|
"string"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"status": "ship_available"
|
"product_id": 123
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"status": "string"
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
// Test No Client-Id or Api-Key
|
// Test No Client-Id or Api-Key
|
||||||
@@ -1526,8 +1565,8 @@ func TestGetProductItemsCheckStatuses(t *testing.T) {
|
|||||||
if resp.Products[0].ProductId == 0 {
|
if resp.Products[0].ProductId == 0 {
|
||||||
t.Errorf("Product id cannot be 0")
|
t.Errorf("Product id cannot be 0")
|
||||||
}
|
}
|
||||||
if len(resp.Products[0].Exemplars) > 0 {
|
if len(resp.Products[0].Exemplars) > 0 && len(resp.Products[0].Exemplars[0].Marks) > 0 {
|
||||||
if resp.Products[0].Exemplars[0].MandatoryMark == "" {
|
if resp.Products[0].Exemplars[0].Marks[0].Mark == "" {
|
||||||
t.Errorf("Mandatory mark cannot be empty")
|
t.Errorf("Mandatory mark cannot be empty")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2877,13 +2916,19 @@ func TestCreateOrGetProductExemplar(t *testing.T) {
|
|||||||
"gtd": "string",
|
"gtd": "string",
|
||||||
"is_gtd_absent": true,
|
"is_gtd_absent": true,
|
||||||
"is_rnpt_absent": true,
|
"is_rnpt_absent": true,
|
||||||
"mandatory_mark": "string",
|
"marks": [
|
||||||
"rnpt": "string",
|
{
|
||||||
"jw_uin": "string"
|
"mark": "string",
|
||||||
|
"mark_type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rnpt": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_gtd_needed": true,
|
"is_gtd_needed": true,
|
||||||
|
"is_jw_uin_needed": true,
|
||||||
"is_mandatory_mark_needed": true,
|
"is_mandatory_mark_needed": true,
|
||||||
|
"is_mandatory_mark_possible": true,
|
||||||
"is_rnpt_needed": true,
|
"is_rnpt_needed": true,
|
||||||
"product_id": 0,
|
"product_id": 0,
|
||||||
"quantity": 0
|
"quantity": 0
|
||||||
@@ -3426,3 +3471,60 @@ func TestVerifyCourierCode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdateProductsData(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
statusCode int
|
||||||
|
headers map[string]string
|
||||||
|
params *UpdateProductsDataParams
|
||||||
|
response string
|
||||||
|
}{
|
||||||
|
// Test Ok
|
||||||
|
{
|
||||||
|
http.StatusOK,
|
||||||
|
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
||||||
|
&UpdateProductsDataParams{
|
||||||
|
PostingNumber: "string",
|
||||||
|
},
|
||||||
|
`{
|
||||||
|
"code": 0,
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"typeUrl": "string",
|
||||||
|
"value": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"message": "string"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
// Test No Client-Id or Api-Key
|
||||||
|
{
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
map[string]string{},
|
||||||
|
&UpdateProductsDataParams{},
|
||||||
|
`{
|
||||||
|
"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().UpdateProductsData(ctx, test.params)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
compareJsonResponse(t, test.response, &UpdateProductsDataResponse{})
|
||||||
|
|
||||||
|
if resp.StatusCode != test.statusCode {
|
||||||
|
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Finance struct {
|
type Finance struct {
|
||||||
@@ -362,11 +362,7 @@ type ListTransactionsResultOperationItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListTransactionsResultOperationPosting struct {
|
type ListTransactionsResultOperationPosting struct {
|
||||||
// Delivery scheme:
|
// Delivery scheme
|
||||||
// - FBO — delivery to Ozon warehouse
|
|
||||||
// - FBS — delivery from seller's warehouse
|
|
||||||
// - RFBS — delivery service of seller's choice
|
|
||||||
// - Crossborder — delivery from abroad
|
|
||||||
DeliverySchema string `json:"delivery_schema"`
|
DeliverySchema string `json:"delivery_schema"`
|
||||||
|
|
||||||
// Date the product was accepted for processing
|
// Date the product was accepted for processing
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReportOnSoldProducts(t *testing.T) {
|
func TestReportOnSoldProducts(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Invoices struct {
|
type Invoices struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateUpdateProformaLink(t *testing.T) {
|
func TestCreateUpdateProformaLink(t *testing.T) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testData struct {
|
type testData struct {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package ozon
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Passes struct {
|
type Passes struct {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListPasses(t *testing.T) {
|
func TestListPasses(t *testing.T) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Polygons struct {
|
type Polygons struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateDeliveryPolygon(t *testing.T) {
|
func TestCreateDeliveryPolygon(t *testing.T) {
|
||||||
|
|||||||
285
ozon/products.go
285
ozon/products.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Products struct {
|
type Products struct {
|
||||||
@@ -106,157 +106,41 @@ func (c Products) GetStocksInfo(ctx context.Context, params *GetStocksInfoParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetails struct {
|
type ProductDetails struct {
|
||||||
// All product barcodes
|
|
||||||
Barcodes []string `json:"barcodes"`
|
Barcodes []string `json:"barcodes"`
|
||||||
|
|
||||||
// Main offer price on Ozon.
|
|
||||||
//
|
|
||||||
// The field is deprecated. Returns an empty string ""
|
|
||||||
BuyboxPrice string `json:"buybox_price"`
|
|
||||||
|
|
||||||
// Category identifier
|
|
||||||
DescriptionCategoryId int64 `json:"description_category_id"`
|
|
||||||
|
|
||||||
// Markdown product stocks at the Ozon warehouse
|
|
||||||
DiscountedFBOStocks int32 `json:"discounted_fbo_stocks"`
|
|
||||||
|
|
||||||
// Details on errors when creating or validating a product
|
|
||||||
Errors []ProductDetailsError `json:"errors"`
|
|
||||||
|
|
||||||
// Indication that the product has similar markdown products at the Ozon warehouse
|
|
||||||
HasDiscountedFBOItem bool `json:"has_discounted_fbo_item"`
|
|
||||||
|
|
||||||
// Product type identifier
|
|
||||||
TypeId int64 `json:"type_id"`
|
|
||||||
|
|
||||||
// Marketing color
|
|
||||||
ColorImage []string `json:"color_image"`
|
ColorImage []string `json:"color_image"`
|
||||||
|
|
||||||
// Commission fees details
|
|
||||||
Commissions []ProductDetailCommission `json:"commissions"`
|
Commissions []ProductDetailCommission `json:"commissions"`
|
||||||
|
|
||||||
// Date and time when the product was created
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
// Product SKU
|
|
||||||
SKU int64 `json:"sku"`
|
|
||||||
|
|
||||||
// SKU of the product that is sold from the Ozon warehouse (FBO)
|
|
||||||
FBOSKU int64 `json:"fbo_sku,omitempty"`
|
|
||||||
|
|
||||||
// SKU of the product that is sold from the seller's warehouse (FBS and rFBS)
|
|
||||||
FBSSKU int64 `json:"fbs_sku,omitempty"`
|
|
||||||
|
|
||||||
// Product identifier
|
|
||||||
Id int64 `json:"id"`
|
|
||||||
|
|
||||||
// An array of links to images. The images in the array are arranged in the order of their arrangement on the site. If the `primary_image` parameter is not specified, the first image in the list is the main one for the product
|
|
||||||
Images []string `json:"images"`
|
|
||||||
|
|
||||||
// Main product image
|
|
||||||
PrimaryImage []string `json:"primary_image"`
|
|
||||||
|
|
||||||
// Array of 360 images
|
|
||||||
Images360 []string `json:"images360"`
|
|
||||||
|
|
||||||
// true if the product has markdown equivalents at the Ozon warehouse
|
|
||||||
HasDiscountedItem bool `json:"has_discounted_item"`
|
|
||||||
|
|
||||||
// Indication of a markdown product:
|
|
||||||
//
|
|
||||||
// * true if the product was created by the seller as a markdown
|
|
||||||
//
|
|
||||||
// * false if the product is not markdown or was marked down by Ozon
|
|
||||||
IsDiscounted bool `json:"is_discounted"`
|
|
||||||
|
|
||||||
// Markdown products stocks
|
|
||||||
DiscountedStocks ProductDiscountedStocks `json:"discounted_stocks"`
|
|
||||||
|
|
||||||
// Indication of a bulky product
|
|
||||||
IsKGT bool `json:"is_kgt"`
|
|
||||||
|
|
||||||
// Indication of mandatory prepayment for the product:
|
|
||||||
//
|
|
||||||
// * true — to buy a product, you need to make a prepayment.
|
|
||||||
//
|
|
||||||
// * false—prepayment is not required
|
|
||||||
IsPrepayment bool `json:"is_prepayment"`
|
|
||||||
|
|
||||||
// If prepayment is possible, the value is true
|
|
||||||
IsPrepaymentAllowed bool `json:"is_prepayment_allowed"`
|
|
||||||
|
|
||||||
// Currency of your prices. It matches the currency set in the personal account settings
|
|
||||||
CurrencyCode string `json:"currency_code"`
|
CurrencyCode string `json:"currency_code"`
|
||||||
|
DescriptionCategoryId int64 `json:"description_category_id"`
|
||||||
// The price of the product including all promotion discounts. This value will be shown on the Ozon storefront
|
DiscountedFBOStocks int32 `json:"discounted_fbo_stocks"`
|
||||||
MarketingPrice string `json:"marketing_price"`
|
Errors []ProductDetailsError `json:"errors"`
|
||||||
|
HasDiscountedFBOItem bool `json:"has_discounted_fbo_item"`
|
||||||
// Minimum price for similar products on Ozon.
|
Id int64 `json:"id"`
|
||||||
//
|
Images []string `json:"images"`
|
||||||
// The field is deprecated. Returns an empty string ""
|
Images360 []string `json:"images360"`
|
||||||
MinOzonPrice string `json:"min_ozon_price"`
|
|
||||||
|
|
||||||
// Minimum product price with all promotions applied
|
|
||||||
MinPrice string `json:"min_price"`
|
|
||||||
|
|
||||||
// Name
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Product identifier in the seller's system
|
|
||||||
OfferId string `json:"offer_id"`
|
|
||||||
|
|
||||||
// Price before discounts. Displayed strikethrough on the product description page
|
|
||||||
OldPrice string `json:"old_price"`
|
|
||||||
|
|
||||||
// Product price including discounts. This value is shown on the product description page
|
|
||||||
Price string `json:"price"`
|
|
||||||
|
|
||||||
// Product price indexes
|
|
||||||
PriceIndexes ProductDetailPriceIndex `json:"price_indexes"`
|
|
||||||
|
|
||||||
// Deprecated: Price index. Learn more in Help Center
|
|
||||||
//
|
|
||||||
// Use PriceIndexes instead
|
|
||||||
PriceIndex string `json:"price_index"`
|
|
||||||
|
|
||||||
// Product state description
|
|
||||||
Status ProductDetailStatus `json:"status"`
|
|
||||||
|
|
||||||
// Details about the sources of similar offers. Learn more in Help Сenter
|
|
||||||
Sources []ProductDetailSource `json:"sources"`
|
|
||||||
|
|
||||||
// Details about product stocks
|
|
||||||
Stocks ProductDetailStock `json:"stocks"`
|
|
||||||
|
|
||||||
// Date of the last product update
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
|
|
||||||
// Product VAT rate
|
|
||||||
VAT string `json:"vat"`
|
|
||||||
|
|
||||||
// Product visibility settings
|
|
||||||
VisibilityDetails ProductDetailVisibilityDetails `json:"visibility_details"`
|
|
||||||
|
|
||||||
// If the product is on sale, the value is true
|
|
||||||
Visible bool `json:"visible"`
|
|
||||||
|
|
||||||
// Product volume weight
|
|
||||||
VolumeWeight float64 `json:"volume_weight"`
|
|
||||||
|
|
||||||
// 'true' if the item is archived manually.
|
|
||||||
IsArchived bool `json:"is_archived"`
|
IsArchived bool `json:"is_archived"`
|
||||||
|
IsAutoarchived bool `json:"is_autoarchived"`
|
||||||
// 'true' if the item is archived automatically.
|
IsDiscounted bool `json:"is_discounted"`
|
||||||
IsArchivedAuto bool `json:"is_autoarchived"`
|
IsKGT bool `json:"is_kgt"`
|
||||||
|
IsPrepaymentAllowed bool `json:"is_prepayment_allowed"`
|
||||||
// Product status details
|
|
||||||
Statuses ProductDetailsStatus `json:"statuses"`
|
|
||||||
|
|
||||||
// Product model details
|
|
||||||
ModelInfo ProductDetailsModelInfo `json:"model_info"`
|
|
||||||
|
|
||||||
// Indication of a super product
|
|
||||||
IsSuper bool `json:"is_super"`
|
IsSuper bool `json:"is_super"`
|
||||||
|
MarketingPrice string `json:"marketing_price"`
|
||||||
|
MinPrice string `json:"min_price"`
|
||||||
|
ModelInfo *ProductDetailsModelInfo `json:"model_info"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OfferId string `json:"offer_id"`
|
||||||
|
OldPrice string `json:"old_price"`
|
||||||
|
Price string `json:"price"`
|
||||||
|
PriceIndexes ProductDetailPriceIndex `json:"price_indexes"`
|
||||||
|
PrimaryImage []string `json:"primary_image"`
|
||||||
|
Sources []ProductDetailSource `json:"sources"`
|
||||||
|
Statuses ProductDetailsStatus `json:"statuses"`
|
||||||
|
Stocks ProductDetailStock `json:"stocks"`
|
||||||
|
TypeId int64 `json:"type_id"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
VAT string `json:"vat"`
|
||||||
|
VisibilityDetails ProductDetailVisibilityDetails `json:"visibility_details"`
|
||||||
|
VolumeWeight float64 `json:"volume_weight"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetailsError struct {
|
type ProductDetailsError struct {
|
||||||
@@ -306,31 +190,14 @@ type NameValue struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetailsStatus struct {
|
type ProductDetailsStatus struct {
|
||||||
// true, if the product is created correctly
|
|
||||||
IsCreated bool `json:"is_created"`
|
IsCreated bool `json:"is_created"`
|
||||||
|
|
||||||
// Moderation status
|
|
||||||
ModerateStatus string `json:"moderate_status"`
|
ModerateStatus string `json:"moderate_status"`
|
||||||
|
|
||||||
// Product status
|
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
|
StatusDescription string `json:"status_description"`
|
||||||
// Product status description
|
StatusFailed string `json:"status_failed"`
|
||||||
Description string `json:"status_description"`
|
StatusName string `json:"status_name"`
|
||||||
|
StatusTooltip string `json:"status_tooltip"`
|
||||||
// Status of the product where the error occurred
|
StatusUpdatedAt time.Time `json:"status_updated_at"`
|
||||||
Failed string `json:"status_failed"`
|
|
||||||
|
|
||||||
// Product status name
|
|
||||||
Name string `json:"status_name"`
|
|
||||||
|
|
||||||
// Status description
|
|
||||||
Tooltip string `json:"status_tooltip"`
|
|
||||||
|
|
||||||
// Time of the last status change
|
|
||||||
UpdatedAt time.Time `json:"status_updated_at"`
|
|
||||||
|
|
||||||
// Validation status
|
|
||||||
ValidationStatus string `json:"validation_status"`
|
ValidationStatus string `json:"validation_status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,58 +312,28 @@ type ProductDetailStatus struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetailSource struct {
|
type ProductDetailSource struct {
|
||||||
// Product creation date
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
// Product identifier in the Ozon system, SKU
|
|
||||||
SKU int64 `json:"sku"`
|
|
||||||
|
|
||||||
// Link to the source
|
|
||||||
Source string `json:"source"`
|
|
||||||
|
|
||||||
// Package type
|
|
||||||
ShipmentType string `json:"shipment_type"`
|
|
||||||
|
|
||||||
// List of MOQs with products
|
|
||||||
QuantCode string `json:"quant_code"`
|
QuantCode string `json:"quant_code"`
|
||||||
|
ShipmentType string `json:"shipment_type"`
|
||||||
|
SKU int64 `json:"sku"`
|
||||||
|
Source string `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetailStock struct {
|
type ProductDetailStock struct {
|
||||||
// true, if there are stocks at the warehouses
|
|
||||||
HasStock bool `json:"has_stock"`
|
HasStock bool `json:"has_stock"`
|
||||||
|
|
||||||
// Status of product stocks
|
|
||||||
Stocks []ProductDetailStockStock `json:"stocks"`
|
Stocks []ProductDetailStockStock `json:"stocks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetailStockStock struct {
|
type ProductDetailStockStock struct {
|
||||||
// Product identifier in the Ozon system, SKU
|
|
||||||
SKU int64 `json:"sku"`
|
|
||||||
|
|
||||||
// Currently at the warehouse
|
|
||||||
Present int32 `json:"present"`
|
Present int32 `json:"present"`
|
||||||
|
|
||||||
// Reserved
|
|
||||||
Reserved int32 `json:"reserved"`
|
Reserved int32 `json:"reserved"`
|
||||||
|
SKU int64 `json:"sku"`
|
||||||
// Sales scheme
|
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductDetailVisibilityDetails struct {
|
type ProductDetailVisibilityDetails struct {
|
||||||
// If the product is active, the value is true
|
|
||||||
//
|
|
||||||
// Deprecated: Use `visible` parameter of `ProductDetails`
|
|
||||||
ActiveProduct bool `json:"active_product"`
|
|
||||||
|
|
||||||
// If the price is set, the value is true
|
|
||||||
HasPrice bool `json:"has_price"`
|
HasPrice bool `json:"has_price"`
|
||||||
|
|
||||||
// If there is stock at the warehouses, the value is true
|
|
||||||
HasStock bool `json:"has_stock"`
|
HasStock bool `json:"has_stock"`
|
||||||
|
|
||||||
// Reason why the product is hidden
|
|
||||||
Reasons map[string]interface{} `json:"reasons"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductDiscountedStocks struct {
|
type ProductDiscountedStocks struct {
|
||||||
@@ -758,6 +595,9 @@ type UpdatePricesPrice struct {
|
|||||||
// Minimum product price with all promotions applied
|
// Minimum product price with all promotions applied
|
||||||
MinPrice string `json:"min_price"`
|
MinPrice string `json:"min_price"`
|
||||||
|
|
||||||
|
// Product cost price
|
||||||
|
NetPrice string `json:"net_price"`
|
||||||
|
|
||||||
// Product identifier in the seller's system
|
// Product identifier in the seller's system
|
||||||
OfferId string `json:"offer_id"`
|
OfferId string `json:"offer_id"`
|
||||||
|
|
||||||
@@ -866,7 +706,7 @@ type CreateOrUpdateProductItem struct {
|
|||||||
DescriptionCategoryId int64 `json:"description_category_id"`
|
DescriptionCategoryId int64 `json:"description_category_id"`
|
||||||
|
|
||||||
// New category identifier. Specify it if you want to change the current product category
|
// New category identifier. Specify it if you want to change the current product category
|
||||||
NewDescriptinoCategoryId int64 `json:"new_description_category_id"`
|
NewDescriptionCategoryId int64 `json:"new_description_category_id"`
|
||||||
|
|
||||||
// Marketing color.
|
// Marketing color.
|
||||||
//
|
//
|
||||||
@@ -996,7 +836,7 @@ type CreateOrUpdateProductPDF struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
// File address
|
// File address
|
||||||
URL string `json:"url"`
|
SrcUrl string `json:"src_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateOrUpdateProductResponse struct {
|
type CreateOrUpdateProductResponse struct {
|
||||||
@@ -1564,6 +1404,9 @@ type GetDescriptionOfProductResult struct {
|
|||||||
// Barcode
|
// Barcode
|
||||||
Barcode string `json:"barcode"`
|
Barcode string `json:"barcode"`
|
||||||
|
|
||||||
|
// All product's barcodes
|
||||||
|
Barcodes []string `json:"barcodes"`
|
||||||
|
|
||||||
// Category identifier
|
// Category identifier
|
||||||
DescriptionCategoryId int64 `json:"description_category_id"`
|
DescriptionCategoryId int64 `json:"description_category_id"`
|
||||||
|
|
||||||
@@ -1589,7 +1432,10 @@ type GetDescriptionOfProductResult struct {
|
|||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
|
|
||||||
// Array of links to product images
|
// Array of links to product images
|
||||||
Images []GetDescriptionOfProductResultImage `json:"images"`
|
Images []string `json:"images"`
|
||||||
|
|
||||||
|
// Model Information
|
||||||
|
ModelInfo GetDescriptionOfProductModelInfo `json:"model_info"`
|
||||||
|
|
||||||
// Array of 360 images
|
// Array of 360 images
|
||||||
Images360 []GetDescriptionOfProductResultImage360 `json:"images360"`
|
Images360 []GetDescriptionOfProductResultImage360 `json:"images360"`
|
||||||
@@ -1603,6 +1449,12 @@ type GetDescriptionOfProductResult struct {
|
|||||||
// Array of PDF files
|
// Array of PDF files
|
||||||
PDFList []GetDescriptionOfProductResultPDF `json:"pdf_list"`
|
PDFList []GetDescriptionOfProductResultPDF `json:"pdf_list"`
|
||||||
|
|
||||||
|
// Link to the main product image
|
||||||
|
PrimaryImage string `json:"primary_image"`
|
||||||
|
|
||||||
|
// Product identifier in the Ozon system, SKU
|
||||||
|
SKU int64 `json:"sku"`
|
||||||
|
|
||||||
// Product type identifier
|
// Product type identifier
|
||||||
TypeId int64 `json:"type_id"`
|
TypeId int64 `json:"type_id"`
|
||||||
|
|
||||||
@@ -1616,9 +1468,17 @@ type GetDescriptionOfProductResult struct {
|
|||||||
Width int32 `json:"width"`
|
Width int32 `json:"width"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetDescriptionOfProductModelInfo struct {
|
||||||
|
// Model Identifier
|
||||||
|
ModelId int64 `json:"model_id"`
|
||||||
|
|
||||||
|
// Quantity of combined model products
|
||||||
|
Count int64 `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
type GetDescriptionOfProductResultAttr struct {
|
type GetDescriptionOfProductResultAttr struct {
|
||||||
// Characteristic identifier
|
// Characteristic identifier
|
||||||
AttributeId int64 `json:"attribute_id"`
|
AttributeId int64 `json:"id"`
|
||||||
|
|
||||||
// Identifier of the characteristic that supports nested properties.
|
// Identifier of the characteristic that supports nested properties.
|
||||||
// For example, the "Processor" characteristic has nested characteristics "Manufacturer" and "L2 Cache".
|
// For example, the "Processor" characteristic has nested characteristics "Manufacturer" and "L2 Cache".
|
||||||
@@ -1663,12 +1523,6 @@ type GetDescriptionOfProductResultComplexAttrValue struct {
|
|||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetDescriptionOfProductResultImage struct {
|
|
||||||
Default bool `json:"default"`
|
|
||||||
FileName string `json:"file_name"`
|
|
||||||
Index int64 `json:"index"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetDescriptionOfProductResultImage360 struct {
|
type GetDescriptionOfProductResultImage360 struct {
|
||||||
FileName string `json:"file_name"`
|
FileName string `json:"file_name"`
|
||||||
Index int64 `json:"index"`
|
Index int64 `json:"index"`
|
||||||
@@ -1687,7 +1541,7 @@ type GetDescriptionOfProductResultPDF struct {
|
|||||||
|
|
||||||
// Returns a product characteristics description by product identifier. You can search for the product by `offer_id` or `product_id`
|
// Returns a product characteristics description by product identifier. You can search for the product by `offer_id` or `product_id`
|
||||||
func (c Products) GetDescriptionOfProduct(ctx context.Context, params *GetDescriptionOfProductParams) (*GetDescriptionOfProductResponse, error) {
|
func (c Products) GetDescriptionOfProduct(ctx context.Context, params *GetDescriptionOfProductParams) (*GetDescriptionOfProductResponse, error) {
|
||||||
url := "/v3/products/info/attributes"
|
url := "/v4/product/info/attributes"
|
||||||
|
|
||||||
resp := &GetDescriptionOfProductResponse{}
|
resp := &GetDescriptionOfProductResponse{}
|
||||||
|
|
||||||
@@ -1742,7 +1596,6 @@ type GetDescriptionOfProductsResult struct {
|
|||||||
ModelInfo *ModelInfo `json:"model_info,omitempty"`
|
ModelInfo *ModelInfo `json:"model_info,omitempty"`
|
||||||
|
|
||||||
Images []string `json:"images"`
|
Images []string `json:"images"`
|
||||||
PDFList []string `json:"pdf_list"`
|
|
||||||
|
|
||||||
Attributes []GetDescriptionOfProductsAttribute `json:"attributes"`
|
Attributes []GetDescriptionOfProductsAttribute `json:"attributes"`
|
||||||
ComplexAttributes []GetDescriptionOfProductsComplexAttribute `json:"complex_attributes"`
|
ComplexAttributes []GetDescriptionOfProductsComplexAttribute `json:"complex_attributes"`
|
||||||
@@ -2113,10 +1966,6 @@ type GetProductPriceInfoFilter struct {
|
|||||||
type GetProductPriceInfoResponse struct {
|
type GetProductPriceInfoResponse struct {
|
||||||
core.CommonResponse
|
core.CommonResponse
|
||||||
|
|
||||||
Result GetProductPriceInfoResult `json:"result"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetProductPriceInfoResult struct {
|
|
||||||
// Products list
|
// Products list
|
||||||
Items []GetProductPriceInfoResultItem `json:"items"`
|
Items []GetProductPriceInfoResultItem `json:"items"`
|
||||||
|
|
||||||
@@ -2129,7 +1978,7 @@ type GetProductPriceInfoResult struct {
|
|||||||
|
|
||||||
type GetProductPriceInfoResultItem struct {
|
type GetProductPriceInfoResultItem struct {
|
||||||
// Maximum acquiring fee
|
// Maximum acquiring fee
|
||||||
Acquiring int32 `json:"acquiring"`
|
Acquiring float64 `json:"acquiring"`
|
||||||
|
|
||||||
// Commissions information
|
// Commissions information
|
||||||
Commissions GetProductPriceInfoResultItemCommission `json:"commissions"`
|
Commissions GetProductPriceInfoResultItemCommission `json:"commissions"`
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetStocksInfo(t *testing.T) {
|
func TestGetStocksInfo(t *testing.T) {
|
||||||
@@ -1370,37 +1370,33 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"id": 213761435,
|
"id": 213761435,
|
||||||
"barcode": "",
|
"barcode": "",
|
||||||
"description_category_id": 17038062,
|
"barcodes": [
|
||||||
|
"123124123",
|
||||||
|
"123342455"
|
||||||
|
],
|
||||||
"name": "Пленка защитная для Xiaomi Redmi Note 10 Pro 5G",
|
"name": "Пленка защитная для Xiaomi Redmi Note 10 Pro 5G",
|
||||||
"offer_id": "21470",
|
"offer_id": "21470",
|
||||||
|
"type_id": 124572394,
|
||||||
"height": 10,
|
"height": 10,
|
||||||
"depth": 210,
|
"depth": 210,
|
||||||
"width": 140,
|
"width": 140,
|
||||||
"dimension_unit": "mm",
|
"dimension_unit": "mm",
|
||||||
"weight": 50,
|
"weight": 50,
|
||||||
"weight_unit": "g",
|
"weight_unit": "g",
|
||||||
|
"primary_image": "https://cdn1.ozone.ru/s3/multimedia-4/6804736960.jpg",
|
||||||
|
"sku": 423434534,
|
||||||
|
"model_info": {
|
||||||
|
"model_id": 43445453,
|
||||||
|
"count": 4
|
||||||
|
},
|
||||||
"images": [
|
"images": [
|
||||||
{
|
"https://cdn1.ozone.ru/s3/multimedia-4/6804736960.jpg",
|
||||||
"file_name": "https://cdn1.ozone.ru/s3/multimedia-f/6190456071.jpg",
|
"https://cdn1.ozone.ru/s3/multimedia-j/6835412647.jpg"
|
||||||
"default": true,
|
|
||||||
"index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file_name": "https://cdn1.ozone.ru/s3/multimedia-7/6190456099.jpg",
|
|
||||||
"default": false,
|
|
||||||
"index": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file_name": "https://cdn1.ozone.ru/s3/multimedia-9/6190456065.jpg",
|
|
||||||
"default": false,
|
|
||||||
"index": 2
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"images360": [],
|
|
||||||
"pdf_list": [],
|
"pdf_list": [],
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{
|
{
|
||||||
"attribute_id": 5219,
|
"id": 5219,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1410,7 +1406,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 11051,
|
"id": 11051,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1420,7 +1416,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 10100,
|
"id": 10100,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1430,7 +1426,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 11794,
|
"id": 11794,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1440,7 +1436,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 9048,
|
"id": 9048,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1450,7 +1446,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 5076,
|
"id": 5076,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1460,7 +1456,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 9024,
|
"id": 9024,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1470,7 +1466,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 10015,
|
"id": 10015,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1480,7 +1476,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 85,
|
"id": 85,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1490,7 +1486,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 9461,
|
"id": 9461,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1500,7 +1496,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 4180,
|
"id": 4180,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1510,7 +1506,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 4191,
|
"id": 4191,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1520,7 +1516,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attribute_id": 8229,
|
"id": 8229,
|
||||||
"complex_id": 0,
|
"complex_id": 0,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
@@ -1531,7 +1527,8 @@ func TestGetDescriptionOfProduct(t *testing.T) {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"complex_attributes": [],
|
"complex_attributes": [],
|
||||||
"color_image": ""
|
"color_image": "",
|
||||||
|
"description_category_id": 71107562
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total": 1,
|
"total": 1,
|
||||||
@@ -2158,11 +2155,10 @@ func TestGetProductPriceInfo(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
`{
|
`{
|
||||||
"result": {
|
|
||||||
"cursor": "string",
|
"cursor": "string",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"acquiring": 0,
|
"acquiring": 0.5,
|
||||||
"commissions": {
|
"commissions": {
|
||||||
"fbo_deliv_to_customer_amount": 14.75,
|
"fbo_deliv_to_customer_amount": 14.75,
|
||||||
"fbo_direct_flow_trans_max_amount": 46.5,
|
"fbo_direct_flow_trans_max_amount": 46.5,
|
||||||
@@ -2225,7 +2221,6 @@ func TestGetProductPriceInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"total": 0
|
"total": 0
|
||||||
}
|
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
// Test No Client-Id or Api-Key
|
// Test No Client-Id or Api-Key
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Promotions struct {
|
type Promotions struct {
|
||||||
@@ -297,196 +297,6 @@ func (c Promotions) RemoveProduct(ctx context.Context, params *RemoveProductFrom
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListHotSalePromotionsResponse struct {
|
|
||||||
core.CommonResponse
|
|
||||||
|
|
||||||
// Method result
|
|
||||||
Result []ListHotSalePromotionsResult `json:"result"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListHotSalePromotionsResult struct {
|
|
||||||
// Promotion end date
|
|
||||||
DateEnd string `json:"date_end"`
|
|
||||||
|
|
||||||
// Promotion start date
|
|
||||||
DateStart string `json:"date_start"`
|
|
||||||
|
|
||||||
// Promotion description
|
|
||||||
Description string `json:"description"`
|
|
||||||
|
|
||||||
// Promotion freeze date.
|
|
||||||
//
|
|
||||||
// If the field is filled, the seller can't increase prices, change the list of products,
|
|
||||||
// or decrease the number of product units in the promotion.
|
|
||||||
//
|
|
||||||
// The seller can lower prices and increase the product units number in the promotion
|
|
||||||
FreezeDate string `json:"freeze_date"`
|
|
||||||
|
|
||||||
// Hot Sale promotion identifier
|
|
||||||
HotsaleId float64 `json:"hotsale_id"`
|
|
||||||
|
|
||||||
// Indication that you participate in this promotion
|
|
||||||
IsParticipating bool `json:"is_participating"`
|
|
||||||
|
|
||||||
// Promotion name
|
|
||||||
Title string `json:"title"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// List of available Hot Sale promotions
|
|
||||||
func (c Promotions) ListHotSalePromotions(ctx context.Context) (*ListHotSalePromotionsResponse, error) {
|
|
||||||
url := "/v1/actions/hotsales/list"
|
|
||||||
|
|
||||||
resp := &ListHotSalePromotionsResponse{}
|
|
||||||
|
|
||||||
response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.CopyCommonResponse(&resp.CommonResponse)
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsAvailableForHotSalePromotionParams struct {
|
|
||||||
// Hot Sale promotion identifier
|
|
||||||
HotSaleId float64 `json:"hotsale_id"`
|
|
||||||
|
|
||||||
// Number of elements in the response. Default value is 100
|
|
||||||
Limit float64 `json:"limit"`
|
|
||||||
|
|
||||||
// Number of elements that will be skipped in the response. For example, if offset=10, the response will start with the 11th element found
|
|
||||||
Offset float64 `json:"offset,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsAvailableForHotSalePromotionResponse struct {
|
|
||||||
core.CommonResponse
|
|
||||||
|
|
||||||
// Method result
|
|
||||||
Result ProductsAvailableForHotSalePromotionResult `json:"result"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsAvailableForHotSalePromotionResult struct {
|
|
||||||
// Products list
|
|
||||||
Products []ProductsAvailableForHotSalePromotionResultProduct `json:"products"`
|
|
||||||
|
|
||||||
// Total number of products that are available for the promotion
|
|
||||||
Total float64 `json:"total"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsAvailableForHotSalePromotionResultProduct struct {
|
|
||||||
// Promotional product price
|
|
||||||
ActionPrice float64 `json:"action_price"`
|
|
||||||
|
|
||||||
// Date when the product participates in the promotion in the YYYY-MM-DD format
|
|
||||||
DateDayPromo string `json:"date_day_promo"`
|
|
||||||
|
|
||||||
// Product identifier
|
|
||||||
Id float64 `json:"id"`
|
|
||||||
|
|
||||||
// Indication that product participates in the promotion
|
|
||||||
IsActive bool `json:"is_active"`
|
|
||||||
|
|
||||||
// Maximum possible promotional price of the product
|
|
||||||
MaxActionPrice float64 `json:"max_action_price"`
|
|
||||||
|
|
||||||
// Minimum number of product units in a stock discount type promotion
|
|
||||||
MinStock float64 `json:"min_stock"`
|
|
||||||
|
|
||||||
// Number of product units in a stock discount type promotion
|
|
||||||
Stock float64 `json:"stock"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method for getting a list of products that can participate or are already participating in the Hot Sale promotion
|
|
||||||
func (c Promotions) ProductsAvailableForHotSalePromotion(ctx context.Context, params *ProductsAvailableForHotSalePromotionParams) (*ProductsAvailableForHotSalePromotionResponse, error) {
|
|
||||||
url := "/v1/actions/hotsales/products"
|
|
||||||
|
|
||||||
resp := &ProductsAvailableForHotSalePromotionResponse{}
|
|
||||||
|
|
||||||
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.CopyCommonResponse(&resp.CommonResponse)
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddProductsToHotSaleParams struct {
|
|
||||||
// Hot Sale promotion identifier
|
|
||||||
HotSaleId float64 `json:"hotsale_id"`
|
|
||||||
|
|
||||||
// Products to be added to the promotion. The maximum number in one request is 100
|
|
||||||
Products []AddProductsToHotSaleProduct `json:"products"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddProductsToHotSaleProduct struct {
|
|
||||||
// Promotional product price
|
|
||||||
ActionPrice float64 `json:"action_price"`
|
|
||||||
|
|
||||||
// Product identifier
|
|
||||||
ProductId float64 `json:"product_id"`
|
|
||||||
|
|
||||||
// Number of product units in a stock discount type promotion
|
|
||||||
Stock float64 `json:"stock"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsToHotSaleResponse struct {
|
|
||||||
core.CommonResponse
|
|
||||||
|
|
||||||
// Method result
|
|
||||||
Result ProductsToHotSaleResult `json:"result"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsToHotSaleResult struct {
|
|
||||||
// List of products that haven't been added to the promotion
|
|
||||||
Rejected []ProductsToHotSaleResultRejected `json:"rejected"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductsToHotSaleResultRejected struct {
|
|
||||||
//Product identifier
|
|
||||||
ProductId float64 `json:"product_id"`
|
|
||||||
|
|
||||||
// Reason why the product hasn't been added to the promotion
|
|
||||||
Reason string `json:"reason"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Promotions) AddProductsToHotSale(ctx context.Context, params *AddProductsToHotSaleParams) (*ProductsToHotSaleResponse, error) {
|
|
||||||
url := "/v1/actions/hotsales/activate"
|
|
||||||
|
|
||||||
resp := &ProductsToHotSaleResponse{}
|
|
||||||
|
|
||||||
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.CopyCommonResponse(&resp.CommonResponse)
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type RemoveProductsToHotSaleParams struct {
|
|
||||||
// Hot Sale promotion identifier
|
|
||||||
HotSaleId float64 `json:"hotsale_id"`
|
|
||||||
|
|
||||||
// List of products identifiers. Maximum number of values in one request is 100
|
|
||||||
ProductIds []float64 `json:"product_ids"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove product from the Hot Sale promotion
|
|
||||||
func (c Promotions) RemoveProductsToHotSale(ctx context.Context, params *RemoveProductsToHotSaleParams) (*ProductsToHotSaleResponse, error) {
|
|
||||||
url := "/v1/actions/hotsales/activate"
|
|
||||||
|
|
||||||
resp := &ProductsToHotSaleResponse{}
|
|
||||||
|
|
||||||
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.CopyCommonResponse(&resp.CommonResponse)
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListDiscountRequestsParams struct {
|
type ListDiscountRequestsParams struct {
|
||||||
// Discount request status
|
// Discount request status
|
||||||
Status ListDiscountRequestsStatus `json:"status" default:"UNKNOWN"`
|
Status ListDiscountRequestsStatus `json:"status" default:"UNKNOWN"`
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetAvailablePromotions(t *testing.T) {
|
func TestGetAvailablePromotions(t *testing.T) {
|
||||||
@@ -354,248 +354,6 @@ func TestRemoveProduct(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListHotSalePromotions(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
statusCode int
|
|
||||||
headers map[string]string
|
|
||||||
response string
|
|
||||||
}{
|
|
||||||
// Test Ok
|
|
||||||
{
|
|
||||||
http.StatusOK,
|
|
||||||
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
|
||||||
`{
|
|
||||||
"result": [
|
|
||||||
{
|
|
||||||
"date_end": "string",
|
|
||||||
"date_start": "string",
|
|
||||||
"description": "string",
|
|
||||||
"freeze_date": "string",
|
|
||||||
"hotsale_id": 0,
|
|
||||||
"is_participating": true,
|
|
||||||
"title": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
// Test No Client-Id or Api-Key
|
|
||||||
{
|
|
||||||
http.StatusUnauthorized,
|
|
||||||
map[string]string{},
|
|
||||||
`{
|
|
||||||
"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.Promotions().ListHotSalePromotions(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
compareJsonResponse(t, test.response, &ListHotSalePromotionsResponse{})
|
|
||||||
|
|
||||||
if resp.StatusCode != test.statusCode {
|
|
||||||
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProductsAvailableForHotSalePromotion(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
statusCode int
|
|
||||||
headers map[string]string
|
|
||||||
params *ProductsAvailableForHotSalePromotionParams
|
|
||||||
response string
|
|
||||||
}{
|
|
||||||
// Test Ok
|
|
||||||
{
|
|
||||||
http.StatusOK,
|
|
||||||
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
|
||||||
&ProductsAvailableForHotSalePromotionParams{
|
|
||||||
HotSaleId: 0,
|
|
||||||
Limit: 0,
|
|
||||||
Offset: 0,
|
|
||||||
},
|
|
||||||
`{
|
|
||||||
"result": {
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"action_price": 0,
|
|
||||||
"date_day_promo": "string",
|
|
||||||
"id": 0,
|
|
||||||
"is_active": true,
|
|
||||||
"max_action_price": 0,
|
|
||||||
"min_stock": 0,
|
|
||||||
"stock": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"total": 0
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
// Test No Client-Id or Api-Key
|
|
||||||
{
|
|
||||||
http.StatusUnauthorized,
|
|
||||||
map[string]string{},
|
|
||||||
&ProductsAvailableForHotSalePromotionParams{},
|
|
||||||
`{
|
|
||||||
"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.Promotions().ProductsAvailableForHotSalePromotion(ctx, test.params)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
compareJsonResponse(t, test.response, &ProductsAvailableForHotSalePromotionResponse{})
|
|
||||||
|
|
||||||
if resp.StatusCode != test.statusCode {
|
|
||||||
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddProductsToHotSale(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
statusCode int
|
|
||||||
headers map[string]string
|
|
||||||
params *AddProductsToHotSaleParams
|
|
||||||
response string
|
|
||||||
}{
|
|
||||||
// Test Ok
|
|
||||||
{
|
|
||||||
http.StatusOK,
|
|
||||||
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
|
||||||
&AddProductsToHotSaleParams{
|
|
||||||
HotSaleId: 1234,
|
|
||||||
Products: []AddProductsToHotSaleProduct{
|
|
||||||
{
|
|
||||||
ActionPrice: 12,
|
|
||||||
ProductId: 111,
|
|
||||||
Stock: 45,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
`{
|
|
||||||
"result": {
|
|
||||||
"rejected": [
|
|
||||||
{
|
|
||||||
"product_id": 0,
|
|
||||||
"reason": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
// Test No Client-Id or Api-Key
|
|
||||||
{
|
|
||||||
http.StatusUnauthorized,
|
|
||||||
map[string]string{},
|
|
||||||
&AddProductsToHotSaleParams{},
|
|
||||||
`{
|
|
||||||
"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.Promotions().AddProductsToHotSale(ctx, test.params)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
compareJsonResponse(t, test.response, &ProductsToHotSaleResponse{})
|
|
||||||
|
|
||||||
if resp.StatusCode != test.statusCode {
|
|
||||||
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveProductsToHotSale(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
statusCode int
|
|
||||||
headers map[string]string
|
|
||||||
params *RemoveProductsToHotSaleParams
|
|
||||||
response string
|
|
||||||
}{
|
|
||||||
// Test Ok
|
|
||||||
{
|
|
||||||
http.StatusOK,
|
|
||||||
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
|
|
||||||
&RemoveProductsToHotSaleParams{
|
|
||||||
HotSaleId: 12345,
|
|
||||||
ProductIds: []float64{111},
|
|
||||||
},
|
|
||||||
`{
|
|
||||||
"result": {
|
|
||||||
"rejected": [
|
|
||||||
{
|
|
||||||
"product_id": 0,
|
|
||||||
"reason": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
// Test No Client-Id or Api-Key
|
|
||||||
{
|
|
||||||
http.StatusUnauthorized,
|
|
||||||
map[string]string{},
|
|
||||||
&RemoveProductsToHotSaleParams{},
|
|
||||||
`{
|
|
||||||
"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.Promotions().RemoveProductsToHotSale(ctx, test.params)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
compareJsonResponse(t, test.response, &ProductsToHotSaleResponse{})
|
|
||||||
|
|
||||||
if resp.StatusCode != test.statusCode {
|
|
||||||
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListDiscountRequests(t *testing.T) {
|
func TestListDiscountRequests(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Quants struct {
|
type Quants struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListQuants(t *testing.T) {
|
func TestListQuants(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rating struct {
|
type Rating struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetCurrentRatingInfo(t *testing.T) {
|
func TestGetCurrentRatingInfo(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Reports struct {
|
type Reports struct {
|
||||||
@@ -480,6 +480,10 @@ type GetReturnsReportsFilter struct {
|
|||||||
type GetReturnsReportResponse struct {
|
type GetReturnsReportResponse struct {
|
||||||
core.CommonResponse
|
core.CommonResponse
|
||||||
|
|
||||||
|
Result GetReturnsReportResult `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetReturnsReportResult struct {
|
||||||
// Unique report identifier. The report is available for downloading within 3 days after making a request.
|
// Unique report identifier. The report is available for downloading within 3 days after making a request.
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetList(t *testing.T) {
|
func TestGetList(t *testing.T) {
|
||||||
@@ -380,7 +380,9 @@ func TestGetReturnsReport(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
`{
|
`{
|
||||||
|
"result": {
|
||||||
"code": "REPORT_seller_products_924336_1720170405_a9ea2f27-a473-4b13-99f9-d0cfcb5b1a69"
|
"code": "REPORT_seller_products_924336_1720170405_a9ea2f27-a473-4b13-99f9-d0cfcb5b1a69"
|
||||||
|
}
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
// Test No Client-Id or Api-Key
|
// Test No Client-Id or Api-Key
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Returns struct {
|
type Returns struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetRFBSReturns(t *testing.T) {
|
func TestGetRFBSReturns(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Reviews struct {
|
type Reviews struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLeaveComment(t *testing.T) {
|
func TestLeaveComment(t *testing.T) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Strategies struct {
|
type Strategies struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListCompetitors(t *testing.T) {
|
func TestListCompetitors(t *testing.T) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Warehouses struct {
|
type Warehouses struct {
|
||||||
@@ -88,7 +88,8 @@ type GetListOfWarehousesResultFirstMile struct {
|
|||||||
FirstMileType string `json:"first_mile_type"`
|
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
|
// Method returns the list of FBS and rFBS warehouses.
|
||||||
|
// To get the list of FBO warehouses, use the /v1/cluster/list method.
|
||||||
func (c Warehouses) GetListOfWarehouses(ctx context.Context) (*GetListOfWarehousesResponse, error) {
|
func (c Warehouses) GetListOfWarehouses(ctx context.Context) (*GetListOfWarehousesResponse, error) {
|
||||||
url := "/v1/warehouse/list"
|
url := "/v1/warehouse/list"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
core "github.com/diphantxm/ozon-api-client"
|
core "git.denco.store/fakz9/ozon-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetListOfWarehouses(t *testing.T) {
|
func TestGetListOfWarehouses(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user