Compare commits
	
		
			15 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					23ca98fedd | ||
| 
						 | 
					eae6f54e71 | ||
| 
						 | 
					8a6cd20b95 | ||
| 
						 | 
					1706575a34 | ||
| 
						 | 
					3430ead143 | ||
| 
						 | 
					2164eff0a6 | ||
| 
						 | 
					b6af642636 | ||
| 
						 | 
					67898a4738 | ||
| 
						 | 
					8c07540d28 | ||
| 
						 | 
					7c0e18681b | ||
| 
						 | 
					895ef8be52 | ||
| 
						 | 
					ccd3610c76 | ||
| 
						 | 
					090b2afb63 | ||
| 
						 | 
					823386edf2 | ||
| 
						 | 
					5ecf131061 | 
@@ -4,6 +4,7 @@
 | 
				
			|||||||
- [x] Product category tree
 | 
					- [x] Product category tree
 | 
				
			||||||
- [x] Category characteristics list
 | 
					- [x] Category characteristics list
 | 
				
			||||||
- [x] Characteristics value directory
 | 
					- [x] Characteristics value directory
 | 
				
			||||||
 | 
					- [x] Search characteristics value directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Uploading and updating products
 | 
					## Uploading and updating products
 | 
				
			||||||
- [x] Create or update a product
 | 
					- [x] Create or update a product
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -200,6 +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
 | 
					// Report on stocks and products movement at Ozon warehouses
 | 
				
			||||||
