13 Commits

Author SHA1 Message Date
diPhantxm
9875a196e9 add all remained methods for managing products 2023-03-19 22:16:32 +03:00
diPhantxm
9f7c22237c add some methods for creating/editing/getting products 2023-03-19 20:14:57 +03:00
diPhantxm
5fb08c30cb add all remained methods for fbs 2023-03-19 01:51:25 +03:00
diPhantxm
c307bc31bd add some more additional endpoints for working with fbs 2023-03-18 23:38:13 +03:00
diPhantxm
f108c846b0 add methods for labeling and product check statuses 2023-03-18 20:34:04 +03:00
diPhantxm
9592e3a2d3 add some methods for working with fbs 2023-03-18 19:44:31 +03:00
diPhantxm
7b4ed2a988 implemented all methods for changing shipment status for fbs 2023-03-18 18:46:08 +03:00
diPhantxm
ec7ea5e1ef add some methods for shipment and delivering for fbs 2023-03-18 18:16:31 +03:00
diPhantxm
da9bedf63b add method for getting shipment details by identifier for fbs 2023-03-18 17:01:57 +03:00
diPhantxm
0fe3d86c48 add method for getting shipment data by barcode for fbs 2023-03-18 16:20:51 +03:00
Kirill
159e1501df update readme
fix example
2023-03-18 03:43:54 +03:00
Kirill
1d6a3f3eb8 Update readme
add instructions how to get Client-Id and Api-Key
2023-03-18 03:07:50 +03:00
diPhantxm
466cbc6379 extend tests 2023-03-18 03:05:06 +03:00
15 changed files with 6503 additions and 358 deletions

3
.gitignore vendored
View File

@@ -1 +1,2 @@
*.out
*.out
mistakes.md

View File

@@ -7,24 +7,24 @@
## Uploading and updating products
- [x] Create or update a product
- [ ] Get the product import status
- [ ] Create a product by Ozon ID
- [ ] Upload and update product images
- [ ] Check products images uploading status
- [x] Get the product import status
- [x] Create a product by Ozon ID
- [x] Upload and update product images
- [x] Check products images uploading status
- [x] List of products
- [x] Product details
- [x] Get products' content rating by SKU
- [ ] Get a list of products by identifiers
- [ ] Get a description of the product characteristics
- [ ] Get product description
- [ ] Product range limit, limits on product creation and update
- [ ] Change product identifiers from the seller's system
- [ ] Archive a product
- [ ] Unarchive a product
- [ ] Remove a product without an SKU from the archive
- [ ] Get a list of geo-restrictions for services
- [ ] Upload activation codes for services and digital products
- [ ] Status of uploading activation codes
- [x] Get a list of products by identifiers
- [x] Get a description of the product characteristics
- [x] Get product description
- [x] Product range limit, limits on product creation and update
- [x] Change product identifiers from the seller's system
- [x] Archive a product
- [x] Unarchive a product
- [x] Remove a product without an SKU from the archive
- [x] Get a list of geo-restrictions for services
- [x] Upload activation codes for services and digital products
- [x] Status of uploading activation codes
## Prices and Stocks
- [x] Update stocks
@@ -83,49 +83,49 @@
- [ ] Shipment details
## FBS and rFBS products labeling
- [ ] Validate labeling codes
- [ ] Check and save product items data
- [ ] Get product items check statuses
- [x] Validate labeling codes
- [x] Check and save product items data
- [x] Get product items check statuses
- [x] Pack the order (version 4)
## FBS and rFBS
- [x] List of unprocessed shipments (version 3)
- [x] Shipments list (version 3)
- [ ] Get shipment details by identifier (version 3)
- [ ] Get shipment data by barcode
- [ ] List of manufacturing countries
- [ ] Set the manufacturing country
- [ ] Specify number of boxes for multi-box shipments
- [ ] Get drop-off point restrictions
- [ ] Partial pack the order
- [ ] Create an acceptance and transfer certificate and a waybill
- [ ] Status of acceptance and transfer certificate and waybill
- [ ] Available freights list
- [ ] Get acceptance and transfer certificate and waybill
- [ ] Generating status of digital acceptance and transfer certificate and waybill
- [ ] Get digital shipment certificate
- [ ] Print the labeling
- [ ] Create a task to generate labeling
- [ ] Get a labeling file
- [ ] Package unit labels
- [ ] Open a dispute over a shipment
- [ ] Pass the shipment to shipping
- [ ] Shipment cancellation reasons
- [ ] Shipments cancellation reasons
- [ ] Cancel the shipment
- [ ] Add weight for bulk products in a shipment
- [ ] Cancel sending some products in the shipment
- [ ] List of shipment certificates
- [ ] Sign shipment certificates
- [ ] List of shipments in the certificate
- [ ] Change the status to "Delivering"
- [ ] Add tracking numbers
- [ ] Change the status to "Last Mile"
- [ ] Change the status to "Delivered"
- [ ] Change status to "Sent by seller"
- [ ] Dates available for delivery reschedule
- [ ] Reschedule shipment delivery date
- [ ] ETGB customs declarations
- [x] Get shipment details by identifier (version 3)
- [x] Get shipment data by barcode
- [x] List of manufacturing countries
- [x] Set the manufacturing country
- [x] Specify number of boxes for multi-box shipments
- [x] Get drop-off point restrictions
- [x] Partial pack the order
- [x] Create an acceptance and transfer certificate and a waybill
- [x] Status of acceptance and transfer certificate and waybill
- [x] Available freights list
- [x] Get acceptance and transfer certificate and waybill
- [x] Generating status of digital acceptance and transfer certificate and waybill
- [x] Get digital shipment certificate
- [x] Print the labeling
- [x] Create a task to generate labeling
- [x] Get a labeling file
- [x] Package unit labels
- [x] Open a dispute over a shipment
- [x] Pass the shipment to shipping
- [x] Shipment cancellation reasons
- [x] Shipments cancellation reasons
- [x] Cancel the shipment
- [x] Add weight for bulk products in a shipment
- [x] Cancel sending some products in the shipment
- [x] List of shipment certificates
- [x] Sign shipment certificates
- [x] List of shipments in the certificate
- [x] Change the status to "Delivering"
- [x] Add tracking numbers
- [x] Change the status to "Last Mile"
- [x] Change the status to "Delivered"
- [x] Change status to "Sent by seller"
- [x] Dates available for delivery reschedule
- [x] Reschedule shipment delivery date
- [x] ETGB customs declarations
## Returns
- [x] Get information about FBO returns (version 3)

