diff --git a/ozon/fbo.go b/ozon/fbo.go index b1b299a..452ce12 100644 --- a/ozon/fbo.go +++ b/ozon/fbo.go @@ -290,108 +290,38 @@ func (c FBO) GetShipmentDetails(ctx context.Context, params *GetShipmentDetailsP } type ListSupplyRequestsParams struct { - // Number of the page returned in the request - Page int32 `json:"page"` + // Filter + Filter *ListSupplyRequestsFilter `json:"filter"` - // Number of elements on the page - PageSize int32 `json:"page_size"` + // Customizing the display of the requests list + Paging *ListSupplyRequestsPaging `json:"paging"` +} - // Filter on status of a supply by request - States []SupplyRequestState `json:"states"` +type ListSupplyRequestsFilter struct { + States []string `json:"states"` +} + +type ListSupplyRequestsPaging struct { + // Supply number from which the list of requests will start + FromOrderId int64 `json:"from_supply_order_id"` + + // Number of requests in the response + Limit int32 `json:"limit"` } type ListSupplyRequestsResponse struct { core.CommonResponse - // Indicates that the response contains not the entire array of supply requests: - // - true — make a new request with a different page and page_size values to get information on the remaining requests; - // - false — the entire array of requests for the filter specified in the request was returned in the response - HasNext bool `json:"has_next"` - - // Supply requests list - SupplyOrders []SupplyRequestCommonResponse `json:"supply_orders"` - - // Total requests number - TotalSupplyOrdersCount int32 `json:"total_supply_orders_count"` -} - -type SupplyRequestCommonResponse struct { - // Supply request creation date - CreatedAt string `json:"created_at"` - - // Local time supply interval - LocalTimeslot SupplyRequestCommonResponseLocalTimeslot `json:"local_timeslot"` - - // Date from which you want to bring the supply to the warehouse. Only for supplies via vDC - PreferredSupplyDateFrom string `json:"preferred_supply_date_from"` - - // Date by which you want to bring the supply to the warehouse. Only for supplies via vDC - PreferredSupplyDateTo string `json:"preferred_supply_date_to"` - - // Your own warehouse from which you'll take the products to the supply warehouse. - // Only for supplies via vDC - SellerWarehouse SupplyRequestSellerWarehouse `json:"seller_warehouse"` - - // Status of a supply by request - State string `json:"state"` + // Supply request identifier you last requested + LastSupplyOrderId int64 `json:"last_supply_order_id"` // Supply request identifier - SupplyOrderId int64 `json:"supply_order_id"` - - // Supply request number - SupplyOrderNumber string `json:"supply_order_number"` - - // Supply warehouse - SupplyWarehouse SupplyRequestCommonResponseSupplyWarehouse `json:"supply_warehouse"` - - // time_left_to_prepare_supply - TimeLeftToPrepareSupply int64 `json:"time_left_to_prepare_supply"` - - // Time in seconds left to select the supply option. Only for supplies via vDC - TimeLeftToSelectSupplyVariant int64 `json:"time_left_to_select_supply_variant"` - - // total_items_count - TotalItemsCount int32 `json:"total_items_count"` - - // Total number of items in the request - TotalQuantity int32 `json:"total_quantity"` + SupplyOrderId []string `json:"supply_order_id"` } -type SupplyRequestSellerWarehouse struct { - // Warehouse address - Address string `json:"address"` - - // Warehouse name - Name string `json:"name"` - - // Warehouse identifier - WarehouseId int64 `json:"warehouse_id"` -} - -type SupplyRequestCommonResponseLocalTimeslot struct { - // Interval start - From string `json:"from"` - - // Interval end - To string `json:"to"` -} - -type SupplyRequestCommonResponseSupplyWarehouse struct { - // Warehouse address - Address string `json:"address"` - - // Warehouse name - Name string `json:"name"` - - // Warehouse identifier - WarehouseId int64 `json:"warehouse_id"` -} - -// Method for getting a list of supply requests to the Ozon warehouse. -// Requests with supply both to a specific warehouse and via a virtual -// distribution center (vDC) are taken into account +// Requests with supply to a specific warehouse and through a virtual distribution center (vDC) are taken into account func (c FBO) ListSupplyRequests(ctx context.Context, params *ListSupplyRequestsParams) (*ListSupplyRequestsResponse, error) { - url := "/v1/supply-order/list" + url := "/v2/supply-order/list" resp := &ListSupplyRequestsResponse{} @@ -405,17 +335,111 @@ func (c FBO) ListSupplyRequests(ctx context.Context, params *ListSupplyRequestsP } type GetSupplyRequestInfoParams struct { - // Supply request identifier - SupplyOrderId int64 `json:"supply_order_id"` + // Supply request identifier in the Ozon system + OrderIds []string `json:"order_ids"` } type GetSupplyRequestInfoResponse struct { core.CommonResponse - SupplyRequestCommonResponse + // Supply request details + Orders []SupplyOrder `json:"orders"` - // Driver and car information - VehicleInfo GetSupplyRequestInfoVehicle `json:"vehicle_info"` + // Warehouse details + Warehouses []SupplyWarehouse `json:"warehouses"` +} + +type SupplyOrder struct { + // Date of supply request creation + CreationDate string `json:"creation_date"` + + // Request source + CreationFlow string `json:"creation_flow"` + + // Time remaining in seconds to fill in the supply details. Only for requests from the vDC + DataFillingDeadline time.Time `json:"data_filling_deadline_utc"` + + // Supply warehouse identifier + DropoffWarehouseId int64 `json:"dropoff_warehouse_id"` + + // Filter by supply status + State string `json:"state"` + + // Supply request contents + Supplies []Supply `json:"supplies"` + + // Supply request identifier + Id int64 `json:"supply_order_id"` + + // Request number + OrderNumber string `json:"supply_order_number"` + + // Supply time slot + Timeslot []SupplyTimeslot `json:"timeslot"` + + // Driver and vehicle details + Vehicle []SupplyVehicle `json:"vehicle"` +} + +type Supply struct { + // Supply contents identifier. Used in the /v1/supply-order/bundle method + BundleId string `json:"bundle_id"` + + // Storage warehouse identifier + StorageWarehouseId int64 `json:"storage_warehouse_id"` + + // Supply identifier + Id int64 `json:"supply_id"` +} + +type SupplyTimeslot struct { + // Reason why you can't select the supply time slot + Reasons []string `json:"can_not_set_reasons"` + + // true, if you can select or edit the supply time slot + CanSet bool `json:"can_set"` + + // true, if the characteristic is required + IsRequired bool `json:"is_required"` + + Value SupplyTimeslotValue `json:"value"` +} + +type SupplyVehicle struct { + // Reason why you can't select the supply time slot + Reasons []string `json:"can_not_set_reasons"` + + // true, if you can select or edit the supply time slot + CanSet bool `json:"can_set"` + + // true, if the characteristic is required + IsRequired bool `json:"is_required"` + + Value []GetSupplyRequestInfoVehicle `json:"value"` +} + +type SupplyTimeslotValue struct { + // Supply time slot in local time + Timeslot []SupplyTimeslotValueTimeslot `json:"timeslot"` + + // Time zone + Timezone []SupplyTimeslotValueTimezone `json:"timezone_info"` +} + +type SupplyTimeslotValueTimeslot struct { + // Supply time slot start + From time.Time `json:"from"` + + // Supply time slot end + To time.Time `json:"to"` +} + +type SupplyTimeslotValueTimezone struct { + // Time zone name + Name string `json:"iana_name"` + + // Time zone offset from UTC-0 in seconds + Offset string `json:"offset"` } type GetSupplyRequestInfoVehicle struct { @@ -432,11 +456,22 @@ type GetSupplyRequestInfoVehicle struct { VehicleNumber string `json:"vehicle_number"` } +type SupplyWarehouse struct { + // Warehouse address + Address string `json:"address"` + + // Warehouse name + Name string `json:"name"` + + // Warehouse identifier + Id int64 `json:"warehouse_id"` +} + // Method for getting detailed information on a supply request. // Requests with supply both to a specific warehouse and via a // virtual distribution center (vDC) are taken into account func (c FBO) GetSupplyRequestInfo(ctx context.Context, params *GetSupplyRequestInfoParams) (*GetSupplyRequestInfoResponse, error) { - url := "/v1/supply-order/get" + url := "/v2/supply-order/get" resp := &GetSupplyRequestInfoResponse{} @@ -563,3 +598,277 @@ func (c FBO) GetWarehouseWorkload(ctx context.Context) (*GetWarehouseWorkloadRes return resp, nil } + +type GetSupplyOrdersByStatusParams struct { +} + +type GetSupplyOrdersByStatusResponse struct { + core.CommonResponse + + Items []SupplyOrdersByStatus `json:"items"` +} + +type SupplyOrdersByStatus struct { + // Number of supply requests in this status + Count int32 `json:"count"` + + // Supply status + OrderState string `json:"order_state"` +} + +// Returns the number of supply requests in a specific status. +func (c FBO) GetSupplyOrdersByStatus(ctx context.Context) (*GetSupplyOrdersByStatusResponse, error) { + url := "/v1/supply-order/status/counter" + + resp := &GetSupplyOrdersByStatusResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, &GetSupplyOrdersByStatusParams{}, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} + +type GetSupplyTimeslotsParams struct { + // Supply request identifier + SupplyOrderId int64 `json:"supply_order_id"` +} + +type GetSupplyTimeslotsResponse struct { + core.CommonResponse + + // Supply time slot + Timeslots []SupplyTimeslotValueTimeslot `json:"timeslots"` + + // Time zone + Timezones []SupplyTimeslotValueTimezone `json:"timezone"` +} + +func (c FBO) GetSupplyTimeslots(ctx context.Context, params *GetSupplyTimeslotsParams) (*GetSupplyTimeslotsResponse, error) { + url := "/v1/supply-order/timeslot/get" + + resp := &GetSupplyTimeslotsResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} + +type UpdateSupplyTimeslotParams struct { + // Supply request identifier + SupplyOrderId int64 `json:"supply_order_id"` + + // Supply time slot details + Timeslot SupplyTimeslotValueTimeslot `json:"timeslot"` +} + +type UpdateSupplyTimeslotResponse struct { + core.CommonResponse + + // Possible errors + Errors []string `json:"errors"` + + // Operation identifier + OperationId string `json:"operation_id"` +} + +func (c FBO) UpdateSupplyTimeslot(ctx context.Context, params *UpdateSupplyTimeslotParams) (*UpdateSupplyTimeslotResponse, error) { + url := "/v1/supply-order/timeslot/update" + + resp := &UpdateSupplyTimeslotResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} + +type GetSupplyTimeslotStatusParams struct { + // Operation identifier + OperationId string `json:"operation_id"` +} + +type GetSupplyTimeslotStatusResponse struct { + core.CommonResponse + + // Possible errors + Errors []string `json:"errors"` + + // Data status + Status string `json:"status"` +} + +func (c FBO) GetSupplyTimeslotStatus(ctx context.Context, params *GetSupplyTimeslotStatusParams) (*GetSupplyTimeslotStatusResponse, error) { + url := "/v1/supply-order/timeslot/status" + + resp := &GetSupplyTimeslotStatusResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} + +type CreatePassParams struct { + // Supply request identifier + SupplyOrderId int64 `json:"supply_order_id"` + + // Driver and car information + Vehicle GetSupplyRequestInfoVehicle `json:"vehicle"` +} + +type CreatePassResponse struct { + core.CommonResponse + + // Possible errors + Errors []string `json:"error_reasons"` + + // Operation identifier + OperationId string `json:"operation_id"` +} + +func (c FBO) CreatePass(ctx context.Context, params *CreatePassParams) (*CreatePassResponse, error) { + url := "/v1/supply-order/pass/create" + + resp := &CreatePassResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} + +type GetPassParams struct { + // Operation identifier + OperationId string `json:"operation_id"` +} + +type GetPassResponse struct { + core.CommonResponse + + // Possible errors + Errors []string `json:"errors"` + + // Status of driver and vehicle data entry + Result string `json:"result"` +} + +func (c FBO) GetPass(ctx context.Context, params *GetPassParams) (*GetPassResponse, error) { + url := "/v1/supply-order/pass/status" + + resp := &GetPassResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} + +type GetSupplyContentParams struct { + // Identifiers of supply contents. Minimum is 1, maximum is 1000. You can get them using the /v2/supply-order/get method + BundleIds []string `json:"bundle_ids"` + + // true, to sort in ascending order + IsAsc bool `json:"is_asc"` + + // Identifier of the last value on the page + LastId string `json:"last_id"` + + // Number of values on the page. Minimum is 1, maximum is 1000 + Limit int32 `json:"limit"` + + // Search query, for example: by name, article code, or SKU + Query string `json:"query"` + + // Sorting by parameters + SortField string `json:"sort_field"` +} + +type GetSupplyContentResponse struct { + core.CommonResponse + + // List of products in the supply request + Items []SupplyContentItem `json:"items"` + + // Quantity of products in the request + TotalCount int32 `json:"total_count"` + + // Indication that the response hasn't returned all products + HasNext bool `json:"has_next"` + + // Identifier of the last value on the page + LastId string `json:"last_id"` +} + +type SupplyContentItem struct { + // Link to product image + IconPath string `json:"icon_path"` + + // Product identifier in the Ozon system, SKU + SKU int64 `json:"sku"` + + // Product name + Name string `json:"name"` + + // Product items quantity + Quantity int32 `json:"quantity"` + + // Barcode + Barcode string `json:"barcode"` + + // Product identifier + ProductId int64 `json:"product_id"` + + // Quantity of products in one package + Quant int32 `json:"quant"` + + // true if the quantity of products in one package can be edited + IsQuantEditable bool `json:"is_quant_editable"` + + // Volume of products in liters + VolumeInLiters float64 `json:"volume_in_litres"` + + // Volume of all products in liters + TotalVolumeInLiters float64 `json:"total_volume_in_litres"` + + // Product article code + ContractorItemCode string `json:"contractor_item_code"` + + // Super product label + SFBOAttribute string `json:"sfbo_attribute"` + + // Type of wrapper + ShipmentType string `json:"shipment_type"` +} + +func (c FBO) GetSupplyContent(ctx context.Context, params *GetSupplyContentParams) (*GetSupplyContentResponse, error) { + url := "/v1/supply-order/bundle" + + resp := &GetSupplyContentResponse{} + + response, err := c.client.Request(ctx, http.MethodGet, url, params, resp, nil) + if err != nil { + return nil, err + } + response.CopyCommonResponse(&resp.CommonResponse) + + return resp, nil +} diff --git a/ozon/fbo_test.go b/ozon/fbo_test.go index 5eec229..9edc84c 100644 --- a/ozon/fbo_test.go +++ b/ozon/fbo_test.go @@ -301,36 +301,19 @@ func TestListSupplyRequests(t *testing.T) { http.StatusOK, map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, &ListSupplyRequestsParams{ - Page: 0, - PageSize: 0, - States: []SupplyRequestState{AcceptanceAtStorageWarehouse}, + Filter: &ListSupplyRequestsFilter{ + States: []string{"ORDER_STATE_DATA_FILLING"}, + }, + Paging: &ListSupplyRequestsPaging{ + FromOrderId: 0, + Limit: 0, + }, }, `{ - "has_next": true, - "supply_orders": [ - { - "created_at": "string", - "local_timeslot": { - "from": "string", - "to": "string" - }, - "preferred_supply_date_from": "string", - "preferred_supply_date_to": "string", - "state": "string", - "supply_order_id": 0, - "supply_order_number": "string", - "supply_warehouse": { - "address": "string", - "name": "string", - "warehouse_id": 0 - }, - "time_left_to_prepare_supply": 0, - "time_left_to_select_supply_variant": 0, - "total_items_count": 0, - "total_quantity": 0 - } - ], - "total_supply_orders_count": 0 + "last_supply_order_id": 0, + "supply_order_id": [ + "string" + ] }`, }, // Test No Client-Id or Api-Key @@ -377,39 +360,74 @@ func TestGetSupplyRequestInfo(t *testing.T) { http.StatusOK, map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, &GetSupplyRequestInfoParams{ - SupplyOrderId: 0, + OrderIds: []string{"string"}, }, `{ - "created_at": "string", - "local_timeslot": { - "from": "string", - "to": "string" - }, - "preferred_supply_date_from": "string", - "preferred_supply_date_to": "string", - "seller_warehouse": { - "address": "string", - "name": "string", - "warehouse_id": 0 - }, - "state": "string", - "supply_order_id": 0, - "supply_order_number": "string", - "supply_warehouse": { - "address": "string", - "name": "string", - "warehouse_id": 0 - }, - "time_left_to_prepare_supply": 0, - "time_left_to_select_supply_variant": 0, - "total_items_count": 0, - "total_quantity": 0, - "vehicle_info": { - "driver_name": "string", - "driver_phone": "string", - "vehicle_model": "string", - "vehicle_number": "string" - } + "orders": [ + { + "creation_date": "string", + "creation_flow": "string", + "data_filling_deadline_utc": "2019-08-24T14:15:22Z", + "dropoff_warehouse_id": 0, + "state": "ORDER_STATE_UNSPECIFIED", + "supplies": [ + { + "bundle_id": "string", + "storage_warehouse_id": 0, + "supply_id": 0 + } + ], + "supply_order_id": 0, + "supply_order_number": "string", + "timeslot": [ + { + "can_not_set_reasons": [ + "string" + ], + "can_set": true, + "is_required": true, + "value": { + "timeslot": [ + { + "from": "2019-08-24T14:15:22Z", + "to": "2019-08-24T14:15:22Z" + } + ], + "timezone_info": [ + { + "iana_name": "string", + "offset": "string" + } + ] + } + } + ], + "vehicle": [ + { + "can_not_set_reasons": [ + "string" + ], + "can_set": true, + "is_required": true, + "value": [ + { + "driver_name": "string", + "driver_phone": "string", + "vehicle_model": "string", + "vehicle_number": "string" + } + ] + } + ] + } + ], + "warehouses": [ + { + "address": "string", + "name": "string", + "warehouse_id": 0 + } + ] }`, }, // Test No Client-Id or Api-Key @@ -565,3 +583,409 @@ func TestGetWarehouseWorkload(t *testing.T) { } } } + +func TestGetSupplyOrdersByStatus(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"}, + `{ + "items": [ + { + "count": 0, + "order_state": "ORDER_STATE_UNSPECIFIED" + } + ] + }`, + }, + // 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.FBO().GetSupplyOrdersByStatus(ctx) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &GetSupplyOrdersByStatusResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} + +func TestGetSupplyTimeslots(t *testing.T) { + t.Parallel() + + tests := []struct { + statusCode int + headers map[string]string + params *GetSupplyTimeslotsParams + response string + }{ + // Test Ok + { + http.StatusOK, + map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, + &GetSupplyTimeslotsParams{ + SupplyOrderId: 0, + }, + `{ + "timeslots": [ + { + "from": "2019-08-24T14:15:22Z", + "to": "2019-08-24T14:15:22Z" + } + ], + "timezone": [ + { + "iana_name": "string", + "offset": "string" + } + ] + }`, + }, + // Test No Client-Id or Api-Key + { + http.StatusUnauthorized, + map[string]string{}, + &GetSupplyTimeslotsParams{}, + `{ + "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.FBO().GetSupplyTimeslots(ctx, test.params) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &GetSupplyTimeslotsResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} + +func TestUpdateSupplyTimeslot(t *testing.T) { + t.Parallel() + + tests := []struct { + statusCode int + headers map[string]string + params *UpdateSupplyTimeslotParams + response string + }{ + // Test Ok + { + http.StatusOK, + map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, + &UpdateSupplyTimeslotParams{ + SupplyOrderId: 0, + Timeslot: SupplyTimeslotValueTimeslot{ + From: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"), + To: core.TimeFromString(t, "2006-01-02T15:04:05Z", "2019-08-24T14:15:22Z"), + }, + }, + `{ + "errors": [ + "UPDATE_TIMESLOT_ERROR_UNSPECIFIED" + ], + "operation_id": "string" + }`, + }, + // Test No Client-Id or Api-Key + { + http.StatusUnauthorized, + map[string]string{}, + &UpdateSupplyTimeslotParams{}, + `{ + "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.FBO().UpdateSupplyTimeslot(ctx, test.params) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &UpdateSupplyTimeslotResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} + +func TestGetSupplyTimeslotStatus(t *testing.T) { + t.Parallel() + + tests := []struct { + statusCode int + headers map[string]string + params *GetSupplyTimeslotStatusParams + response string + }{ + // Test Ok + { + http.StatusOK, + map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, + &GetSupplyTimeslotStatusParams{ + OperationId: "string", + }, + `{ + "errors": [ + "UPDATE_TIMESLOT_ERROR_UNSPECIFIED" + ], + "status": "STATUS_UNSPECIFIED" + }`, + }, + // Test No Client-Id or Api-Key + { + http.StatusUnauthorized, + map[string]string{}, + &GetSupplyTimeslotStatusParams{}, + `{ + "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.FBO().GetSupplyTimeslotStatus(ctx, test.params) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &GetSupplyTimeslotStatusResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} + +func TestCreatePass(t *testing.T) { + t.Parallel() + + tests := []struct { + statusCode int + headers map[string]string + params *CreatePassParams + response string + }{ + // Test Ok + { + http.StatusOK, + map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, + &CreatePassParams{ + SupplyOrderId: 123, + Vehicle: GetSupplyRequestInfoVehicle{ + DriverName: "string", + DriverPhone: "string", + VehicleModel: "string", + VehicleNumber: "string", + }, + }, + `{ + "error_reasons": [ + "SET_VEHICLE_ERROR_UNSPECIFIED" + ], + "operation_id": "string" + }`, + }, + // Test No Client-Id or Api-Key + { + http.StatusUnauthorized, + map[string]string{}, + &CreatePassParams{}, + `{ + "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.FBO().CreatePass(ctx, test.params) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &CreatePassResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} + +func TestGetPass(t *testing.T) { + t.Parallel() + + tests := []struct { + statusCode int + headers map[string]string + params *GetPassParams + response string + }{ + // Test Ok + { + http.StatusOK, + map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, + &GetPassParams{ + OperationId: "string", + }, + `{ + "errors": [ + "SET_VEHICLE_ERROR_UNSPECIFIED" + ], + "result": "Unknown" + }`, + }, + // Test No Client-Id or Api-Key + { + http.StatusUnauthorized, + map[string]string{}, + &GetPassParams{}, + `{ + "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.FBO().GetPass(ctx, test.params) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &GetPassResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} + +func TestGetSupplyContent(t *testing.T) { + t.Parallel() + + tests := []struct { + statusCode int + headers map[string]string + params *GetSupplyContentParams + response string + }{ + // Test Ok + { + http.StatusOK, + map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, + &GetSupplyContentParams{ + BundleIds: []string{"string"}, + IsAsc: true, + Limit: 0, + Query: "string", + SortField: "UNSPECIFIED", + }, + `{ + "items": [ + { + "icon_path": "string", + "sku": 0, + "name": "string", + "quantity": 0, + "barcode": "string", + "product_id": 0, + "quant": 0, + "is_quant_editable": true, + "volume_in_litres": 0, + "total_volume_in_litres": 0, + "contractor_item_code": "string", + "sfbo_attribute": "ITEM_SFBO_ATTRIBUTE_UNSPECIFIED", + "shipment_type": "BUNDLE_ITEM_SHIPMENT_TYPE_UNSPECIFIED" + } + ], + "total_count": 0, + "has_next": true, + "last_id": "string" + }`, + }, + // Test No Client-Id or Api-Key + { + http.StatusUnauthorized, + map[string]string{}, + &GetSupplyContentParams{}, + `{ + "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.FBO().GetSupplyContent(ctx, test.params) + if err != nil { + t.Error(err) + continue + } + + compareJsonResponse(t, test.response, &GetSupplyContentResponse{}) + + if resp.StatusCode != test.statusCode { + t.Errorf("got wrong status code: got: %d, expected: %d", resp.StatusCode, test.statusCode) + } + } +} diff --git a/ozon/returns.go b/ozon/returns.go index 3738bf3..8c85193 100644 --- a/ozon/returns.go +++ b/ozon/returns.go @@ -12,125 +12,6 @@ type Returns struct { client *core.Client } -type GetFBOReturnsParams struct { - // Filter - Filter *GetFBOReturnsFilter `json:"filter,omitempty"` - - // Identifier of the last value on the page. Leave this field blank in the first request. - // - // To get the next values, specify the recieved value in the next request in the `last_id` parameter - LastId int64 `json:"last_id"` - - // Number of values in the response - Limit int64 `json:"limit"` -} - -type GetFBOReturnsFilter struct { - // Shipment number - PostingNumber string `json:"posting_number"` - - // Return status - Status []GetFBOReturnsFilterStatus `json:"status"` -} - -type GetFBOReturnsResponse struct { - core.CommonResponse - - // Identifier of the last value on the page - LastId int64 `json:"last_id"` - - // Returns information - Returns []GetFBOReturnsReturn `json:"returns"` -} - -type GetFBOReturnsReturn struct { - // Time when a return was received from the customer - AcceptedFromCustomerMoment time.Time `json:"accepted_from_customer_moment"` - - // Seller identifier - CompanyId int64 `json:"company_id"` - - // Current return location - CurrentPlaceName string `json:"current_place_name"` - - // Return destination - DestinationPlaceName string `json:"dst_place_name"` - - // Return shipment identifier - Id int64 `json:"id"` - - // Indication that the package has been opened. true, if it has been - IsOpened bool `json:"is_opened"` - - // Shipment number - PostingNumber string `json:"posting_number"` - - // Unique return record identifier - ReturnId int64 `json:"return_id"` - - // Return reason - ReturnReasonName string `json:"return_reason_name"` - - // Return delivery time to the Ozon warehouse - ReturnedToOzonMoment time.Time `json:"returned_to_ozon_moment"` - - // Product identifier in the Ozon system, SKU - SKU int64 `json:"sku"` - - // Return status - Status GetFBOReturnsReturnStatus `json:"status_name"` -} - -// Method for getting information on returned products that are sold from the Ozon warehouse -func (c Returns) GetFBOReturns(ctx context.Context, params *GetFBOReturnsParams) (*GetFBOReturnsResponse, error) { - url := "/v3/returns/company/fbo" - - resp := &GetFBOReturnsResponse{} - - 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 GetFBSReturnsParams struct { - // Filter - Filter *GetFBSReturnsFilter `json:"filter,omitempty"` - - // Number of values in the response: - // - maximum — 1000, - // - minimum — 1 - Limit int64 `json:"limit"` - - // Return identifier that was loaded the last time. - // Return identifiers with the higher value than `last_id` - // will be returned in the response. - LastId int64 `json:"offset"` -} - -type GetFBSReturnsFilter struct { - // Last day of free storage - LastFreeWaitingDay GetFBSReturnsFilterTimeRange `json:"last_free_waiting_dat"` - - // Order ID - OrderId int64 `json:"order_id"` - - // Shipment ID - PostingNumber []string `json:"posting_number"` - - // Product name - ProductName string `json:"product_name"` - - // Product ID - ProductOfferId string `json:"product_offer_id"` - - // Return status - Status GetFBSReturnsFilterStatus `json:"status"` -} - type GetFBSReturnsFilterTimeRange struct { // The beginning of the period. // @@ -147,118 +28,6 @@ type GetFBSReturnsFilterTimeRange struct { TimeTo time.Time `json:"time_to"` } -type GetFBSReturnsResponse struct { - core.CommonResponse - - // Return identifier that was loaded the last time. - // Return identifiers with the higher value than `last_id` - // will be returned in the response - LastId int64 `json:"last_id"` - - // Returns information - Returns []GetFBSReturnResultReturn `json:"returns"` -} - -type GetFBSReturnResultReturn struct { - // Bottom barcode on the product label - ClearingId int64 `json:"clearing_id"` - - // Commission fee - Commission float64 `json:"commission"` - - // Commission percentage - CommissionPercent float64 `json:"commission_percent"` - - // Product item identifier in the Ozon logistics system - ExemplarId int64 `json:"exemplar_id"` - - // Return identifier in the Ozon accounting system - Id int64 `json:"id"` - - // If the product is in transit — true - IsMoving bool `json:"is_moving"` - - // Indication that the package has been opened. true, if it has been - IsOpened bool `json:"is_opened"` - - // Last day of free storage - LastFreeWaitingDay string `json:"last_free_waiting_day"` - - // ID of the warehouse the product is being transported to - PlaceId int64 `json:"place_id"` - - // Intermediate return point - MovingToPlaceName string `json:"moving_to_place_name"` - - // Delivery cost - PickingAmount float64 `json:"picking_amount"` - - // Shipment number - PostingNumber string `json:"posting_number"` - - PickingTag string `json:"picking_tag"` - - // Current product price without a discount - Price float64 `json:"price"` - - // Product price without commission - PriceWithoutCommission float64 `json:"price_without_commission"` - - // Product identifier — SKU - ProductId int64 `json:"product_id"` - - // Product name - ProductName string `json:"product_name"` - - // Product quantity - Quantity int64 `json:"quantity"` - - // Barcode on the return label. Use this parameter value to work with the return label - ReturnBarcode string `json:"return_barcode"` - - // Package unit identifier in the Ozon logistics system - ReturnClearingId int64 `json:"return_clearing_id"` - - // Product return date - ReturnDate string `json:"return_date"` - - // Return reason - ReturnReasonName string `json:"return_reason_name"` - - // Date when the product is ready to be handed over to the seller - WaitingForSellerDate string `json:"waiting_for_seller_date_time"` - - // Date of handing over the product to the seller - ReturnedToSellerDate string `json:"returned_to_seller_date_time"` - - // Return storage period in days - WaitingForSellerDays int64 `json:"waiting_for_seller_days"` - - // Return storage cost - ReturnsKeepingCost float64 `json:"returns_keeping_cost"` - - // Product identifier in the Ozon system, SKU - SKU int64 `json:"sku"` - - // Return status - Status string `json:"status"` -} - -// Method for getting information on returned products that are sold from the seller's warehouse -func (c Returns) GetFBSReturns(ctx context.Context, params *GetFBSReturnsParams) (*GetFBSReturnsResponse, error) { - url := "/v3/returns/company/fbs" - - resp := &GetFBSReturnsResponse{} - - 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 GetRFBSReturnsParams struct { // Filter Filter *GetRFBSReturnsFilter `json:"filter,omitempty"` diff --git a/ozon/returns_test.go b/ozon/returns_test.go index 0e3eb30..60ebfd1 100644 --- a/ozon/returns_test.go +++ b/ozon/returns_test.go @@ -8,193 +8,6 @@ import ( core "github.com/diphantxm/ozon-api-client" ) -func TestGetFBOReturns(t *testing.T) { - t.Parallel() - - tests := []struct { - statusCode int - headers map[string]string - params *GetFBOReturnsParams - response string - }{ - // Test Ok - { - http.StatusOK, - map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, - &GetFBOReturnsParams{ - Filter: &GetFBOReturnsFilter{ - PostingNumber: "some number", - }, - LastId: 123, - Limit: 100, - }, - `{ - "last_id": 0, - "returns": [ - { - "accepted_from_customer_moment": "2019-08-24T14:15:22Z", - "company_id": 123456789, - "current_place_name": "my-place", - "dst_place_name": "that-place", - "id": 123456789, - "is_opened": true, - "posting_number": "some number", - "return_reason_name": "ripped", - "returned_to_ozon_moment": "2019-08-24T14:15:22Z", - "sku": 123456789, - "status_name": "delivering" - } - ] - }`, - }, - // Test No Client-Id or Api-Key - { - http.StatusUnauthorized, - map[string]string{}, - &GetFBOReturnsParams{}, - `{ - "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().GetFBOReturns(ctx, test.params) - if err != nil { - t.Error(err) - continue - } - - compareJsonResponse(t, test.response, &GetFBOReturnsResponse{}) - - 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") - } - } - } - } -} - -func TestGetFBSReturns(t *testing.T) { - t.Parallel() - - tests := []struct { - statusCode int - headers map[string]string - params *GetFBSReturnsParams - response string - }{ - // Test Ok - { - http.StatusOK, - map[string]string{"Client-Id": "my-client-id", "Api-Key": "my-api-key"}, - &GetFBSReturnsParams{ - Filter: &GetFBSReturnsFilter{ - PostingNumber: []string{"07402477-0022-2"}, - Status: "returned_to_seller", - }, - Limit: 1000, - LastId: 0, - }, - `{ - "last_id": 0, - "returns": [ - { - "clearing_id": 23, - "commission": 21, - "commission_percent": 0, - "exemplar_id": 42, - "id": 123, - "is_moving": true, - "is_opened": true, - "last_free_waiting_day": "string", - "place_id": 122, - "moving_to_place_name": "string", - "picking_amount": 0, - "posting_number": "string", - "picking_tag": "string", - "price": 0, - "price_without_commission": 0, - "product_id": 2222, - "product_name": "string", - "quantity": 0, - "return_barcode": "string", - "return_clearing_id": 0, - "return_date": "string", - "return_reason_name": "string", - "waiting_for_seller_date_time": "string", - "returned_to_seller_date_time": "string", - "waiting_for_seller_days": 0, - "returns_keeping_cost": 0, - "sku": 33332, - "status": "string" - } - ] - }`, - }, - // Test No Client-Id or Api-Key - { - http.StatusUnauthorized, - map[string]string{}, - &GetFBSReturnsParams{}, - `{ - "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().GetFBSReturns(ctx, test.params) - if err != nil { - t.Error(err) - continue - } - - compareJsonResponse(t, test.response, &GetFBSReturnsResponse{}) - - 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].ProductId == 0 { - t.Errorf("Product id cannot be 0") - } - if resp.Returns[0].SKU == 0 { - t.Errorf("SKU cannot be 0") - } - if resp.Returns[0].Status == "" { - t.Errorf("Status cannot be empty") - } - } - } - } -} - func TestGetRFBSReturns(t *testing.T) { t.Parallel()