@@ -216,3 +219,54 @@ func (c Analytics) GetStocksOnWarehouses(ctx context.Context, params *GetStocksO
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return resp, nil
 | 
						return resp, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GetProductTurnoverParams struct {
 | 
				
			||||||
 | 
						// Number of values in the response
 | 
				
			||||||
 | 
						Limit int64 `json:"limit"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number of elements to skip in the response.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// For example, if offset = 10, the response starts with the 11th element found
 | 
				
			||||||
 | 
						Offset int32 `json:"offset"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product identifiers in the Ozon system, SKU
 | 
				
			||||||
 | 
						SKU []string `json:"sku"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GetProductTurnoverResponse struct {
 | 
				
			||||||
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Products
 | 
				
			||||||
 | 
						Items []ProductTurnoverItem `json:"items"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ProductTurnoverItem struct {
 | 
				
			||||||
 | 
						// Average daily number of product items sold over the last 60 days
 | 
				
			||||||
 | 
						Ads float64 `json:"ads"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product stock, pcs
 | 
				
			||||||
 | 
						CurrentStock int64 `json:"current_stock"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number of days the stock will last based on your average daily sales
 | 
				
			||||||
 | 
						IDC float64 `json:"idc"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product stock level
 | 
				
			||||||
 | 
						IDCGrade string `json:"idc_grade"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Use the method to get the product turnover rate and the number of days the current stock will last.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If you request a list of products by sku, the limit and offset parameters are optional.
 | 
				
			||||||
 | 
					func (c Analytics) GetProductTurnover(ctx context.Context, params *GetProductTurnoverParams) (*GetProductTurnoverResponse, error) {
 | 
				
			||||||
 | 
						url := "/v1/analytics/turnover/stocks"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := &GetProductTurnoverResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,3 +145,67 @@ func TestGetStocksOnWarehouses(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetProductTurnover(t *testing.T) {
 | 
				
			||||||
 | 
						t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							statusCode int
 | 
				
			||||||
 | 
							headers    map[string]string
 | 
				
			||||||
 | 
							params     *GetProductTurnoverParams
 | 
				
			||||||
 | 
							response   string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							// Test Ok
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusOK,
 | 
				
			||||||
 | 
								map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
 | 
				
			||||||
 | 
								&GetProductTurnoverParams{
 | 
				
			||||||
 | 
									Limit: 1,
 | 
				
			||||||
 | 
									SKU:   []string{"string"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"items": [
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"ads": 0,
 | 
				
			||||||
 | 
										"current_stock": 0,
 | 
				
			||||||
 | 
										"idc": 0,
 | 
				
			||||||
 | 
										"idc_grade": "GRADES_NONE"
 | 
				
			||||||
 | 
									  }
 | 
				
			||||||
 | 
									]
 | 
				
			||||||
 | 
								}`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Test No Client-Id or Api-Key
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusUnauthorized,
 | 
				
			||||||
 | 
								map[string]string{},
 | 
				
			||||||
 | 
								&GetProductTurnoverParams{},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"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().GetProductTurnover(ctx, test.params)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compareJsonResponse(t, test.response, &GetProductTurnoverResponse{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode != test.statusCode {
 | 
				
			||||||
 | 
								t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode == http.StatusOK {
 | 
				
			||||||
 | 
								if len(resp.Items) > int(test.params.Limit) {
 | 
				
			||||||
 | 
									t.Errorf("Length of items is bigger than limit")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -224,3 +224,63 @@ func (c *Categories) AttributesDictionary(ctx context.Context, params *GetAttrib
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return resp, nil
 | 
						return resp, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SearchAttributeDictionaryParams struct {
 | 
				
			||||||
 | 
						// Characteristics identifier
 | 
				
			||||||
 | 
						AttributeId int64 `json:"attribute_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Category identifier
 | 
				
			||||||
 | 
						DescriptionCategoryId int64 `json:"description_category_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The value to be searched for
 | 
				
			||||||
 | 
						//  - minimum—2 characters
 | 
				
			||||||
 | 
						Value string `json:"value"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number of values in the response:
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 	- maximum—100,
 | 
				
			||||||
 | 
						// 	- minimum—1.
 | 
				
			||||||
 | 
						Limit int64 `json:"limit,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product type identifier
 | 
				
			||||||
 | 
						TypeId int64 `json:"type_id"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SearchAttributeDictionaryResponse struct {
 | 
				
			||||||
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Characteristic values
 | 
				
			||||||
 | 
						Result []SearchAttributeDictionaryResult `json:"result"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SearchAttributeDictionaryResult struct {
 | 
				
			||||||
 | 
						// Characteristic value identifier
 | 
				
			||||||
 | 
						Id int64 `json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Additional description
 | 
				
			||||||
 | 
						Info string `json:"info"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Image link
 | 
				
			||||||
 | 
						Picture string `json:"picture"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product characteristic value
 | 
				
			||||||
 | 
						Value string `json:"value"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns found characteristics value directory.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// To check if an attribute has a nested directory,
 | 
				
			||||||
 | 
					// use the `/v1/description-category/attribute` method.
 | 
				
			||||||
 | 
					func (c *Categories) SearchAttributesDictionary(ctx context.Context, params *SearchAttributeDictionaryParams) (*SearchAttributeDictionaryResponse, error) {
 | 
				
			||||||
 | 
						url := "/v1/description-category/attribute/values/search"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := &SearchAttributeDictionaryResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,3 +203,71 @@ func TestGetAttributeDictionary(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSearchAttributeDictionary(t *testing.T) {
 | 
				
			||||||
 | 
						t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							statusCode int
 | 
				
			||||||
 | 
							headers    map[string]string
 | 
				
			||||||
 | 
							params     *SearchAttributeDictionaryParams
 | 
				
			||||||
 | 
							response   string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							// Test Ok
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusOK,
 | 
				
			||||||
 | 
								map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
 | 
				
			||||||
 | 
								&SearchAttributeDictionaryParams{
 | 
				
			||||||
 | 
									AttributeId:           123456,
 | 
				
			||||||
 | 
									DescriptionCategoryId: 12,
 | 
				
			||||||
 | 
									Value:                 "34",
 | 
				
			||||||
 | 
									Limit:                 5,
 | 
				
			||||||
 | 
									TypeId:                6,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"has_next": true,
 | 
				
			||||||
 | 
									"result": [
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"id": 0,
 | 
				
			||||||
 | 
										"info": "string",
 | 
				
			||||||
 | 
										"picture": "string",
 | 
				
			||||||
 | 
										"value": "string"
 | 
				
			||||||
 | 
									  }
 | 
				
			||||||
 | 
									]
 | 
				
			||||||
 | 
								}`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Test No Client-Id or Api-Key
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusUnauthorized,
 | 
				
			||||||
 | 
								map[string]string{},
 | 
				
			||||||
 | 
								&SearchAttributeDictionaryParams{},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"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.Categories().SearchAttributesDictionary(ctx, test.params)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compareJsonResponse(t, test.response, &GetAttributeDictionaryResponse{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode != test.statusCode {
 | 
				
			||||||
 | 
								t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode == http.StatusOK {
 | 
				
			||||||
 | 
								if len(resp.Result) > int(test.params.Limit) {
 | 
				
			||||||
 | 
									t.Errorf("Length of response result is bigger than limit")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ type ListChatsResponse struct {
 | 
				
			|||||||
	core.CommonResponse
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Chats data
 | 
						// Chats data
 | 
				
			||||||
	Chats []ListChatsChat `json:"chats"`
 | 
						Chats []ListChatsChatData `json:"chats"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Total number of chats
 | 
						// Total number of chats
 | 
				
			||||||
	TotalChatsCount int64 `json:"total_chats_count"`
 | 
						TotalChatsCount int64 `json:"total_chats_count"`
 | 
				
			||||||
@@ -48,20 +48,6 @@ type ListChatsResponse struct {
 | 
				
			|||||||
	TotalUnreadCount int64 `json:"total_unread_count"`
 | 
						TotalUnreadCount int64 `json:"total_unread_count"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ListChatsChat struct {
 | 
					 | 
				
			||||||
	// Chat data
 | 
					 | 
				
			||||||
	Chat ListChatsChatData `json:"chat"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Identifier of the first unread chat message
 | 
					 | 
				
			||||||
	FirstUnreadMessageId string `json:"first_unread_message_id"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Identifier of the last message in the chat
 | 
					 | 
				
			||||||
	LastMessageId string `json:"last_message_id"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Number of unread messages in the chat
 | 
					 | 
				
			||||||
	UnreadCount int64 `json:"unread_count"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ListChatsChatData struct {
 | 
					type ListChatsChatData struct {
 | 
				
			||||||
	// Chat identifier
 | 
						// Chat identifier
 | 
				
			||||||
	ChatId string `json:"chat_id"`
 | 
						ChatId string `json:"chat_id"`
 | 
				
			||||||
@@ -79,6 +65,15 @@ type ListChatsChatData struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Chat creation date
 | 
						// Chat creation date
 | 
				
			||||||
	CreatedAt time.Time `json:"created_at"`
 | 
						CreatedAt time.Time `json:"created_at"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Identifier of the first unread chat message
 | 
				
			||||||
 | 
						FirstUnreadMessageId uint64 `json:"first_unread_message_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Identifier of the last message in the chat
 | 
				
			||||||
 | 
						LastMessageId uint64 `json:"last_message_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number of unread messages in the chat
 | 
				
			||||||
 | 
						UnreadCount int64 `json:"unread_count"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Returns information about chats by specified filters
 | 
					// Returns information about chats by specified filters
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,15 +32,13 @@ func TestListChats(t *testing.T) {
 | 
				
			|||||||
			`{
 | 
								`{
 | 
				
			||||||
				"chats": [
 | 
									"chats": [
 | 
				
			||||||
				  {
 | 
									  {
 | 
				
			||||||
					"chat": {
 | 
					 | 
				
			||||||
					  "created_at": "2022-07-22T08:07:19.581Z",
 | 
					 | 
				
			||||||
            "chat_id": "5e767w03-b400-4y1b-a841-75319ca8a5c8",
 | 
					            "chat_id": "5e767w03-b400-4y1b-a841-75319ca8a5c8",
 | 
				
			||||||
            "chat_status": "Opened",
 | 
					            "chat_status": "Opened",
 | 
				
			||||||
					  "chat_type": "Seller_Support"
 | 
					            "chat_type": "Seller_Support",
 | 
				
			||||||
					},
 | 
					            "created_at": "2022-07-22T08:07:19.581Z",
 | 
				
			||||||
					"first_unread_message_id": "3000000000118021931",
 | 
					            "unread_count": 1,
 | 
				
			||||||
					"last_message_id": "30000000001280042740",
 | 
					            "last_message_id": 3000000000128004274,
 | 
				
			||||||
					"unread_count": 1
 | 
					            "first_unread_message_id": 3000000000118021931
 | 
				
			||||||
				  }
 | 
									  }
 | 
				
			||||||
				],
 | 
									],
 | 
				
			||||||
				"total_chats_count": 25,
 | 
									"total_chats_count": 25,
 | 
				
			||||||
@@ -77,10 +75,10 @@ func TestListChats(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if resp.StatusCode == http.StatusOK {
 | 
							if resp.StatusCode == http.StatusOK {
 | 
				
			||||||
			if len(resp.Chats) > 0 {
 | 
								if len(resp.Chats) > 0 {
 | 
				
			||||||
				if resp.Chats[0].Chat.ChatStatus == "" {
 | 
									if resp.Chats[0].ChatStatus == "" {
 | 
				
			||||||
					t.Errorf("Chat status cannot be empty")
 | 
										t.Errorf("Chat status cannot be empty")
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if resp.Chats[0].Chat.ChatType == "" {
 | 
									if resp.Chats[0].ChatType == "" {
 | 
				
			||||||
					t.Errorf("Chat type cannot be empty")
 | 
										t.Errorf("Chat type cannot be empty")
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										131
									
								
								ozon/common.go
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								ozon/common.go
									
									
									
									
									
								
							@@ -126,24 +126,6 @@ const (
 | 
				
			|||||||
type SupplyRequestState string
 | 
					type SupplyRequestState string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// request draft. Only for supplies via vDC
 | 
					 | 
				
			||||||
	Draft SupplyRequestState = "DRAFT"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// selecting supply options. Only for supplies via vDC
 | 
					 | 
				
			||||||
	SupplyVariantsArranging SupplyRequestState = "SUPPLY_VARIANTS_ARRANGING"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// no supply options, the request is archived. Only for supplies via vDC
 | 
					 | 
				
			||||||
	HasNoSupplyVariantsArchive SupplyRequestState = "HAS_NO_SUPPLY_VARIANTS_ARCHIVE"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// no supply options. Only for supplies via vDC
 | 
					 | 
				
			||||||
	HasNoSupplyVariantsNew SupplyRequestState = "HAS_NO_SUPPLY_VARIANTS_NEW"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// supply being approved. Only for supplies via vDC
 | 
					 | 
				
			||||||
	SupplyVariantsConfirmation SupplyRequestState = "SUPPLY_VARIANTS_CONFIRMATION"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// time reservation
 | 
					 | 
				
			||||||
	TimeslotBooking SupplyRequestState = "TIMESLOT_BOOKING"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// filling in the data
 | 
						// filling in the data
 | 
				
			||||||
	DATA_FILLING SupplyRequestState = "DATA_FILLING"
 | 
						DATA_FILLING SupplyRequestState = "DATA_FILLING"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -471,6 +453,8 @@ const (
 | 
				
			|||||||
	ReadyForShipment          GetFBSReturnsFilterStatus = "ready_for_shipment"
 | 
						ReadyForShipment          GetFBSReturnsFilterStatus = "ready_for_shipment"
 | 
				
			||||||
	Disposing                 GetFBSReturnsFilterStatus = "disposing"
 | 
						Disposing                 GetFBSReturnsFilterStatus = "disposing"
 | 
				
			||||||
	Disposed                  GetFBSReturnsFilterStatus = "disposed"
 | 
						Disposed                  GetFBSReturnsFilterStatus = "disposed"
 | 
				
			||||||
 | 
						ArrivedForResale          GetFBSReturnsFilterStatus = "arrived_for_resale"
 | 
				
			||||||
 | 
						MovingToResale            GetFBSReturnsFilterStatus = "moving_to_resale"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GetFBOReturnsFilterStatus string
 | 
					type GetFBOReturnsFilterStatus string
 | 
				
			||||||
@@ -740,6 +724,8 @@ const (
 | 
				
			|||||||
	// picking up products for removal by the seller
 | 
						// picking up products for removal by the seller
 | 
				
			||||||
	TransactionServiceReturnFromStock TransactionOperationService = "MarketplaceServiceItemReturnFromStock"
 | 
						TransactionServiceReturnFromStock TransactionOperationService = "MarketplaceServiceItemReturnFromStock"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TransactionServiceStarsMembership TransactionOperationService = "ItemAgentServiceStarsMembership"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// forwarding trade
 | 
						// forwarding trade
 | 
				
			||||||
	TransactionItemAdForSupplierLogisticSeller TransactionOperationService = "ItemAdvertisementForSupplierLogisticSeller"
 | 
						TransactionItemAdForSupplierLogisticSeller TransactionOperationService = "ItemAdvertisementForSupplierLogisticSeller"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -808,6 +794,9 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// reissue of returns at the pick-up point
 | 
						// reissue of returns at the pick-up point
 | 
				
			||||||
	TransactionServiceRedistributionReturnsPVZ TransactionOperationService = "MarketplaceServiceItemRedistributionReturnsPVZ"
 | 
						TransactionServiceRedistributionReturnsPVZ TransactionOperationService = "MarketplaceServiceItemRedistributionReturnsPVZ"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Agregator 3PL Globalagency service tariffication
 | 
				
			||||||
 | 
						TransactionServiceAgencyFeeAggregator3PLGlobal TransactionOperationService = "OperationMarketplaceAgencyFeeAggregator3PLGlobal"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PaymentTypeGroupName string
 | 
					type PaymentTypeGroupName string
 | 
				
			||||||
@@ -822,3 +811,109 @@ const (
 | 
				
			|||||||
	PaymentTypeGroupPaymentToCurrentAccount   PaymentTypeGroupName = "payment to current account"
 | 
						PaymentTypeGroupPaymentToCurrentAccount   PaymentTypeGroupName = "payment to current account"
 | 
				
			||||||
	PaymentTypeGroupSberpay                   PaymentTypeGroupName = "Sberpay"
 | 
						PaymentTypeGroupSberpay                   PaymentTypeGroupName = "Sberpay"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type VisualStatus string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// dispute with the customer has been opened
 | 
				
			||||||
 | 
						VisualStatusDisputeOpened VisualStatus = "DisputeOpened"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pending with the seller
 | 
				
			||||||
 | 
						VisualStatusOnSellerApproval VisualStatus = "OnSellerApproval"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// at the pick-up point
 | 
				
			||||||
 | 
						VisualStatusArrivedAtReturnPlace VisualStatus = "ArrivedAtReturnPlace"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pending clarification by the seller
 | 
				
			||||||
 | 
						VisualStatusOnSellerClarification VisualStatus = "OnSellerClarification"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pending clarification by the seller after partial compensation
 | 
				
			||||||
 | 
						VisualStatusOnSellerClarificationPartial VisualStatus = "OnSellerClarificationAfterPartialCompensation"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// partial compensation offered
 | 
				
			||||||
 | 
						VisualStatusOfferedPartial VisualStatus = "OfferedPartialCompensation"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// refund approved
 | 
				
			||||||
 | 
						VisualStatusReturnMoneyApproved VisualStatus = "ReturnMoneyApproved"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// partial compensation provided
 | 
				
			||||||
 | 
						VisualStatusPartialReturned VisualStatus = "PartialCompensationReturned"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// refund rejected, dispute isn't opened
 | 
				
			||||||
 | 
						VisualStatusCancelledDisputeNotOpen VisualStatus = "CancelledDisputeNotOpen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// request rejected
 | 
				
			||||||
 | 
						VisualStatusRejected VisualStatus = "Rejected"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// request rejected by Ozon
 | 
				
			||||||
 | 
						VisualStatusCrmRejected VisualStatus = "CrmRejected"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// request canceled
 | 
				
			||||||
 | 
						VisualStatusCancelled VisualStatus = "Cancelled"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// request approved by the seller
 | 
				
			||||||
 | 
						VisualStatusApproved VisualStatus = "Approved"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// request approved by Ozon
 | 
				
			||||||
 | 
						VisualStatusApprovedByOzon VisualStatus = "ApprovedByOzon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// seller received the return
 | 
				
			||||||
 | 
						VisualStatusReceivedBySeller VisualStatus = "ReceivedBySeller"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// return is on its way to the seller
 | 
				
			||||||
 | 
						VisualStatusMovingToSeller VisualStatus = "MovingToSeller"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// seller received the refund
 | 
				
			||||||
 | 
						VisualStatusReturnCompensated VisualStatus = "ReturnCompensated"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// courier is taking the return to the seller
 | 
				
			||||||
 | 
						VisualStatusReturningByCourier VisualStatus = "ReturningByCourier"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// on disposal
 | 
				
			||||||
 | 
						VisualStatusUtilizing VisualStatus = "Utilizing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// disposed of
 | 
				
			||||||
 | 
						VisualStatusUtilized VisualStatus = "Utilized"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// customer received full refund
 | 
				
			||||||
 | 
						VisualStatusMoneyReturned VisualStatus = "MoneyReturned"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// partial refund has been approved
 | 
				
			||||||
 | 
						VisualStatusPartialInProcess VisualStatus = "PartialCompensationInProcess"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// seller opened a dispute
 | 
				
			||||||
 | 
						VisualStatusDisputeYouOpened VisualStatus = "DisputeYouOpened"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// compensation rejected
 | 
				
			||||||
 | 
						VisualStatusCompensationRejected VisualStatus = "CompensationRejected"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// support request sent
 | 
				
			||||||
 | 
						VisualStatusDisputeOpening VisualStatus = "DisputeOpening"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// awaiting your decision on compensation
 | 
				
			||||||
 | 
						VisualStatusCompensationOffered VisualStatus = "CompensationOffered"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// awaiting compensation
 | 
				
			||||||
 | 
						VisualStatusWaitingCompensation VisualStatus = "WaitingCompensation"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// an error occurred when sending the support request
 | 
				
			||||||
 | 
						VisualStatusSendingError VisualStatus = "SendingError"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// decision period has expired
 | 
				
			||||||
 | 
						VisualStatusCompensationRejectedBySla VisualStatus = "CompensationRejectedBySla"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// seller has refused compensation
 | 
				
			||||||
 | 
						VisualStatusCompensationRejectedBySeller VisualStatus = "CompensationRejectedBySeller"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// on the way to the Ozon warehouse
 | 
				
			||||||
 | 
						VisualStatusMovingToOzon VisualStatus = "MovingToOzon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// arrived at the Ozon warehouse
 | 
				
			||||||
 | 
						VisualStatusReturnedToOzon VisualStatus = "ReturnedToOzon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// quick refund
 | 
				
			||||||
 | 
						VisualStatusMoneyReturnedBySystem VisualStatus = "MoneyReturnedBySystem"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// awaiting shipping
 | 
				
			||||||
 | 
						VisualStatusWaitingShipment VisualStatus = "WaitingShipment"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										122
									
								
								ozon/fbs.go
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								ozon/fbs.go
									
									
									
									
									
								
							@@ -106,6 +106,9 @@ type FBSPosting struct {
 | 
				
			|||||||
	// Analytics data
 | 
						// Analytics data
 | 
				
			||||||
	AnalyticsData FBSPostingAnalyticsData `json:"analytics_data"`
 | 
						AnalyticsData FBSPostingAnalyticsData `json:"analytics_data"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Available actions and shipment information
 | 
				
			||||||
 | 
						AvailableActions []string `json:"available_actions"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Shipment barcodes
 | 
						// Shipment barcodes
 | 
				
			||||||
	Barcodes FBSBarcode `json:"barcodes"`
 | 
						Barcodes FBSBarcode `json:"barcodes"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -912,6 +915,9 @@ type GetShipmentDataByIdentifierResult struct {
 | 
				
			|||||||
	// Analytics data
 | 
						// Analytics data
 | 
				
			||||||
	AnalyticsData GetShipmentDataByIdentifierResultAnalyticsData `json:"analytics_data"`
 | 
						AnalyticsData GetShipmentDataByIdentifierResultAnalyticsData `json:"analytics_data"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Available actions and shipment information
 | 
				
			||||||
 | 
						AvailableActions []string `json:"available_actions"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Shipment barcodes
 | 
						// Shipment barcodes
 | 
				
			||||||
	Barcodes FBSBarcode `json:"barcodes"`
 | 
						Barcodes FBSBarcode `json:"barcodes"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3016,3 +3022,119 @@ func (c FBS) GetCarriage(ctx context.Context, params *GetCarriageParams) (*GetCa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return resp, nil
 | 
						return resp, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GetCancellationReasonsResponse struct {
 | 
				
			||||||
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Method result
 | 
				
			||||||
 | 
						Result []GetCancellationReasonsResult `json:"result"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GetCancellationReasonsResult struct {
 | 
				
			||||||
 | 
						// Cancellation reasons identifier
 | 
				
			||||||
 | 
						Id int64 `json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shipment cancellation result. true if the request is available for cancellation
 | 
				
			||||||
 | 
						IsAvailableForCancellation bool `json:"is_available_for_cancellation"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Category name
 | 
				
			||||||
 | 
						Title string `json:"title"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shipment cancellation initiator
 | 
				
			||||||
 | 
						TypeId string `json:"type_id"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c FBS) GetCancellationReasons(ctx context.Context) (*GetCancellationReasonsResponse, error) {
 | 
				
			||||||
 | 
						url := "/v1/posting/fbo/cancel-reason/list"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := &GetCancellationReasonsResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 SetShippingDateParams struct {
 | 
				
			||||||
 | 
						// New shipping date
 | 
				
			||||||
 | 
						NewCutoffDate time.Time `json:"new_cutoff_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shipment number
 | 
				
			||||||
 | 
						PostingNumber string `json:"posting_number"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SetShippingDateResponse struct {
 | 
				
			||||||
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// true if the new date is set
 | 
				
			||||||
 | 
						Result bool `json:"result"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c FBS) SetShippingDate(ctx context.Context, params *SetShippingDateParams) (*SetShippingDateResponse, error) {
 | 
				
			||||||
 | 
						url := "/v1/posting/cutoff/set"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := &SetShippingDateResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 SplitOrderParams struct {
 | 
				
			||||||
 | 
						// Shipment number
 | 
				
			||||||
 | 
						PostingNumber string `json:"posting_number"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shipments list the order will be split into. You can split one order per one request
 | 
				
			||||||
 | 
						Postings []SplitOrderParamPosting `json:"postings"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SplitOrderParamPosting struct {
 | 
				
			||||||
 | 
						Products []SplitOrderPostingProduct `json:"products"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SplitOrderResponse struct {
 | 
				
			||||||
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Original shipment details
 | 
				
			||||||
 | 
						ParentPosting SplitOrderPosting `json:"parent_posting"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// List of shipments the order was split into
 | 
				
			||||||
 | 
						Postings []SplitOrderPosting `json:"postings"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SplitOrderPosting struct {
 | 
				
			||||||
 | 
						// Shipment number
 | 
				
			||||||
 | 
						PostingNumber string `json:"posting_number"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// List of products in the shipment
 | 
				
			||||||
 | 
						Products []SplitOrderPostingProduct `json:"products"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SplitOrderPostingProduct struct {
 | 
				
			||||||
 | 
						// FBS product identifier in the Ozon system, SKU
 | 
				
			||||||
 | 
						ProductId int64 `json:"product_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product quantity
 | 
				
			||||||
 | 
						Quantity int64 `json:"quantity"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c FBS) SplitOrder(ctx context.Context, params *SplitOrderParams) (*SplitOrderResponse, error) {
 | 
				
			||||||
 | 
						url := "/v1/posting/fbs/split"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := &SplitOrderResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										199
									
								
								ozon/fbs_test.go
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								ozon/fbs_test.go
									
									
									
									
									
								
							@@ -3010,3 +3010,202 @@ func TestGetCarriage(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetCancellationReasons(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": [
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"id": 352,
 | 
				
			||||||
 | 
										"title": "The products ran out at the seller's warehouse",
 | 
				
			||||||
 | 
										"type_id": "seller",
 | 
				
			||||||
 | 
										"is_available_for_cancellation": true
 | 
				
			||||||
 | 
									  },
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"id": 401,
 | 
				
			||||||
 | 
										"title": "Seller rejects arbitration",
 | 
				
			||||||
 | 
										"type_id": "seller",
 | 
				
			||||||
 | 
										"is_available_for_cancellation": false
 | 
				
			||||||
 | 
									  },
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"id": 402,
 | 
				
			||||||
 | 
										"title": "Other (seller's fault)",
 | 
				
			||||||
 | 
										"type_id": "seller",
 | 
				
			||||||
 | 
										"is_available_for_cancellation": true
 | 
				
			||||||
 | 
									  },
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"id": 666,
 | 
				
			||||||
 | 
										"title": "Return from the delivery service: there is no delivery to the specified region",
 | 
				
			||||||
 | 
										"type_id": "seller",
 | 
				
			||||||
 | 
										"is_available_for_cancellation": false
 | 
				
			||||||
 | 
									  }
 | 
				
			||||||
 | 
									]
 | 
				
			||||||
 | 
								}`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// 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.FBS().GetCancellationReasons(ctx)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compareJsonResponse(t, test.response, &GetCancellationReasonsResponse{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode != test.statusCode {
 | 
				
			||||||
 | 
								t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSetShippingDate(t *testing.T) {
 | 
				
			||||||
 | 
						t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							statusCode int
 | 
				
			||||||
 | 
							headers    map[string]string
 | 
				
			||||||
 | 
							params     *SetShippingDateParams
 | 
				
			||||||
 | 
							response   string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							// Test Ok
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusOK,
 | 
				
			||||||
 | 
								map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
 | 
				
			||||||
 | 
								&SetShippingDateParams{
 | 
				
			||||||
 | 
									NewCutoffDate: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"result": true
 | 
				
			||||||
 | 
								}`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Test No Client-Id or Api-Key
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusUnauthorized,
 | 
				
			||||||
 | 
								map[string]string{},
 | 
				
			||||||
 | 
								&SetShippingDateParams{},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"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().SetShippingDate(ctx, test.params)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compareJsonResponse(t, test.response, &SetShippingDateResponse{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode != test.statusCode {
 | 
				
			||||||
 | 
								t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSplitOrder(t *testing.T) {
 | 
				
			||||||
 | 
						t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							statusCode int
 | 
				
			||||||
 | 
							headers    map[string]string
 | 
				
			||||||
 | 
							params     *SplitOrderParams
 | 
				
			||||||
 | 
							response   string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							// Test Ok
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusOK,
 | 
				
			||||||
 | 
								map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
 | 
				
			||||||
 | 
								&SplitOrderParams{
 | 
				
			||||||
 | 
									PostingNumber: "string",
 | 
				
			||||||
 | 
									Postings: []SplitOrderParamPosting{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Products: []SplitOrderPostingProduct{
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													ProductId: 1,
 | 
				
			||||||
 | 
													Quantity:  1,
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"parent_posting": {
 | 
				
			||||||
 | 
									  "posting_number": "string",
 | 
				
			||||||
 | 
									  "products": [
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
										  "product_id": 0,
 | 
				
			||||||
 | 
										  "quantity": 0
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									  ]
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									"postings": [
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"posting_number": "string",
 | 
				
			||||||
 | 
										"products": [
 | 
				
			||||||
 | 
										  {
 | 
				
			||||||
 | 
											"product_id": 0,
 | 
				
			||||||
 | 
											"quantity": 0
 | 
				
			||||||
 | 
										  }
 | 
				
			||||||
 | 
										]
 | 
				
			||||||
 | 
									  }
 | 
				
			||||||
 | 
									]
 | 
				
			||||||
 | 
								}`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Test No Client-Id or Api-Key
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusUnauthorized,
 | 
				
			||||||
 | 
								map[string]string{},
 | 
				
			||||||
 | 
								&SplitOrderParams{},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"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().SplitOrder(ctx, test.params)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compareJsonResponse(t, test.response, &SplitOrderResponse{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode != test.statusCode {
 | 
				
			||||||
 | 
								t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -747,6 +747,9 @@ type CreateOrUpdateProductItem struct {
 | 
				
			|||||||
	// Category identifier
 | 
						// Category identifier
 | 
				
			||||||
	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
 | 
				
			||||||
 | 
						NewDescriptinoCategoryId int64 `json:"new_description_category_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Marketing color.
 | 
						// Marketing color.
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// Pass the link to the image in the public cloud storage. The image format is JPG
 | 
						// Pass the link to the image in the public cloud storage. The image format is JPG
 | 
				
			||||||
@@ -819,6 +822,12 @@ type CreateOrUpdateProductItem struct {
 | 
				
			|||||||
	//   - IS_NO_CODE_SERVICE
 | 
						//   - IS_NO_CODE_SERVICE
 | 
				
			||||||
	ServiceType string `json:"service_type" default:"IS_CODE_SERVICE"`
 | 
						ServiceType string `json:"service_type" default:"IS_CODE_SERVICE"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product type identifier.
 | 
				
			||||||
 | 
						// You can get values from the type_id parameter in the `/v1/description-category/tree` method response.
 | 
				
			||||||
 | 
						// When filling this parameter in,
 | 
				
			||||||
 | 
						// you can leave out the attributes attribute if it has the `id:8229` parameter
 | 
				
			||||||
 | 
						TypeId int64 `json:"type_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// VAT rate for the product:
 | 
						// VAT rate for the product:
 | 
				
			||||||
	//   - 0 — not subject to VAT,
 | 
						//   - 0 — not subject to VAT,
 | 
				
			||||||
	//   - 0.1 — 10%,
 | 
						//   - 0.1 — 10%,
 | 
				
			||||||
@@ -1409,9 +1418,6 @@ type GetDescriptionOfProductResult struct {
 | 
				
			|||||||
	// Product characteristic identifier
 | 
						// Product characteristic identifier
 | 
				
			||||||
	Id int64 `json:"id"`
 | 
						Id int64 `json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Identifier for subsequent batch loading of images
 | 
					 | 
				
			||||||
	ImageGroupId string `json:"image_group_id"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Array of links to product images
 | 
						// Array of links to product images
 | 
				
			||||||
	Images []GetDescriptionOfProductResultImage `json:"images"`
 | 
						Images []GetDescriptionOfProductResultImage `json:"images"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1427,6 +1433,9 @@ type GetDescriptionOfProductResult struct {
 | 
				
			|||||||
	// Array of PDF files
 | 
						// Array of PDF files
 | 
				
			||||||
	PDFList []GetDescriptionOfProductResultPDF `json:"pdf_list"`
 | 
						PDFList []GetDescriptionOfProductResultPDF `json:"pdf_list"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product type identifier
 | 
				
			||||||
 | 
						TypeId int64 `json:"type_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Weight of product in the package
 | 
						// Weight of product in the package
 | 
				
			||||||
	Weight int32 `json:"weight"`
 | 
						Weight int32 `json:"weight"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1753,67 +1762,6 @@ func (c Products) RemoveProductWithoutSKU(ctx context.Context, params *RemovePro
 | 
				
			|||||||
	return resp, nil
 | 
						return resp, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ListGeoRestrictionsParams struct {
 | 
					 | 
				
			||||||
	// Filter. To get all geo-restrictions, leave names blank and specify true in the only_visible parameter
 | 
					 | 
				
			||||||
	Filter ListGeoRestrictionsFilter `json:"filter"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Order number of geo-restriction from which to output data in the response.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	// If you specify 23 in this parameter, the first item in the restrictions list will output order_number = 24.
 | 
					 | 
				
			||||||
	// If you want to get all geo-restrictions, pass 0 in this parameter
 | 
					 | 
				
			||||||
	LastOrderNumber int64 `json:"last_order_number"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Number of items in the response
 | 
					 | 
				
			||||||
	Limit int64 `json:"limit"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ListGeoRestrictionsFilter struct {
 | 
					 | 
				
			||||||
	// List with city names
 | 
					 | 
				
			||||||
	Names []string `json:"names"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Value visibility. We recommend always passing true in this parameter
 | 
					 | 
				
			||||||
	OnlyVisible bool `json:"only_visible"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ListGeoRestrictionsResponse struct {
 | 
					 | 
				
			||||||
	core.CommonResponse
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Restrictions
 | 
					 | 
				
			||||||
	Restrictions []ListGeoRestrictionsRestriction `json:"restrictions"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ListGeoRestrictionsRestriction struct {
 | 
					 | 
				
			||||||
	// Geo-restriction identifier
 | 
					 | 
				
			||||||
	Id string `json:"id"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Item visibility
 | 
					 | 
				
			||||||
	IsVisible bool `json:"is_visible"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// City name
 | 
					 | 
				
			||||||
	Name string `json:"name"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Geo-restriction order number.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	// If you specify 23 in the last_order_number parameter in the request,
 | 
					 | 
				
			||||||
	// the first item in the restrictions list will have order_number = 24
 | 
					 | 
				
			||||||
	OrderNumber int64 `json:"order_number"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Get a list of geo-restrictions for services
 | 
					 | 
				
			||||||
func (c Products) ListGeoRestrictions(ctx context.Context, params *ListGeoRestrictionsParams) (*ListGeoRestrictionsResponse, error) {
 | 
					 | 
				
			||||||
	url := "/v1/products/geo-restrictions-catalog-by-filter"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp := &ListGeoRestrictionsResponse{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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 UploadActivationCodesParams struct {
 | 
					type UploadActivationCodesParams struct {
 | 
				
			||||||
	// Digital activation codes
 | 
						// Digital activation codes
 | 
				
			||||||
	DigitalCodes []string `json:"digital_codes"`
 | 
						DigitalCodes []string `json:"digital_codes"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1611,7 +1611,6 @@ func TestGetDescriptionOfProduct(t *testing.T) {
 | 
				
			|||||||
						"index": 2
 | 
											"index": 2
 | 
				
			||||||
					  }
 | 
										  }
 | 
				
			||||||
					],
 | 
										],
 | 
				
			||||||
					"image_group_id": "",
 | 
					 | 
				
			||||||
					"images360": [],
 | 
										"images360": [],
 | 
				
			||||||
					"pdf_list": [],
 | 
										"pdf_list": [],
 | 
				
			||||||
					"attributes": [
 | 
										"attributes": [
 | 
				
			||||||
@@ -2141,79 +2140,6 @@ func TestRemoveProductWithoutSKU(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestListGeoRestrictions(t *testing.T) {
 | 
					 | 
				
			||||||
	t.Parallel()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tests := []struct {
 | 
					 | 
				
			||||||
		statusCode int
 | 
					 | 
				
			||||||
		headers    map[string]string
 | 
					 | 
				
			||||||
		params     *ListGeoRestrictionsParams
 | 
					 | 
				
			||||||
		response   string
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		// Test Ok
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			http.StatusOK,
 | 
					 | 
				
			||||||
			map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
 | 
					 | 
				
			||||||
			&ListGeoRestrictionsParams{
 | 
					 | 
				
			||||||
				Filter: ListGeoRestrictionsFilter{
 | 
					 | 
				
			||||||
					OnlyVisible: true,
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				LastOrderNumber: 0,
 | 
					 | 
				
			||||||
				Limit:           3,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			`{
 | 
					 | 
				
			||||||
				"restrictions": [
 | 
					 | 
				
			||||||
				  {
 | 
					 | 
				
			||||||
					"id": "world",
 | 
					 | 
				
			||||||
					"name": "Весь Мир",
 | 
					 | 
				
			||||||
					"is_visible": true,
 | 
					 | 
				
			||||||
					"order_number": 1
 | 
					 | 
				
			||||||
				  },
 | 
					 | 
				
			||||||
				  {
 | 
					 | 
				
			||||||
					"id": "42fb1c32-0cfe-5c96-9fb5-7f8e8449f28c",
 | 
					 | 
				
			||||||
					"name": "Все города РФ",
 | 
					 | 
				
			||||||
					"is_visible": true,
 | 
					 | 
				
			||||||
					"order_number": 2
 | 
					 | 
				
			||||||
				  },
 | 
					 | 
				
			||||||
				  {
 | 
					 | 
				
			||||||
					"id": "moscow",
 | 
					 | 
				
			||||||
					"name": "Москва",
 | 
					 | 
				
			||||||
					"is_visible": true,
 | 
					 | 
				
			||||||
					"order_number": 3
 | 
					 | 
				
			||||||
				  }
 | 
					 | 
				
			||||||
				]
 | 
					 | 
				
			||||||
			}`,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		// Test No Client-Id or Api-Key
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			http.StatusUnauthorized,
 | 
					 | 
				
			||||||
			map[string]string{},
 | 
					 | 
				
			||||||
			&ListGeoRestrictionsParams{},
 | 
					 | 
				
			||||||
			`{
 | 
					 | 
				
			||||||
				"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.Products().ListGeoRestrictions(ctx, test.params)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Error(err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		compareJsonResponse(t, test.response, &ListGeoRestrictionsResponse{})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if resp.StatusCode != test.statusCode {
 | 
					 | 
				
			||||||
			t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestUploadActivationCodes(t *testing.T) {
 | 
					func TestUploadActivationCodes(t *testing.T) {
 | 
				
			||||||
	t.Parallel()
 | 
						t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,11 @@ type GetCurrentSellerRatingInfoResponse struct {
 | 
				
			|||||||
	// Rating groups list
 | 
						// Rating groups list
 | 
				
			||||||
	Groups []GetCurrentSellerRatingInfoGroup `json:"groups"`
 | 
						Groups []GetCurrentSellerRatingInfoGroup `json:"groups"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Localization index details.
 | 
				
			||||||
 | 
						// If you had no sales in the last 14 days,
 | 
				
			||||||
 | 
						// the parameter fields will be empty
 | 
				
			||||||
 | 
						LocalizationIndex []LocalizationIndex `json:"localization_index"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// An indication that the penalty points balance is exceeded
 | 
						// An indication that the penalty points balance is exceeded
 | 
				
			||||||
	PenaltyScoreExceeded bool `json:"penalty_score_exceeded"`
 | 
						PenaltyScoreExceeded bool `json:"penalty_score_exceeded"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,6 +30,14 @@ type GetCurrentSellerRatingInfoResponse struct {
 | 
				
			|||||||
	Premium bool `json:"premium"`
 | 
						Premium bool `json:"premium"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LocalizationIndex struct {
 | 
				
			||||||
 | 
						// Date of localization index calculation
 | 
				
			||||||
 | 
						CalculationDate time.Time `json:"calculation_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Localization index value
 | 
				
			||||||
 | 
						LocalizationPercentage int32 `json:"localization_percentage"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GetCurrentSellerRatingInfoGroup struct {
 | 
					type GetCurrentSellerRatingInfoGroup struct {
 | 
				
			||||||
	// Ratings group name
 | 
						// Ratings group name
 | 
				
			||||||
	GroupName string `json:"group_name"`
 | 
						GroupName string `json:"group_name"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,12 @@ func TestGetCurrentRatingInfo(t *testing.T) {
 | 
				
			|||||||
					]
 | 
										]
 | 
				
			||||||
				  }
 | 
									  }
 | 
				
			||||||
				],
 | 
									],
 | 
				
			||||||
 | 
									"localization_index": [
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											"calculation_date": "2019-08-24T14:15:22Z",
 | 
				
			||||||
 | 
											"localization_percentage": 0
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
				"penalty_score_exceeded": true,
 | 
									"penalty_score_exceeded": true,
 | 
				
			||||||
				"premium": true
 | 
									"premium": true
 | 
				
			||||||
			}`,
 | 
								}`,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										245
									
								
								ozon/returns.go
									
									
									
									
									
								
							
							
						
						
									
										245
									
								
								ozon/returns.go
									
									
									
									
									
								
							@@ -943,7 +943,250 @@ func (c Returns) FBSQuantity(ctx context.Context, params *GetFBSQuantityReturnsP
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	resp := &GetFBSQuantityReturnsResponse{}
 | 
						resp := &GetFBSQuantityReturnsResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	response, err := c.client.Request(ctx, http.MethodPost, url, nil, resp, nil)
 | 
						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 ListReturnsParams struct {
 | 
				
			||||||
 | 
						// Filter
 | 
				
			||||||
 | 
						Filter *ListReturnsFilter `json:"filter,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number of loaded returns. The maximum value is 500
 | 
				
			||||||
 | 
						Limit int32 `json:"limit"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Identifier of the last loaded return
 | 
				
			||||||
 | 
						LastId int64 `json:"last_id"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListReturnsFilter struct {
 | 
				
			||||||
 | 
						// Filter by return creation date
 | 
				
			||||||
 | 
						LogisticReturnDate *GetFBSReturnsFilterTimeRange `json:"logistic_return_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by storage fees start date
 | 
				
			||||||
 | 
						StorageTarifficationDate *GetFBSReturnsFilterTimeRange `json:"storage_tariffication_start_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by date the return status changed
 | 
				
			||||||
 | 
						VisualStatusChangeMoment *GetFBSReturnsFilterTimeRange `json:"visual_status_change_moment"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by order identifier
 | 
				
			||||||
 | 
						OrderId int64 `json:"order_id,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by shipment number
 | 
				
			||||||
 | 
						PostingNumbers []string `json:"posting_numbers,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by product name
 | 
				
			||||||
 | 
						ProductName string `json:"product_name,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by product identifier in the seller's system
 | 
				
			||||||
 | 
						OfferId string `json:"offer_id,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by return status
 | 
				
			||||||
 | 
						VisualStatusName VisualStatus `json:"visual_status_name,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by warehouse identifier
 | 
				
			||||||
 | 
						WarehouseId int64 `json:"warehouse_id,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by return label barcode
 | 
				
			||||||
 | 
						Barcode string `json:"barcode,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Filter by delivery scheme: FBS or FBO
 | 
				
			||||||
 | 
						ReturnSchema string `json:"return_schema,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListReturnsResponse struct {
 | 
				
			||||||
 | 
						core.CommonResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Returns details
 | 
				
			||||||
 | 
						Returns []Return `json:"returns"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// true, if the seller has other returns
 | 
				
			||||||
 | 
						HasNext bool `json:"has_next"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Return struct {
 | 
				
			||||||
 | 
						// Product items data
 | 
				
			||||||
 | 
						Exemplars []ReturnExemplar `json:"exemplars"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return identifier
 | 
				
			||||||
 | 
						Id int64 `json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Company identifier
 | 
				
			||||||
 | 
						CompanyId int64 `json:"company_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return reason
 | 
				
			||||||
 | 
						ReturnReasonName string `json:"return_reason_name"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return type
 | 
				
			||||||
 | 
						Type string `json:"type"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return scheme
 | 
				
			||||||
 | 
						Schema string `json:"schema"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Order identifier
 | 
				
			||||||
 | 
						OrderId int64 `json:"order_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Order number
 | 
				
			||||||
 | 
						OrderNumber string `json:"order_number"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Warehouse where the return is stored
 | 
				
			||||||
 | 
						Place ReturnPlace `json:"place"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Warehouse where returns are sent to
 | 
				
			||||||
 | 
						TargetPlace ReturnPlace `json:"target_place"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Storage details
 | 
				
			||||||
 | 
						Storage ReturnStorage `json:"storage"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product details
 | 
				
			||||||
 | 
						Product ReturnProduct `json:"product"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return details
 | 
				
			||||||
 | 
						Logistic ReturnLogistic `json:"logistic"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return status details
 | 
				
			||||||
 | 
						Visual ReturnVisual `json:"visual"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Additional information
 | 
				
			||||||
 | 
						AdditionalInfo ReturnAdditionalInfo `json:"additional_info"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Previous return identifier
 | 
				
			||||||
 | 
						SourceId int64 `json:"source_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shipment number
 | 
				
			||||||
 | 
						PostingNumber string `json:"posting_number"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Original shipment barcode
 | 
				
			||||||
 | 
						ClearingId int64 `json:"clearing_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Package unit identifier in the Ozon logistics system
 | 
				
			||||||
 | 
						ReturnClearingId int64 `json:"return_clearing_id"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnExemplar struct {
 | 
				
			||||||
 | 
						// Product identifier
 | 
				
			||||||
 | 
						Id int64 `json:"id"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnPlace struct {
 | 
				
			||||||
 | 
						// Warehouse identifier
 | 
				
			||||||
 | 
						Id int64 `json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Warehouse name
 | 
				
			||||||
 | 
						Name string `json:"name"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Warehouse address
 | 
				
			||||||
 | 
						Address string `json:"address"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnStorage struct {
 | 
				
			||||||
 | 
						// Storage cost details
 | 
				
			||||||
 | 
						Sum ReturnSum `json:"sum"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// First day of charging for storage
 | 
				
			||||||
 | 
						TarifficationsFirstDate time.Time `json:"tariffication_first_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Start date for storage fees
 | 
				
			||||||
 | 
						TarifficationsStartDate time.Time `json:"tariffication_start_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Date when the return was ready for handover
 | 
				
			||||||
 | 
						ArrivedMoment time.Time `json:"arrived_moment"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Number of days the return has been waiting for handover
 | 
				
			||||||
 | 
						Days int64 `json:"days"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disposal cost details
 | 
				
			||||||
 | 
						UtilizationSum ReturnSum `json:"utilization_sum"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Planned disposal date
 | 
				
			||||||
 | 
						UtilizationForecastDate string `json:"utilization_forecast_date"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnSum struct {
 | 
				
			||||||
 | 
						// Currency
 | 
				
			||||||
 | 
						CurrencyCode string `json:"currency_code"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disposal cost
 | 
				
			||||||
 | 
						Price float64 `json:"price"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnProduct struct {
 | 
				
			||||||
 | 
						// Product identifier in the Ozon system, SKU
 | 
				
			||||||
 | 
						SKU int64 `json:"sku"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product identifier in the seller's system
 | 
				
			||||||
 | 
						OfferId string `json:"offer_id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// product name
 | 
				
			||||||
 | 
						Name string `json:"name"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product price details
 | 
				
			||||||
 | 
						Price ReturnSum `json:"price"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Product cost without commission
 | 
				
			||||||
 | 
						PriceWithoutCommission ReturnSum `json:"price_without_commission"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Sales commission by category
 | 
				
			||||||
 | 
						CommissionPercent float64 `json:"commission_percent"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Commission details
 | 
				
			||||||
 | 
						Commission ReturnSum `json:"commission"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnLogistic struct {
 | 
				
			||||||
 | 
						// Date when the order was placed for technical return
 | 
				
			||||||
 | 
						TechnicalReturnMoment time.Time `json:"technical_return_moment"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Date when the return arrived to the warehouse or was handed over to the seller
 | 
				
			||||||
 | 
						FinalMoment time.Time `json:"final_moment"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Date when the seller received compensation for the return
 | 
				
			||||||
 | 
						CancelledWithCompensationMoment time.Time `json:"cancelled_with_compensation_moment"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Date when the customer returned the product
 | 
				
			||||||
 | 
						ReturnDate time.Time `json:"return_date"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return label barcode
 | 
				
			||||||
 | 
						Barcode string `json:"barcode"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnVisual struct {
 | 
				
			||||||
 | 
						// Return status
 | 
				
			||||||
 | 
						Status ReturnVisualStatus `json:"status"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Date the return status changed
 | 
				
			||||||
 | 
						ChangeMoment time.Time `json:"change_moment"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnVisualStatus struct {
 | 
				
			||||||
 | 
						// Return status identifier
 | 
				
			||||||
 | 
						Id int32 `json:"id"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return status name
 | 
				
			||||||
 | 
						DisplayName string `json:"display_name"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// System name of the return status
 | 
				
			||||||
 | 
						SystemName string `json:"sys_name"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ReturnAdditionalInfo struct {
 | 
				
			||||||
 | 
						// true, if the return package is opened
 | 
				
			||||||
 | 
						IsOpened bool `json:"is_opened"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// true, if the return belongs to Super Economy products
 | 
				
			||||||
 | 
						IsSuperEconom bool `json:"is_super_econom"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c Returns) List(ctx context.Context, params *ListReturnsParams) (*ListReturnsResponse, error) {
 | 
				
			||||||
 | 
						url := "/v1/returns/list"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp := &ListReturnsResponse{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						response, err := c.client.Request(ctx, http.MethodPost, url, params, resp, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1059,3 +1059,153 @@ func TestFBSQuantity(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestListReturns(t *testing.T) {
 | 
				
			||||||
 | 
						t.Parallel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							statusCode int
 | 
				
			||||||
 | 
							headers    map[string]string
 | 
				
			||||||
 | 
							params     *ListReturnsParams
 | 
				
			||||||
 | 
							response   string
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							// Test Ok
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusOK,
 | 
				
			||||||
 | 
								map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"},
 | 
				
			||||||
 | 
								&ListReturnsParams{
 | 
				
			||||||
 | 
									Filter: &ListReturnsFilter{
 | 
				
			||||||
 | 
										LogisticReturnDate: &GetFBSReturnsFilterTimeRange{
 | 
				
			||||||
 | 
											TimeFrom: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
											TimeTo:   core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										StorageTarifficationDate: &GetFBSReturnsFilterTimeRange{
 | 
				
			||||||
 | 
											TimeFrom: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
											TimeTo:   core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										VisualStatusChangeMoment: &GetFBSReturnsFilterTimeRange{
 | 
				
			||||||
 | 
											TimeFrom: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
											TimeTo:   core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										WarehouseId:  911,
 | 
				
			||||||
 | 
										ReturnSchema: "FBO",
 | 
				
			||||||
 | 
										ProductName:  "string",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Limit:  500,
 | 
				
			||||||
 | 
									LastId: 0,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"returns": [
 | 
				
			||||||
 | 
									  {
 | 
				
			||||||
 | 
										"exemplars": [
 | 
				
			||||||
 | 
										  {
 | 
				
			||||||
 | 
											"id": 1019562967545956
 | 
				
			||||||
 | 
										  }
 | 
				
			||||||
 | 
										],
 | 
				
			||||||
 | 
										"id": 1000015552,
 | 
				
			||||||
 | 
										"company_id": 3058,
 | 
				
			||||||
 | 
										"return_reason_name": "Customer refused on receipt: not satisfied with the quality of the product",
 | 
				
			||||||
 | 
										"type": "FullReturn",
 | 
				
			||||||
 | 
										"schema": "Fbs",
 | 
				
			||||||
 | 
										"order_id": 24540784250,
 | 
				
			||||||
 | 
										"order_number": "58544282-0057",
 | 
				
			||||||
 | 
										"place": {
 | 
				
			||||||
 | 
										  "id": 23869688194000,
 | 
				
			||||||
 | 
										  "name": "СЦ_Львовский_Возвраты",
 | 
				
			||||||
 | 
										  "address": "Россия, обл. Московская, г. Подольск, промышленная зона Львовский, ул. Московская, д. 69, стр. 5"
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"target_place": {
 | 
				
			||||||
 | 
										  "id": 23869688194000,
 | 
				
			||||||
 | 
										  "name": "СЦ_Львовский_Возвраты",
 | 
				
			||||||
 | 
										  "address": "Россия, обл. Московская, г. Подольск, промышленная зона Львовский, ул. Московская, д. 69, стр. 5"
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"storage": {
 | 
				
			||||||
 | 
										  "sum": {
 | 
				
			||||||
 | 
											"currency_code": "RUB",
 | 
				
			||||||
 | 
											"price": 1231
 | 
				
			||||||
 | 
										  },
 | 
				
			||||||
 | 
										  "tariffication_first_date": "2024-07-30T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "tariffication_start_date": "2024-07-29T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "arrived_moment": "2024-07-29T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "days": 0,
 | 
				
			||||||
 | 
										  "utilization_sum": {
 | 
				
			||||||
 | 
											"currency_code": "RUB",
 | 
				
			||||||
 | 
											"price": 1231
 | 
				
			||||||
 | 
										  },
 | 
				
			||||||
 | 
										  "utilization_forecast_date": "2024-07-29T06:15:48.998146Z"
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"product": {
 | 
				
			||||||
 | 
										  "sku": 1100526203,
 | 
				
			||||||
 | 
										  "offer_id": "81451",
 | 
				
			||||||
 | 
										  "name": "Кукла Дотти Плачущий младенец Cry Babies Dressy Dotty",
 | 
				
			||||||
 | 
										  "price": {
 | 
				
			||||||
 | 
											"currency_code": "RUB",
 | 
				
			||||||
 | 
											"price": 3318
 | 
				
			||||||
 | 
										  },
 | 
				
			||||||
 | 
										  "price_without_commission": {
 | 
				
			||||||
 | 
											"currency_code": "RUB",
 | 
				
			||||||
 | 
											"price": 3318
 | 
				
			||||||
 | 
										  },
 | 
				
			||||||
 | 
										  "commission_percent": 1.2,
 | 
				
			||||||
 | 
										  "commission": {
 | 
				
			||||||
 | 
											"currency_code": "RUB",
 | 
				
			||||||
 | 
											"price": 2312
 | 
				
			||||||
 | 
										  }
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"logistic": {
 | 
				
			||||||
 | 
										  "technical_return_moment": "2024-07-29T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "final_moment": "2024-07-29T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "cancelled_with_compensation_moment": "2024-07-29T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "return_date": "2024-07-29T06:15:48.998146Z",
 | 
				
			||||||
 | 
										  "barcode": "ii5275210303"
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"visual": {
 | 
				
			||||||
 | 
										  "status": {
 | 
				
			||||||
 | 
											"id": 3,
 | 
				
			||||||
 | 
											"display_name": "At the pick-up point",
 | 
				
			||||||
 | 
											"sys_name": "ArrivedAtReturnPlace"
 | 
				
			||||||
 | 
										  },
 | 
				
			||||||
 | 
										  "change_moment": "2024-07-29T06:15:48.998146Z"
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"additional_info": {
 | 
				
			||||||
 | 
										  "is_opened": true,
 | 
				
			||||||
 | 
										  "is_super_econom": false
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										"source_id": 90426223,
 | 
				
			||||||
 | 
										"posting_number": "58544282-0057-1",
 | 
				
			||||||
 | 
										"clearing_id": 21190893156000,
 | 
				
			||||||
 | 
										"return_clearing_id": null
 | 
				
			||||||
 | 
									  }
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
									"has_next": false
 | 
				
			||||||
 | 
								}`,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// Test No Client-Id or Api-Key
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								http.StatusUnauthorized,
 | 
				
			||||||
 | 
								map[string]string{},
 | 
				
			||||||
 | 
								&ListReturnsParams{},
 | 
				
			||||||
 | 
								`{
 | 
				
			||||||
 | 
									"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.Returns().List(ctx, test.params)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Error(err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compareJsonResponse(t, test.response, &ListReturnsResponse{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if resp.StatusCode != test.statusCode {
 | 
				
			||||||
 | 
								t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user