Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2547,6 +2547,64 @@ func (c *Client) DeliveryShipments(parameters DeliveryShipmentsRequest) (Deliver
return resp, status, nil
}

// DeliveryCalculate calculates delivery cost
//
// For more information see https://docs.retailcrm.ru/Developers/API/APIMethods#post--api-v5-delivery-calculate
//
// Example:
//
// var client = retailcrm.New("https://demo.url", "09jIJ")
//
// data, status, err := client.DeliveryCalculate(retailcrm.DeliveryCalculateRequest{
// DeliveryTypeCodes: []string{"courier"},
// Order: retailcrm.DeliveryCalculateOrder{
// Weight: 1200,
// Delivery: &retailcrm.DeliveryCalculateSerializedDelivery{
// Address: &retailcrm.Address{
// City: "Москва",
// Building: "1",
// },
// },
// },
// })
//
// if err != nil {
// if apiErr, ok := retailcrm.AsAPIError(err); ok {
// log.Fatalf("http status: %d, %s", status, apiErr.String())
// }
//
// log.Fatalf("http status: %d, error: %s", status, err)
// }
//
// for _, value := range data.Calculations {
// log.Printf("%v\n", value)
// }
func (c *Client) DeliveryCalculate(parameters DeliveryCalculateRequest) (DeliveryCalculateResponse, int, error) {
var resp DeliveryCalculateResponse

orderJSON, err := marshalToString(&parameters.Order)
if err != nil {
return resp, 0, err
}

p := url.Values{
"deliveryTypeCodes[]": parameters.DeliveryTypeCodes,
"order": {orderJSON},
}

data, status, err := c.PostRequest("/delivery/calculate", p)
if err != nil {
return resp, status, err
}

err = json.Unmarshal(data, &resp)
if err != nil {
return resp, status, err
}

return resp, status, nil
}

// DeliveryShipmentCreate creates shipment
//
// For more information see http://www.simla.com/docs/Developers/API/APIVersions/APIv5#post--api-v5-delivery-shipments-create
Expand Down
108 changes: 108 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6797,6 +6797,114 @@ func TestClient_DeliveryShipments_Fail(t *testing.T) {
}
}

func TestClient_DeliveryCalculate(t *testing.T) {
defer gock.Off()

req := DeliveryCalculateRequest{
DeliveryTypeCodes: []string{"courier", "pickup"},
Order: DeliveryCalculateOrder{
Weight: 1.2,
Length: 10,
Width: 20,
Height: 30,
Items: []DeliveryCalculateOrderProduct{
{
InitialPrice: 1000,
DiscountManualAmount: 100,
DiscountManualPercent: 5,
Quantity: 2,
},
},
Delivery: &DeliveryCalculateSerializedDelivery{
Date: "2024-01-02",
Time: &DeliveryTime{
From: "10:00",
To: "18:00",
},
Address: &Address{
City: "Москва",
Street: "Ленина",
Building: "1",
},
},
},
}

orderJSON, err := json.Marshal(req.Order)
assert.NoError(t, err)

p := url.Values{
"deliveryTypeCodes[]": req.DeliveryTypeCodes,
"order": {string(orderJSON)},
}

gock.New(crmURL).
Post(prefix + "/delivery/calculate").
BodyString(p.Encode()).
Reply(http.StatusOK).
BodyString(`{"success": true, "calculations": [{"code": "courier", "available": true, "vatRate": "20", "cost": 350.5}]}`)

res, status, err := client().DeliveryCalculate(req)

if err != nil {
t.Errorf("%v", err)
}

if !statuses[status] {
t.Errorf("%v", err)
}

assert.True(t, res.Success)
assert.Len(t, res.Calculations, 1)
assert.Equal(t, "courier", res.Calculations[0].Code)
assert.True(t, res.Calculations[0].Available)
assert.Equal(t, "20", res.Calculations[0].VatRate)
assert.Equal(t, float32(350.5), res.Calculations[0].Cost)
}

func TestClient_DeliveryCalculate_Fail(t *testing.T) {
defer gock.Off()

req := DeliveryCalculateRequest{
DeliveryTypeCodes: []string{codeFail},
Order: DeliveryCalculateOrder{
Delivery: &DeliveryCalculateSerializedDelivery{
Address: &Address{
City: "Москва",
},
},
},
}

orderJSON, err := json.Marshal(req.Order)
assert.NoError(t, err)

p := url.Values{
"deliveryTypeCodes[]": req.DeliveryTypeCodes,
"order": {string(orderJSON)},
}

gock.New(crmURL).
Post(prefix + "/delivery/calculate").
BodyString(p.Encode()).
Reply(http.StatusBadRequest).
BodyString(`{"success": false, "errorMsg": "Errors in the input parameters"}`)

res, status, err := client().DeliveryCalculate(req)

if err == nil {
t.Error("Error must be return")
}

if status < http.StatusBadRequest {
t.Error(statusFail)
}

if res.Success != false {
t.Error(successFail)
}
}

func TestClient_Cost(t *testing.T) {
c := client()

Expand Down
6 changes: 6 additions & 0 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ type DeliveryShipmentsRequest struct {
Page int `url:"page,omitempty"`
}

// DeliveryCalculateRequest type.
type DeliveryCalculateRequest struct {
DeliveryTypeCodes []string
Order DeliveryCalculateOrder
}

// ClearCartRequest type.
type ClearCartRequest struct {
ClearedAt string `json:"clearedAt,omitempty"`
Expand Down
6 changes: 6 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ type DeliveryShipmentsResponse struct {
DeliveryShipments []DeliveryShipment `json:"deliveryShipments,omitempty"`
}

// DeliveryCalculateResponse type.
type DeliveryCalculateResponse struct {
SuccessfulResponse
Calculations []DeliveryCalculation `json:"calculations,omitempty"`
}

// DeliveryShipmentResponse type.
type DeliveryShipmentResponse struct {
Success bool `json:"success"`
Expand Down
34 changes: 34 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,40 @@ type OrderDeliveryData struct {
AdditionalFields map[string]interface{}
}

// DeliveryCalculateOrder type.
type DeliveryCalculateOrder struct {
Weight float32 `json:"weight,omitempty"`
Length int `json:"length,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Items []DeliveryCalculateOrderProduct `json:"items,omitempty"`
Delivery *DeliveryCalculateSerializedDelivery `json:"delivery,omitempty"`
}

// DeliveryCalculateOrderProduct type.
type DeliveryCalculateOrderProduct struct {
InitialPrice float32 `json:"initialPrice,omitempty"`
DiscountManualAmount float32 `json:"discountManualAmount,omitempty"`
DiscountManualPercent float32 `json:"discountManualPercent,omitempty"`
Quantity float32 `json:"quantity,omitempty"`
}

// DeliveryCalculateSerializedDelivery type.
type DeliveryCalculateSerializedDelivery struct {
Date string `json:"date,omitempty"`
Time *DeliveryTime `json:"time,omitempty"`
Address *Address `json:"address,omitempty"`
}

// DeliveryCalculation type.
type DeliveryCalculation struct {
Code string `json:"code,omitempty"`
Available bool `json:"available,omitempty"`
VatRate string `json:"vatRate,omitempty"`
Cost float32 `json:"cost,omitempty"`
Description string `json:"description,omitempty"`
}

// SetCartItem type.
type SetCartItem struct {
Quantity float64 `json:"quantity,omitempty"`
Expand Down
Loading