14 Commits

Author SHA1 Message Date
89aeba12d4 fixed misspelling
Some checks failed
tests / unit (push) Has been cancelled
tests / coverage (push) Has been cancelled
2025-07-23 05:38:00 +03:00
1e2c591a70 fixed misspelling
Some checks are pending
tests / unit (push) Waiting to run
tests / coverage (push) Waiting to run
2025-07-23 04:32:47 +03:00
3e6c8fbc05 fixed misspelling
Some checks are pending
tests / unit (push) Waiting to run
tests / coverage (push) Waiting to run
2025-07-23 04:23:08 +03:00
c6c3030925 Refactor ProductDetails struct for improved clarity and organization
Some checks failed
tests / unit (push) Has been cancelled
tests / coverage (push) Has been cancelled
2025-05-26 03:37:54 +03:00
c9ca89e364 Update module path to git.denco.store/fakz9/ozon-api-client
Some checks are pending
tests / unit (push) Waiting to run
tests / coverage (push) Waiting to run
2025-05-26 03:24:11 +03:00
dcff4ba1e3 Change module path to git.denco.store/fakz9/ozon-api-client
Some checks are pending
tests / unit (push) Waiting to run
tests / coverage (push) Waiting to run
2025-05-26 03:19:07 +03:00
Kirill
25e5e568b5 Update March 11, 2025 (#154) 2025-04-11 01:53:40 +03:00
Kirill
a9d7a5c6d3 Update March 3, 2025 (#153) 2025-04-11 01:41:48 +03:00
Kirill
bac3c04f59 Fix GetProductPriceInfo response (#152) 2025-03-06 01:23:54 +03:00
Kirill
851e7a2819 Update February 28, 2025 (#150) 2025-03-02 15:43:21 +03:00
Kirill
94119c0f39 Update February 27, 2025 (#149) 2025-03-02 15:30:08 +03:00
Kirill
1c42f6b3a6 Update February 26, 2025 (#148) 2025-03-02 15:17:09 +03:00
Kirill
dc69b67f0f Update February 24, 2025 (#147) 2025-03-02 15:15:15 +03:00
Kirill
bd280b54f4 Update February 17, 2025 (#146) 2025-03-02 15:11:00 +03:00
51 changed files with 828 additions and 995 deletions

8
.idea/.gitignore generated vendored Normal file
View 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

View File

@@ -2,7 +2,7 @@
A Ozon Seller API client written in Golang
[![Coverage Status](https://coveralls.io/repos/github/diPhantxm/ozon-api-client/badge.svg)](https://coveralls.io/github/diPhantxm/ozon-api-client)
![example workflow](https://github.com/diPhantxm/ozon-api-client/actions/workflows/tests.yml/badge.svg)
![example workflow](https://git.denco.store/fakz9/ozon-api-client/actions/workflows/tests.yml/badge.svg)
[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.
```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:
```Golang
@@ -26,7 +26,7 @@ import (
"log"
"net/http"
"github.com/diphantxm/ozon-api-client/ozon"
"git.denco.store/fakz9/ozon-api-client/ozon"
)
func main() {
@@ -65,7 +65,7 @@ package main
import (
"log"
"github.com/diphantxm/ozon-api-client/ozon/notifications"
"git.denco.store/fakz9/ozon-api-client/ozon/notifications"
)
func main() {

2
go.mod
View File

@@ -1,4 +1,4 @@
module github.com/diphantxm/ozon-api-client
module git.denco.store/fakz9/ozon-api-client
go 1.20

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Analytics struct {
@@ -200,12 +200,9 @@ type GetStocksOnWarehousesResultRow struct {
// Name of the warehouse where the products are stored
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) {
url := "/v2/analytics/stock_on_warehouses"
@@ -340,3 +337,114 @@ func (c Analytics) Stock(ctx context.Context, params *GetStockManagementParams)
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
}

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
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)
}
}
}

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Barcodes struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGenerateBarcodes(t *testing.T) {

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Brands struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListCertifiedBrands(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Cancellations struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetCancellationInfo(t *testing.T) {

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Categories struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetProductTree(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Certificates struct {

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListOfAccordanceTypes(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
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
Direction string `json:"direction" default:"Backward"`
Filter *ChatHistoryFilter `json:"filter,omitempty"`
// Identifier of the message from which the chat history will be displayed.
// Default value is the last visible message
FromMessageId string `json:"from_message_id"`
@@ -172,6 +174,10 @@ type ChatHistoryParams struct {
Limit int64 `json:"limit" default:"50"`
}
type ChatHistoryFilter struct {
MessageIds []string `json:"message_ids"`
}
type ChatHistoryResponse struct {
core.CommonResponse
@@ -183,22 +189,33 @@ type ChatHistoryResponse struct {
}
type ChatHistoryMessage struct {
Context *ChatHistoryContext `json:"context,omitempty"`
// Message creation date
CreatedAt time.Time `json:"created_at"`
// Array with message content in Markdown format
Data []string `json:"data"`
IsImage bool `json:"is_image"`
// Indication of the read message
IsRead bool `json:"is_read"`
// Message identifier
MessageId string `json:"message_id"`
ModarateImageStatus string `json:"moderate_image_status"`
// Chat participant identifier
User ChatHistoryMessageUser `json:"user"`
}
type ChatHistoryContext struct {
OrderNumber string `json:"order_number"`
SKU string `json:"sku"`
}
type ChatHistoryMessageUser struct {
// Chat participant identifier
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.
func (c Chats) History(ctx context.Context, params *ChatHistoryParams) (*ChatHistoryResponse, error) {
url := "/v2/chat/history"
url := "/v3/chat/history"
resp := &ChatHistoryResponse{}

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListChats(t *testing.T) {
@@ -212,16 +212,22 @@ func TestChatHistory(t *testing.T) {
"has_next": true,
"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",
"moderate_image_status": "SUCCESS",
"user": {
"id": "115568",
"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) телефона?"
]
}
}
]
}`,

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Clusters struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListClusters(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type FBO struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetFBOShipmentsList(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type FBS struct {
@@ -195,6 +195,14 @@ type FBSPosting struct {
// Economy product identifier
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 {
@@ -240,7 +248,7 @@ type FBSPostingAddressee 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"`
// Delivery start date and time
@@ -373,9 +381,6 @@ type FBSRequirements struct {
}
type PostingProduct struct {
// Mandatory product labeling
MandatoryMark []string `json:"mandatory_mark"`
// Product name
Name string `json:"name"`
@@ -393,6 +398,9 @@ type PostingProduct struct {
// Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"`
// Product traceability attribute
IsBLRTraceable bool `json:"is_blr_traceable"`
}
type FBSCustomer struct {
@@ -769,7 +777,7 @@ type ValidateLabelingCodesExemplar struct {
GTD string `json:"gtd"`
// Mandatory “Chestny ZNAK” labeling
MandatoryMark string `json:"mandatory_mark"`
Marks []SetProductItemsDataProductMark `json:"marks"`
// Product batch registration number
RNPT string `json:"rnpt"`
@@ -778,11 +786,6 @@ type ValidateLabelingCodesExemplar struct {
type ValidateLabelingCodesResponse struct {
core.CommonResponse
// Method result
Result ValidateLabelingCodesResult `json:"result"`
}
type ValidateLabelingCodesResult struct {
// Products list
Products []ValidateLabelingCodesResultProduct `json:"products"`
}
@@ -792,7 +795,7 @@ type ValidateLabelingCodesResultProduct struct {
Error string `json:"error"`
// Product items data
Exemplars []FBSProductExemplar `json:"exemplars"`
Exemplars []ValidateLabelingCodesResultExemplar `json:"exemplars"`
// Product identifier
ProductId int64 `json:"product_id"`
@@ -801,11 +804,43 @@ type ValidateLabelingCodesResultProduct struct {
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.
//
// 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) {
url := "/v4/fbs/posting/product/exemplar/validate"
url := "/v5/fbs/posting/product/exemplar/validate"
resp := &ValidateLabelingCodesResponse{}
@@ -1016,6 +1051,9 @@ type GetShipmentDataByIdentifierResult struct {
// Number of the parent shipment which split resulted in the current shipment
ParentPostingNumber string `json:"parent_posting_number"`
// List of products with additional characteristics
Optional GetShipmentDataByIdentifierOptional `json:"optional"`
// Shipment number
PostingNumber string `json:"posting_number"`
@@ -1067,6 +1105,11 @@ type GetShipmentDataByIdentifierResult struct {
Tariffication []FBSPostingTariffication `json:"tariffication"`
}
type GetShipmentDataByIdentifierOptional struct {
// List of products with optional labeling
ProductsWithPossibleMandatoryMark []int `json:"products_with_possible_mandatory_mark"`
}
type GetShipmentDataByIdentifierResultAdditionalData struct {
// Key
Key string `json:"key"`
@@ -1086,7 +1129,7 @@ type GetShipmentDataByIdentifierResultAddressee 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"`
// Delivery start date and time
@@ -1194,39 +1237,23 @@ type ProductDimension struct {
}
type FBSProductExemplar struct {
// Product item validation errors
Errors []string `json:"errors"`
// Item identifier
ExemplarId int64 `json:"exemplar_id"`
// Mandatory “Chestny ZNAK” labeling
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
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
IsGTDAbsest bool `json:"is_gtd_absent"`
// Сustoms cargo declaration (CCD) check error codes
GTDErrorCodes []string `json:"gtd_error_codes"`
// Product batch registration number
RNPT string `json:"rnpt"`
// Indication that a product batch registration number hasn't been specified
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
@@ -1803,7 +1830,7 @@ func (c FBS) GetDropOffPointRestrictions(ctx context.Context, params *GetDropOff
return resp, nil
}
type CheckProductItemsDataParams struct {
type SetProductItemsDataParams struct {
// Quantity of boxes the product is packed in
MultiBoxQuantity int32 `json:"multi_box_qty"`
@@ -1811,20 +1838,26 @@ type CheckProductItemsDataParams struct {
PostingNumber string `json:"posting_number"`
// Product list
Products []CheckProductItemsDataProduct `json:"products"`
Products []SetProductItemsDataProduct `json:"products"`
}
type CheckProductItemsDataProduct struct {
type SetProductItemsDataProduct struct {
// Product items data
Exemplars []CheckProductItemsDataProductExemplar `json:"exemplars"`
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"`
@@ -1835,48 +1868,35 @@ type CheckProductItemsDataProduct struct {
Quantity int32 `json:"quantity"`
}
type CheckProductItemsDataProductExemplar struct {
type SetProductItemsDataProductExemplar 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"`
// "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
IsRNPTAbsent bool `json:"is_rnpt_absent"`
// Mandatory "Chestny ZNAK" labeling
MandatoryMark string `json:"mandatory_mark"`
// 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"`
// Unique identifier of charges of the jewelry
JWUIN string `json:"jw_uin"`
// Errors that appeared during verification of Control Identification Marks
Marks []SetProductItemsDataProductMark `json:"marks"`
}
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
// Method result. true if the request was processed successfully
@@ -1885,39 +1905,21 @@ type CheckProductItemsDataResponse struct {
// Asynchronous method:
//
// for checking the availability of product items in the “Chestny ZNAK” labeling system;
// for saving product items data.
// for checking the availability of product items in the “Chestny ZNAK” labeling system;
// 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,
// 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.
// 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.
//
// For example, you have 10 product items in your system.
// 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.
// 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.
//
// Unlike /v4/fbs/posting/product/exemplar/set,
// you can pass more item information in the request.
//
// 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"
// 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.
func (c FBS) SetProductItemsData(ctx context.Context, params *SetProductItemsDataParams) (*SetProductItemsDataResponse, error) {
url := "/v6/fbs/posting/product/exemplar/set"
resp := &CheckProductItemsDataResponse{}
resp := &SetProductItemsDataResponse{}
response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
if err != nil {
@@ -1940,19 +1942,71 @@ type GetProductItemsCheckStatusesResponse struct {
PostingNumber string `json:"posting_number"`
// Products list
Products []CheckProductItemsDataProduct `json:"products"`
Products []GetProductItemsCheckStatusProduct `json:"products"`
// 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
// Product items check statuses and order collection availability
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.
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{}
@@ -2938,11 +2992,37 @@ type CreateOrGetProductExemplarResponse struct {
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.
//
// Use this method to get the `exemplar_id`
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{}
@@ -3310,3 +3390,29 @@ func (c FBS) VerifyCourierCode(ctx context.Context, params *VerifyCourierCodePar
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
}

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListUnprocessedShipments(t *testing.T) {
@@ -58,6 +58,11 @@ func TestListUnprocessedShipments(t *testing.T) {
"in_process_at": "2021-08-25T10:48:38Z",
"shipment_date": "2021-08-26T10:00:00Z",
"delivering_date": null,
"optional": {
"products_with_possible_mandatory_mark": [
0
]
},
"cancellation": {
"cancel_reason_id": 0,
"cancel_reason": "",
@@ -71,12 +76,12 @@ func TestListUnprocessedShipments(t *testing.T) {
"products": [
{
"currency_code": "RUB",
"is_blr_traceable": true,
"price": "1259",
"offer_id": "УТ-0001365",
"name": "Мяч, цвет: черный, 5 кг",
"sku": 140048123,
"quantity": 1,
"mandatory_mark": []
"quantity": 1
}
],
"addressee": null,
@@ -255,6 +260,11 @@ func TestGetFBSShipmentsList(t *testing.T) {
"in_process_at": "2022-05-13T07:07:32Z",
"shipment_date": "2022-05-13T10:00:00Z",
"delivering_date": null,
"optional": {
"products_with_possible_mandatory_mark": [
0
]
},
"cancellation": {
"cancel_reason_id": 0,
"cancel_reason": "",
@@ -267,12 +277,12 @@ func TestGetFBSShipmentsList(t *testing.T) {
"products": [
{
"currency_code": "RUB",
"is_blr_traceable": true,
"price": "1390.000000",
"offer_id": "205953",
"name": " Электронный конструктор PinLab Позитроник",
"sku": 358924380,
"quantity": 1,
"mandatory_mark": []
"quantity": 1
}
],
"addressee": null,
@@ -303,7 +313,7 @@ func TestGetFBSShipmentsList(t *testing.T) {
],
"has_next": true
}
}`,
}`,
},
// Test No Client-Id or Api-Key
{
@@ -423,8 +433,7 @@ func TestValidateLabelingCodes(t *testing.T) {
{
Exemplars: []ValidateLabelingCodesExemplar{
{
GTD: "",
MandatoryMark: "010290000151642731tVMohkbfFgunB",
GTD: "",
},
},
ProductId: 476925391,
@@ -432,23 +441,33 @@ func TestValidateLabelingCodes(t *testing.T) {
},
},
`{
"result": {
"products": [
{
"product_id": 476925391,
"exemplars": [
{
"mandatory_mark": "010290000151642731tVMohkbfFgunB",
"gtd": "",
"valid": true,
"errors": []
}
],
"valid": true,
"error": ""
}
]
}
"products": [
{
"error": "string",
"exemplars": [
{
"errors": [
"string"
],
"gtd": "string",
"marks": [
{
"errors": [
"string"
],
"mark": "string",
"mark_type": "string",
"valid": true
}
],
"rnpt": "string",
"valid": true
}
],
"product_id": 476925391,
"valid": true
}
]
}`,
},
// Test No Client-Id or Api-Key
@@ -480,11 +499,11 @@ func TestValidateLabelingCodes(t *testing.T) {
}
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")
}
if len(resp.Result.Products) > 0 {
if resp.Result.Products[0].ProductId != test.params.Products[0].ProductId {
if len(resp.Products) > 0 {
if resp.Products[0].ProductId != test.params.Products[0].ProductId {
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",
"name": "Кофе ароматизированный \"Шоколадный апельсин\" 250 гр",
"sku": 180550365,
"quantity": 1,
"mandatory_mark": []
"quantity": 1
}
],
"barcodes": null,
@@ -612,6 +630,11 @@ func TestGetShipmentDataByIdentifier(t *testing.T) {
"delivering_date": null,
"provider_status": "",
"delivery_price": "",
"optional": {
"products_with_possible_mandatory_mark": [
0
]
},
"cancellation": {
"cancel_reason_id": 0,
"cancel_reason": "",
@@ -625,12 +648,12 @@ func TestGetShipmentDataByIdentifier(t *testing.T) {
"products": [
{
"currency_code": "RUB",
"is_blr_traceable": true,
"price": "279.0000",
"offer_id": "250-7898-1",
"name": "Кофе ароматизированный \"Шоколадный апельсин\" 250 гр",
"sku": 180550365,
"quantity": 1,
"mandatory_mark": [],
"dimensions": {
"height": "40.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()
tests := []struct {
statusCode int
headers map[string]string
params *CheckProductItemsDataParams
params *SetProductItemsDataParams
response string
}{
// Test Ok
{
http.StatusOK,
map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
&CheckProductItemsDataParams{
&SetProductItemsDataParams{
MultiBoxQuantity: 0,
PostingNumber: "1234",
Products: []CheckProductItemsDataProduct{
Products: []SetProductItemsDataProduct{
{
Exemplars: []CheckProductItemsDataProductExemplar{
Exemplars: []SetProductItemsDataProductExemplar{
{
ExemplarId: 1,
GTD: "string",
IsGTDAbsent: true,
IsRNPTAbsent: true,
MandatoryMark: "string",
RNPT: "string",
JWUIN: "string",
ExemplarId: 1,
GTD: "string",
IsGTDAbsent: true,
RNPT: "string",
},
},
IsGTDNeeded: true,
IsMandatoryMarkNeeded: true,
IsRNPTNeeded: true,
ProductId: 22,
Quantity: 11,
ProductId: 22,
},
},
},
`{
"result": true
"code": 0,
"details": [
{
"typeUrl": "string",
"value": "string"
}
],
"message": "string"
}`,
},
// Test No Client-Id or Api-Key
{
http.StatusUnauthorized,
map[string]string{},
&CheckProductItemsDataParams{},
&SetProductItemsDataParams{},
`{
"code": 16,
"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))
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 {
t.Error(err)
continue
}
compareJsonResponse(t, test.response, &CheckProductItemsDataResponse{})
compareJsonResponse(t, test.response, &SetProductItemsDataResponse{})
if 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",
"products": [
{
"product_id": 476925391,
"exemplars": [
{
"mandatory_mark": "010290000151642731tVMohkbfFgunB",
"gtd": "",
"exemplar_id": 0,
"gtd": "string",
"gtd_check_status": "string",
"gtd_error_codes": [
"string"
],
"is_gtd_absent": true,
"mandatory_mark_check_status": "passed",
"mandatory_mark_error_codes": [],
"gtd_check_status": "passed",
"gtd_error_codes": []
"is_rnpt_absent": true,
"marks": [
{
"check_status": "string",
"error_codes": [
"string"
],
"mark": "string",
"mark_type": "string"
}
],
"rnpt": "string",
"rnpt_check_status": "string",
"rnpt_error_codes": [
"string"
]
}
]
],
"product_id": 123
}
],
"status": "ship_available"
"status": "string"
}`,
},
// Test No Client-Id or Api-Key
@@ -1526,8 +1565,8 @@ func TestGetProductItemsCheckStatuses(t *testing.T) {
if resp.Products[0].ProductId == 0 {
t.Errorf("Product id cannot be 0")
}
if len(resp.Products[0].Exemplars) > 0 {
if resp.Products[0].Exemplars[0].MandatoryMark == "" {
if len(resp.Products[0].Exemplars) > 0 && len(resp.Products[0].Exemplars[0].Marks) > 0 {
if resp.Products[0].Exemplars[0].Marks[0].Mark == "" {
t.Errorf("Mandatory mark cannot be empty")
}
}
@@ -2877,13 +2916,19 @@ func TestCreateOrGetProductExemplar(t *testing.T) {
"gtd": "string",
"is_gtd_absent": true,
"is_rnpt_absent": true,
"mandatory_mark": "string",
"rnpt": "string",
"jw_uin": "string"
"marks": [
{
"mark": "string",
"mark_type": "string"
}
],
"rnpt": "string"
}
],
"is_gtd_needed": true,
"is_jw_uin_needed": true,
"is_mandatory_mark_needed": true,
"is_mandatory_mark_possible": true,
"is_rnpt_needed": true,
"product_id": 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)
}
}
}

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Finance struct {
@@ -362,11 +362,7 @@ type ListTransactionsResultOperationItem struct {
}
type ListTransactionsResultOperationPosting struct {
// Delivery scheme:
// - FBO — delivery to Ozon warehouse
// - FBS — delivery from seller's warehouse
// - RFBS — delivery service of seller's choice
// - Crossborder — delivery from abroad
// Delivery scheme
DeliverySchema string `json:"delivery_schema"`
// Date the product was accepted for processing

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestReportOnSoldProducts(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Invoices struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestCreateUpdateProformaLink(t *testing.T) {

View File

@@ -11,7 +11,7 @@ import (
"testing"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type testData struct {

View File

@@ -3,7 +3,7 @@ package ozon
import (
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
const (

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Passes struct {

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListPasses(t *testing.T) {

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Polygons struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestCreateDeliveryPolygon(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Products struct {
@@ -106,157 +106,41 @@ func (c Products) GetStocksInfo(ctx context.Context, params *GetStocksInfoParams
}
type ProductDetails struct {
// All product 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"`
// Commission fees details
Commissions []ProductDetailCommission `json:"commissions"`
// Date and time when the product was created
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"`
// The price of the product including all promotion discounts. This value will be shown on the Ozon storefront
MarketingPrice string `json:"marketing_price"`
// Minimum price for similar products on Ozon.
//
// The field is deprecated. Returns an empty string ""
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"`
// 'true' if the item is archived automatically.
IsArchivedAuto bool `json:"is_autoarchived"`
// 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"`
Barcodes []string `json:"barcodes"`
ColorImage []string `json:"color_image"`
Commissions []ProductDetailCommission `json:"commissions"`
CreatedAt time.Time `json:"created_at"`
CurrencyCode string `json:"currency_code"`
DescriptionCategoryId int64 `json:"description_category_id"`
DiscountedFBOStocks int32 `json:"discounted_fbo_stocks"`
Errors []ProductDetailsError `json:"errors"`
HasDiscountedFBOItem bool `json:"has_discounted_fbo_item"`
Id int64 `json:"id"`
Images []string `json:"images"`
Images360 []string `json:"images360"`
IsArchived bool `json:"is_archived"`
IsAutoarchived bool `json:"is_autoarchived"`
IsDiscounted bool `json:"is_discounted"`
IsKGT bool `json:"is_kgt"`
IsPrepaymentAllowed bool `json:"is_prepayment_allowed"`
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 {
@@ -306,32 +190,15 @@ type NameValue struct {
}
type ProductDetailsStatus struct {
// true, if the product is created correctly
IsCreated bool `json:"is_created"`
// Moderation status
ModerateStatus string `json:"moderate_status"`
// Product status
Status string `json:"status"`
// Product status description
Description string `json:"status_description"`
// Status of the product where the error occurred
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"`
IsCreated bool `json:"is_created"`
ModerateStatus string `json:"moderate_status"`
Status string `json:"status"`
StatusDescription string `json:"status_description"`
StatusFailed string `json:"status_failed"`
StatusName string `json:"status_name"`
StatusTooltip string `json:"status_tooltip"`
StatusUpdatedAt time.Time `json:"status_updated_at"`
ValidationStatus string `json:"validation_status"`
}
type ProductDetailsModelInfo struct {
@@ -445,58 +312,28 @@ type ProductDetailStatus struct {
}
type ProductDetailSource struct {
// Product creation date
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"`
CreatedAt time.Time `json:"created_at"`
QuantCode string `json:"quant_code"`
ShipmentType string `json:"shipment_type"`
SKU int64 `json:"sku"`
Source string `json:"source"`
}
type ProductDetailStock struct {
// true, if there are stocks at the warehouses
HasStock bool `json:"has_stock"`
// Status of product stocks
Stocks []ProductDetailStockStock `json:"stocks"`
HasStock bool `json:"has_stock"`
Stocks []ProductDetailStockStock `json:"stocks"`
}
type ProductDetailStockStock struct {
// Product identifier in the Ozon system, SKU
SKU int64 `json:"sku"`
// Currently at the warehouse
Present int32 `json:"present"`
// Reserved
Reserved int32 `json:"reserved"`
// Sales scheme
Source string `json:"source"`
Present int32 `json:"present"`
Reserved int32 `json:"reserved"`
SKU int64 `json:"sku"`
Source string `json:"source"`
}
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"`
// If there is stock at the warehouses, the value is true
HasStock bool `json:"has_stock"`
// Reason why the product is hidden
Reasons map[string]interface{} `json:"reasons"`
}
type ProductDiscountedStocks struct {
@@ -758,6 +595,9 @@ type UpdatePricesPrice struct {
// Minimum product price with all promotions applied
MinPrice string `json:"min_price"`
// Product cost price
NetPrice string `json:"net_price"`
// Product identifier in the seller's system
OfferId string `json:"offer_id"`
@@ -866,7 +706,7 @@ type CreateOrUpdateProductItem struct {
DescriptionCategoryId int64 `json:"description_category_id"`
// 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.
//
@@ -996,7 +836,7 @@ type CreateOrUpdateProductPDF struct {
Name string `json:"name"`
// File address
URL string `json:"url"`
SrcUrl string `json:"src_url"`
}
type CreateOrUpdateProductResponse struct {
@@ -1564,6 +1404,9 @@ type GetDescriptionOfProductResult struct {
// Barcode
Barcode string `json:"barcode"`
// All product's barcodes
Barcodes []string `json:"barcodes"`
// Category identifier
DescriptionCategoryId int64 `json:"description_category_id"`
@@ -1589,7 +1432,10 @@ type GetDescriptionOfProductResult struct {
Id int64 `json:"id"`
// 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
Images360 []GetDescriptionOfProductResultImage360 `json:"images360"`
@@ -1603,6 +1449,12 @@ type GetDescriptionOfProductResult struct {
// Array of PDF files
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
TypeId int64 `json:"type_id"`
@@ -1616,9 +1468,17 @@ type GetDescriptionOfProductResult struct {
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 {
// Characteristic identifier
AttributeId int64 `json:"attribute_id"`
AttributeId int64 `json:"id"`
// Identifier of the characteristic that supports nested properties.
// For example, the "Processor" characteristic has nested characteristics "Manufacturer" and "L2 Cache".
@@ -1663,12 +1523,6 @@ type GetDescriptionOfProductResultComplexAttrValue struct {
Value string `json:"value"`
}
type GetDescriptionOfProductResultImage struct {
Default bool `json:"default"`
FileName string `json:"file_name"`
Index int64 `json:"index"`
}
type GetDescriptionOfProductResultImage360 struct {
FileName string `json:"file_name"`
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`
func (c Products) GetDescriptionOfProduct(ctx context.Context, params *GetDescriptionOfProductParams) (*GetDescriptionOfProductResponse, error) {
url := "/v3/products/info/attributes"
url := "/v4/product/info/attributes"
resp := &GetDescriptionOfProductResponse{}
@@ -1741,8 +1595,7 @@ type GetDescriptionOfProductsResult struct {
// new "model_info" structure
ModelInfo *ModelInfo `json:"model_info,omitempty"`
Images []string `json:"images"`
PDFList []string `json:"pdf_list"`
Images []string `json:"images"`
Attributes []GetDescriptionOfProductsAttribute `json:"attributes"`
ComplexAttributes []GetDescriptionOfProductsComplexAttribute `json:"complex_attributes"`
@@ -2113,10 +1966,6 @@ type GetProductPriceInfoFilter struct {
type GetProductPriceInfoResponse struct {
core.CommonResponse
Result GetProductPriceInfoResult `json:"result"`
}
type GetProductPriceInfoResult struct {
// Products list
Items []GetProductPriceInfoResultItem `json:"items"`
@@ -2129,7 +1978,7 @@ type GetProductPriceInfoResult struct {
type GetProductPriceInfoResultItem struct {
// Maximum acquiring fee
Acquiring int32 `json:"acquiring"`
Acquiring float64 `json:"acquiring"`
// Commissions information
Commissions GetProductPriceInfoResultItemCommission `json:"commissions"`

View File

@@ -7,7 +7,7 @@ import (
"testing"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetStocksInfo(t *testing.T) {
@@ -1370,37 +1370,33 @@ func TestGetDescriptionOfProduct(t *testing.T) {
{
"id": 213761435,
"barcode": "",
"description_category_id": 17038062,
"barcodes": [
"123124123",
"123342455"
],
"name": "Пленка защитная для Xiaomi Redmi Note 10 Pro 5G",
"offer_id": "21470",
"type_id": 124572394,
"height": 10,
"depth": 210,
"width": 140,
"dimension_unit": "mm",
"weight": 50,
"weight_unit": "g",
"primary_image": "https://cdn1.ozone.ru/s3/multimedia-4/6804736960.jpg",
"sku": 423434534,
"model_info": {
"model_id": 43445453,
"count": 4
},
"images": [
{
"file_name": "https://cdn1.ozone.ru/s3/multimedia-f/6190456071.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
}
"https://cdn1.ozone.ru/s3/multimedia-4/6804736960.jpg",
"https://cdn1.ozone.ru/s3/multimedia-j/6835412647.jpg"
],
"images360": [],
"pdf_list": [],
"attributes": [
{
"attribute_id": 5219,
"id": 5219,
"complex_id": 0,
"values": [
{
@@ -1410,7 +1406,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 11051,
"id": 11051,
"complex_id": 0,
"values": [
{
@@ -1420,7 +1416,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 10100,
"id": 10100,
"complex_id": 0,
"values": [
{
@@ -1430,7 +1426,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 11794,
"id": 11794,
"complex_id": 0,
"values": [
{
@@ -1440,7 +1436,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 9048,
"id": 9048,
"complex_id": 0,
"values": [
{
@@ -1450,7 +1446,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 5076,
"id": 5076,
"complex_id": 0,
"values": [
{
@@ -1460,7 +1456,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 9024,
"id": 9024,
"complex_id": 0,
"values": [
{
@@ -1470,7 +1466,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 10015,
"id": 10015,
"complex_id": 0,
"values": [
{
@@ -1480,7 +1476,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 85,
"id": 85,
"complex_id": 0,
"values": [
{
@@ -1490,7 +1486,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 9461,
"id": 9461,
"complex_id": 0,
"values": [
{
@@ -1500,7 +1496,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 4180,
"id": 4180,
"complex_id": 0,
"values": [
{
@@ -1510,7 +1506,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 4191,
"id": 4191,
"complex_id": 0,
"values": [
{
@@ -1520,7 +1516,7 @@ func TestGetDescriptionOfProduct(t *testing.T) {
]
},
{
"attribute_id": 8229,
"id": 8229,
"complex_id": 0,
"values": [
{
@@ -1531,7 +1527,8 @@ func TestGetDescriptionOfProduct(t *testing.T) {
}
],
"complex_attributes": [],
"color_image": ""
"color_image": "",
"description_category_id": 71107562
}
],
"total": 1,
@@ -2158,74 +2155,72 @@ func TestGetProductPriceInfo(t *testing.T) {
},
},
`{
"result": {
"cursor": "string",
"items": [
{
"acquiring": 0,
"commissions": {
"fbo_deliv_to_customer_amount": 14.75,
"fbo_direct_flow_trans_max_amount": 46.5,
"fbo_direct_flow_trans_min_amount": 31,
"fbo_return_flow_amount": 50,
"fbs_deliv_to_customer_amount": 60,
"fbs_direct_flow_trans_max_amount": 61.5,
"fbs_direct_flow_trans_min_amount": 41,
"fbs_first_mile_max_amount": 25,
"fbs_first_mile_min_amount": 0,
"fbs_return_flow_amount": 40,
"sales_percent_fbo": 15,
"sales_percent_fbs": 0
},
"marketing_actions": {
"actions": [
{
"date_from": "2024-12-13T06:49:37.591Z",
"date_to": "2024-12-13T06:49:37.591Z",
"title": "string",
"value": 0
}
],
"current_period_from": "2024-12-13T06:49:37.591Z",
"current_period_to": "2024-12-13T06:49:37.591Z",
"ozon_actions_exist": true
},
"offer_id": "356792",
"price": {
"auto_action_enabled": true,
"currency_code": "RUB",
"marketing_price": 0,
"marketing_seller_price": 0,
"min_price": 0,
"old_price": 579,
"price": 499,
"retail_price": 0,
"vat": 0.2
},
"price_indexes": {
"color_index": "WITHOUT_INDEX",
"external_index_data": {
"min_price": 0,
"min_price_currency": "string",
"price_index_value": 0
},
"ozon_index_data": {
"min_price": 0,
"min_price_currency": "string",
"price_index_value": 0
},
"self_marketplaces_index_data": {
"min_price": 0,
"min_price_currency": "string",
"price_index_value": 0
"cursor": "string",
"items": [
{
"acquiring": 0.5,
"commissions": {
"fbo_deliv_to_customer_amount": 14.75,
"fbo_direct_flow_trans_max_amount": 46.5,
"fbo_direct_flow_trans_min_amount": 31,
"fbo_return_flow_amount": 50,
"fbs_deliv_to_customer_amount": 60,
"fbs_direct_flow_trans_max_amount": 61.5,
"fbs_direct_flow_trans_min_amount": 41,
"fbs_first_mile_max_amount": 25,
"fbs_first_mile_min_amount": 0,
"fbs_return_flow_amount": 40,
"sales_percent_fbo": 15,
"sales_percent_fbs": 0
},
"marketing_actions": {
"actions": [
{
"date_from": "2024-12-13T06:49:37.591Z",
"date_to": "2024-12-13T06:49:37.591Z",
"title": "string",
"value": 0
}
},
"product_id": 243686911,
"volume_weight": 0
],
"current_period_from": "2024-12-13T06:49:37.591Z",
"current_period_to": "2024-12-13T06:49:37.591Z",
"ozon_actions_exist": true
},
"offer_id": "356792",
"price": {
"auto_action_enabled": true,
"currency_code": "RUB",
"marketing_price": 0,
"marketing_seller_price": 0,
"min_price": 0,
"old_price": 579,
"price": 499,
"retail_price": 0,
"vat": 0.2
},
"price_indexes": {
"color_index": "WITHOUT_INDEX",
"external_index_data": {
"min_price": 0,
"min_price_currency": "string",
"price_index_value": 0
},
"ozon_index_data": {
"min_price": 0,
"min_price_currency": "string",
"price_index_value": 0
},
"self_marketplaces_index_data": {
"min_price": 0,
"min_price_currency": "string",
"price_index_value": 0
}
],
"total": 0
},
"product_id": 243686911,
"volume_weight": 0
}
],
"total": 0
}`,
},
// Test No Client-Id or Api-Key

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Promotions struct {
@@ -297,196 +297,6 @@ func (c Promotions) RemoveProduct(ctx context.Context, params *RemoveProductFrom
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 {
// Discount request status
Status ListDiscountRequestsStatus `json:"status" default:"UNKNOWN"`

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
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) {
t.Parallel()

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Quants struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListQuants(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Rating struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetCurrentRatingInfo(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Reports struct {
@@ -480,6 +480,10 @@ type GetReturnsReportsFilter struct {
type GetReturnsReportResponse struct {
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.
Code string `json:"code"`
}

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetList(t *testing.T) {
@@ -380,7 +380,9 @@ func TestGetReturnsReport(t *testing.T) {
},
},
`{
"code": "REPORT_seller_products_924336_1720170405_a9ea2f27-a473-4b13-99f9-d0cfcb5b1a69"
"result": {
"code": "REPORT_seller_products_924336_1720170405_a9ea2f27-a473-4b13-99f9-d0cfcb5b1a69"
}
}`,
},
// Test No Client-Id or Api-Key

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Returns struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetRFBSReturns(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Reviews struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestLeaveComment(t *testing.T) {

View File

@@ -4,7 +4,7 @@ import (
"context"
"net/http"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Strategies struct {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestListCompetitors(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"time"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
type Warehouses struct {
@@ -88,7 +88,8 @@ type GetListOfWarehousesResultFirstMile struct {
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) {
url := "/v1/warehouse/list"

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"testing"
core "github.com/diphantxm/ozon-api-client"
core "git.denco.store/fakz9/ozon-api-client"
)
func TestGetListOfWarehouses(t *testing.T) {