View File

@@ -11,6 +11,8 @@ Read full [documentation](https://docs.ozon.ru/api/seller/en/#tag/Introduction)
You can check [list of supported endpoints](ENDPOINTS.md)
## How to start
Get Client-Id and Api-Key in your seller profile [here](https://seller.ozon.ru/app/settings/api-keys?locale=en)
Just add dependency to your project and you're ready to go.
```bash
go get github.com/diphantxm/ozon-api-client
@@ -33,7 +35,7 @@ func main() {
client := ozon.NewClient("my-client-id", "my-api-key")
// Send request with parameters
resp, err := client.GetProductDetails(&ozon.GetProductDetailsParams{
resp, err := client.Products().GetProductDetails(&ozon.GetProductDetailsParams{
ProductId: 123456789,
})
if err != nil || resp.StatusCode != http.StatusOK {

View File

@@ -112,7 +112,7 @@ type GetStocksOnWarehousesParams struct {
// Number of values per page.
//
// Default is 100
Limit int64 `json:"limit"`
Limit int64 `json:"limit" default:"100"`
// Number of elements that will be skipped in the response. For example, if `offset=10`, the response will start with the 11th element found
Offset int64 `json:"offset"`

View File

@@ -127,5 +127,11 @@ func TestGetStocksOnWarehouses(t *testing.T) {
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.Rows) > int(test.params.Limit) {
t.Errorf("Length of rows is bigger than limit")
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -64,6 +64,17 @@ func TestGetAvailablePromotions(t *testing.T) {
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) > 0 {
if resp.Result[0].Id == 0 {
t.Errorf("Id cannot be 0")
}
if resp.Result[0].ActionType == "" {
t.Errorf("Action type cannot be empty")
}
}
}
}
}
@@ -122,5 +133,11 @@ func TestAddToPromotion(t *testing.T) {
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.ProductIds) != len(test.params.Products) {
t.Errorf("Length of products in response and request must be equal")
}
}
}
}

View File

@@ -66,6 +66,14 @@ func TestGetCurrentRatingInfo(t *testing.T) {
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.Groups) > 0 {
if len(resp.Groups[0].Items) == 0 {
t.Errorf("Length of items in a group cannot be 0")
}
}
}
}
}
@@ -146,5 +154,13 @@ func TestGetRatingInfoForPeriod(t *testing.T) {
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.Ratings) > 0 {
if resp.Ratings[0].Rating == "" {
t.Errorf("Rating system cannot be empty")
}
}
}
}
}

View File

@@ -31,7 +31,7 @@ type GetReportsListParams struct {
// - SELLER_RETURNS — returns report,
// - SELLER_POSTINGS — shipments report,
// - SELLER_FINANCE — financial report
ReportType string `json:"report_type"`
ReportType string `json:"report_type" default:"ALL"`
}
type GetReportsListResponse struct {
@@ -39,41 +39,44 @@ type GetReportsListResponse struct {
// Method result
Result struct {
// Unique report identifier
Code string `json:"code"`
// Array with generated reports
Reports []struct {
// Unique report identifier
Code string `json:"code"`
// Report creation date
CreatedAt time.Time `json:"created_at"`
// Report creation date
CreatedAt time.Time `json:"created_at"`
// Error code when generating the report
Error string `json:"error"`
// Error code when generating the report
Error string `json:"error"`
// Link to CSV file
File string `json:"file"`
// Link to CSV file
File string `json:"file"`
// Array with the filters specified when the seller created the report
Params struct {
} `json:"params"`
// Array with the filters specified when the seller created the report
Params struct {
} `json:"params"`
// Report type:
// - SELLER_PRODUCTS — products report,
// - SELLER_TRANSACTIONS — transactions report,
// - SELLER_PRODUCT_PRICES — product prices report,
// - SELLER_STOCK — stocks report,
// - SELLER_PRODUCT_MOVEMENT — products movement report,
// - SELLER_RETURNS — returns report,
// - SELLER_POSTINGS — shipments report,
// - SELLER_FINANCE — financial report
ReportType string `json:"report_type"`
// Report type:
// - SELLER_PRODUCTS — products report,
// - SELLER_TRANSACTIONS — transactions report,
// - SELLER_PRODUCT_PRICES — product prices report,
// - SELLER_STOCK — stocks report,
// - SELLER_PRODUCT_MOVEMENT — products movement report,
// - SELLER_RETURNS — returns report,
// - SELLER_POSTINGS — shipments report,
// - SELLER_FINANCE — financial report
ReportType string `json:"report_type"`
// Report generation status
// - `success`
// - `failed`
Status string `json:"status"`
// Report generation status
// - `success`
// - `failed`
Status string `json:"status"`
} `json:"reports"`
// Total number of reports
Total int32 `json:"total"`
} `json:"result"`
// Total number of reports
Total int32 `json:"total"`
}
// Returns the list of reports that have been generated before
@@ -136,7 +139,7 @@ type GetReportDetailsResponse struct {
// Returns information about a created report by its identifier
func (c Reports) GetReportDetails(params *GetReportDetailsParams) (*GetReportDetailsResponse, error) {
url := "/v1/report/list"
url := "/v1/report/info"
resp := &GetReportDetailsResponse{}
@@ -405,7 +408,7 @@ type GetShipmentReportParams struct {
// Response language:
// - RU — Russian
// - EN — English
Language string `json:"language"`
Language string `json:"language" default:"DEFAULT"`
}
type GetShipmentReportFilter struct {

View File

@@ -77,6 +77,15 @@ func TestGetList(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if int(resp.Result.Total) != len(resp.Result.Reports) {
t.Errorf("Amount of reports (%d) is not equal to total (%d)", len(resp.Result.Reports), resp.Result.Total)
}
if len(resp.Result.Reports) > 0 {
if resp.Result.Reports[0].Status == "" {
t.Errorf("Status must be 'success' or 'failed'")
}
}
}
}
@@ -129,6 +138,12 @@ func TestGetReportDetails(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if resp.StatusCode == http.StatusOK {
if resp.Result.Status == "" {
t.Errorf("Status must be 'success' or 'failed'")
}
}
}
}
@@ -197,6 +212,14 @@ func TestGetFinancialReport(t *testing.T) {
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.CashFlows) > 0 {
if resp.Result.CashFlows[0].CurrencyCode == "" {
t.Errorf("Currency Code cannot be empty")
}
}
}
}
}
@@ -243,6 +266,12 @@ func TestGetProductsReport(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if resp.StatusCode == http.StatusOK {
if resp.Result.Code == "" {
t.Errorf("Code cannot be empty")
}
}
}
}
@@ -289,6 +318,12 @@ func TestGetStocksReport(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if resp.StatusCode == http.StatusOK {
if resp.Result.Code == "" {
t.Errorf("Code cannot be empty")
}
}
}
}
@@ -338,6 +373,12 @@ func TestGetProductsMovementReport(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if resp.StatusCode == http.StatusOK {
if resp.Result.Code == "" {
t.Errorf("Code cannot be empty")
}
}
}
}
@@ -388,6 +429,12 @@ func TestGetReturnsReport(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if resp.StatusCode == http.StatusOK {
if resp.Result.Code == "" {
t.Errorf("Code cannot be empty")
}
}
}
}
@@ -440,5 +487,11 @@ func TestGetShipmentReport(t *testing.T) {
if resp.StatusCode != test.statusCode {
t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode)
}
if resp.StatusCode == http.StatusOK {
if resp.Result.Code == "" {
t.Errorf("Code cannot be empty")
}
}
}
}

View File

@@ -32,15 +32,15 @@ func TestGetFBOReturns(t *testing.T) {
"returns": [
{
"accepted_from_customer_moment": "2019-08-24T14:15:22Z",
"company_id": 0,
"company_id": 123456789,
"current_place_name": "my-place",
"dst_place_name": "that-place",
"id": 0,
"id": 123456789,
"is_opened": true,
"posting_number": "some number",
"return_reason_name": "ripped",
"returned_to_ozon_moment": "2019-08-24T14:15:22Z",
"sku": 0,
"sku": 123456789,
"status_name": "delivering"
}
]
@@ -69,6 +69,20 @@ func TestGetFBOReturns(t *testing.T) {
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.Returns) > 0 {
if resp.Returns[0].Id == 0 {
t.Errorf("Id cannot be 0")
}
if resp.Returns[0].CompanyId == 0 {
t.Errorf("Company id cannot be 0")
}
if resp.Returns[0].SKU == 0 {
t.Errorf("SKU cannot be 0")
}
}
}
}
}
@@ -152,5 +166,25 @@ func TestGetFBSReturns(t *testing.T) {
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 int(resp.Result.Count) != len(resp.Result.Returns) {
t.Errorf("Count must equal to length of returns")
}
if len(resp.Result.Returns) > 0 {
if resp.Result.Returns[0].Id == 0 {
t.Errorf("Id cannot be 0")
}
if resp.Result.Returns[0].ProductId == 0 {
t.Errorf("Product id cannot be 0")
}
if resp.Result.Returns[0].SKU == 0 {
t.Errorf("SKU cannot be 0")
}
if resp.Result.Returns[0].Status == "" {
t.Errorf("Status cannot be empty")
}
}
}
}
}

View File

@@ -66,6 +66,17 @@ func TestGetListOfWarehouses(t *testing.T) {
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) > 0 {
if resp.Result[0].WarehouseId == 0 {
t.Errorf("Warehouse id cannot be 0")
}
if resp.Result[0].Name == "" {
t.Errorf("Name cannot be empty")
}
}
}
}
}
@@ -130,5 +141,22 @@ func TestGetListOfDeliveryMethods(t *testing.T) {
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) > 0 {
if resp.Result[0].Id == 0 {
t.Errorf("Id cannot be 0")
}
if resp.Result[0].Name == "" {
t.Errorf("Name cannot be empty")
}
if resp.Result[0].Status == "" {
t.Errorf("Status cannot be empty")
}
if resp.Result[0].WarehouseId == 0 {
t.Errorf("Warehouse id cannot be 0")
}
}
}
}
}