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
60 changes: 59 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ func (c *Client) CustomersCombine(customers []Customer, resultCustomer Customer)
//
// var client = retailcrm.New("https://demo.url", "09jIJ")
//
// data, status, err := client.CustomersCombine(retailcrm.Customer{
// data, status, err := client.CustomerCreate(retailcrm.Customer{
// FirstName: "Ivan",
// LastName: "Ivanov",
// Patronymic: "Ivanovich",
Expand Down Expand Up @@ -5135,6 +5135,34 @@ func (c *Client) Inventories(parameters InventoriesRequest) (InventoriesResponse
return resp, status, nil
}

// StoreInventories returns leftover stocks and purchasing prices.
//
// For more information see https://docs.retailcrm.ru/Developers/API/APIMethods#get--api-v5-store-inventories
//
// Example:
//
// var client = retailcrm.New("https://demo.url", "09jIJ")
//
// data, status, err := client.StoreInventories(retailcrm.StoreInventoriesRequest{
// Filter: retailcrm.InventoriesFilter{Details: 1, ProductActive: 1},
// Page: 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.Offers {
// log.Printf("%v\n", value)
// }
func (c *Client) StoreInventories(parameters StoreInventoriesRequest) (StoreInventoriesResponse, int, error) {
return c.Inventories(parameters)
}

// InventoriesUpload updates the leftover stocks and purchasing prices
//
// For more information see http://www.simla.com/docs/Developers/API/APIVersions/APIv5#post--api-v5-store-inventories-upload
Expand Down Expand Up @@ -5342,6 +5370,36 @@ func (c *Client) Products(parameters ProductsRequest) (ProductsResponse, int, er
return resp, status, nil
}

// StoreProducts returns list of products and SKU.
//
// For more information see https://docs.retailcrm.ru/Developers/API/APIMethods#get--api-v5-store-products
//
// Example:
//
// var client = retailcrm.New("https://demo.url", "09jIJ")
//
// data, status, err := client.StoreProducts(retailcrm.StoreProductsRequest{
// Filter: retailcrm.ProductsFilter{
// Active: 1,
// MinPrice: 1000,
// },
// })
//
// 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.Products {
// log.Printf("%v\n", value)
// }
func (c *Client) StoreProducts(parameters StoreProductsRequest) (StoreProductsResponse, int, error) {
return c.Products(parameters)
}

// ProductsProperties returns list of item properties, matching the specified filters
//
// For more information see http://www.simla.com/docs/Developers/API/APIVersions/APIv5#get--api-v5-store-products-properties
Expand Down
109 changes: 107 additions & 2 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6180,10 +6180,11 @@ func TestClient_Packs(t *testing.T) {
gock.New(crmURL).
Get("/orders/packs").
MatchParam("page", "1").
MatchParam("filter[stores][]", "main").
Reply(200).
BodyString(`{"success": true}`)

data, status, err := c.Packs(PacksRequest{Filter: PacksFilter{}, Page: 1})
data, status, err := c.Packs(PacksRequest{Filter: PacksFilter{Stores: []string{"main"}}, Page: 1})
if err != nil {
t.Errorf("%v", err)
}
Expand Down Expand Up @@ -6267,6 +6268,52 @@ func TestClient_Inventories_Fail(t *testing.T) {
}
}

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

defer gock.Off()

gock.New(crmURL).
Get("/store/inventories").
MatchParam("filter[details]", "1").
MatchParam("filter[productActive]", "1").
MatchParam("filter[offerActive]", "1").
MatchParam("filter[offerExternalId][]", "offer-1").
MatchParam("limit", "250").
Reply(http.StatusOK).
BodyString(`{
"success": true,
"offers": [{
"id": 76,
"externalId": "offer-1",
"xmlId": "xml-1",
"quantity": 5,
"stores": [{"store": "main", "quantity": 5, "purchasePrice": 10}]
}]
}`)

data, status, err := c.StoreInventories(StoreInventoriesRequest{
Filter: InventoriesFilter{
Details: 1,
ProductActive: 1,
OfferActive: 1,
OfferExternalID: []string{"offer-1"},
},
Limit: 250,
})
if err != nil {
t.Errorf("%v", err)
}

if status != http.StatusOK {
t.Errorf("%v", err)
}

assert.True(t, data.Success)
assert.Len(t, data.Offers, 1)
assert.Equal(t, "main", data.Offers[0].Stores[0].Store)
}

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

Expand Down Expand Up @@ -6679,6 +6726,62 @@ func TestClient_Products(t *testing.T) {
}
}

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

defer gock.Off()

gock.New(crmURL).
Get("/store/products").
MatchParam("filter[groups][]", "10").
MatchParam("filter[catalogs][]", "2").
MatchParam("filter[offerXmlId]", "offer-xml-id").
MatchParam("filter[groupExternalId]", "group-external-id").
MatchParam("filter[sinceUpdatedAt]", "2026-05-06 12:00:00").
MatchParam("filter[sinceId]", "75").
MatchParam("filter[productType]", "product").
MatchParam("filter[markable]", "1").
Reply(http.StatusOK).
BodyString(`{
"success": true,
"products": [{
"id": 222,
"catalogId": 2,
"type": "product",
"externalId": "product-external-id",
"groups": [{"id": 10, "externalId": "group-external-id"}],
"offers": [{"id": 76, "xmlId": "offer-xml-id"}],
"markingProvider": "chestny_znak"
}]
}`)

g, status, err := c.StoreProducts(StoreProductsRequest{
Filter: ProductsFilter{
Groups: []int{10},
Catalogs: []int{2},
OfferXMLID: "offer-xml-id",
GroupExternalID: "group-external-id",
SinceUpdatedAt: "2026-05-06 12:00:00",
SinceID: 75,
ProductType: "product",
Markable: 1,
},
})
if err != nil {
t.Errorf("%v", err)
}

if status != http.StatusOK {
t.Errorf("%v", err)
}

assert.True(t, g.Success)
assert.Len(t, g.Products, 1)
assert.Equal(t, "group-external-id", g.Products[0].Groups[0].ExternalID)
assert.Equal(t, "offer-xml-id", g.Products[0].Offers[0].XMLID)
assert.Equal(t, "chestny_znak", g.Products[0].MarkingProvider)
}

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

Expand Down Expand Up @@ -6744,7 +6847,7 @@ func TestClient_DeliveryTracking(t *testing.T) {
defer gock.Off()

p := url.Values{
"statusUpdate": {`[{"deliveryId":"123","history":[{"code":"1","updatedAt":"2020-01-01T00:00:00:000"}]}]`},
"statusUpdate": {`[{"deliveryId":"123","cost":99.5,"history":[{"code":"1","updatedAt":"2020-01-01T00:00:00:000"}],"extraData":{"gate":"A1"}}]`},
}

gock.New(crmURL).
Expand All @@ -6756,10 +6859,12 @@ func TestClient_DeliveryTracking(t *testing.T) {

g, status, err := c.DeliveryTracking([]DeliveryTrackingRequest{{
DeliveryID: "123",
Cost: 99.5,
History: []DeliveryHistoryRecord{{
Code: "1",
UpdatedAt: "2020-01-01T00:00:00:000",
}},
ExtraData: map[string]string{"gate": "A1"},
}}, "subcode")

if err != nil {
Expand Down
11 changes: 9 additions & 2 deletions filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ type SegmentsFilter struct {
// PacksFilter type.
type PacksFilter struct {
Ids []int `url:"ids,omitempty,brackets"`
Stores []string `url:"stores,omitempty"`
Stores []string `url:"stores,omitempty,brackets"`
ItemID int `url:"itemId,omitempty"`
OfferXMLID string `url:"offerXmlId,omitempty"`
OfferExternalID string `url:"offerExternalId,omitempty"`
Expand Down Expand Up @@ -338,6 +338,7 @@ type ProductsFilter struct {
Ids []int `url:"ids,omitempty,brackets"`
OfferIds []int `url:"offerIds,omitempty,brackets"`
Active int `url:"active,omitempty"`
Markable int `url:"markable,omitempty"`
Recommended int `url:"recommended,omitempty"`
Novelty int `url:"novelty,omitempty"`
Stock int `url:"stock,omitempty"`
Expand All @@ -348,7 +349,7 @@ type ProductsFilter struct {
MinPurchasePrice float32 `url:"minPurchasePrice,omitempty"`
MaxPrice float32 `url:"maxPrice,omitempty"`
MinPrice float32 `url:"minPrice,omitempty"`
Groups string `url:"groups,omitempty"`
Groups []int `url:"groups,omitempty,brackets"`
Name string `url:"name,omitempty"`
ClassSegment string `url:"classSegment,omitempty"`
XMLID string `url:"xmlId,omitempty"`
Expand All @@ -357,7 +358,13 @@ type ProductsFilter struct {
URL string `url:"url,omitempty"`
URLLike string `url:"urlLike,omitempty"`
PriceType string `url:"priceType,omitempty"`
Catalogs []int `url:"catalogs,omitempty,brackets"`
OfferExternalID string `url:"offerExternalId,omitempty"`
OfferXMLID string `url:"offerXmlId,omitempty"`
GroupExternalID string `url:"groupExternalId,omitempty"`
SinceUpdatedAt string `url:"sinceUpdatedAt,omitempty"`
SinceID int `url:"sinceId,omitempty"`
ProductType string `url:"productType,omitempty"`
Sites []string `url:"sites,omitempty,brackets"`
Properties map[string]string `url:"properties,omitempty,brackets"`
}
Expand Down
7 changes: 7 additions & 0 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ type InventoriesRequest struct {
Page int `url:"page,omitempty"`
}

// StoreInventoriesRequest type.
type StoreInventoriesRequest = InventoriesRequest

// ProductsGroupsRequest type.
type ProductsGroupsRequest struct {
Filter ProductsGroupsFilter `url:"filter,omitempty"`
Expand All @@ -172,6 +175,9 @@ type ProductsRequest struct {
Page int `url:"page,omitempty"`
}

// StoreProductsRequest type.
type StoreProductsRequest = ProductsRequest

// ProductsPropertiesRequest type.
type ProductsPropertiesRequest struct {
Filter ProductsPropertiesFilter `url:"filter,omitempty"`
Expand All @@ -183,6 +189,7 @@ type ProductsPropertiesRequest struct {
type DeliveryTrackingRequest struct {
DeliveryID string `json:"deliveryId,omitempty"`
TrackNumber string `json:"trackNumber,omitempty"`
Cost float32 `json:"cost,omitempty"`
History []DeliveryHistoryRecord `json:"history,omitempty"`
ExtraData map[string]string `json:"extraData,omitempty"`
}
Expand Down
6 changes: 6 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ type InventoriesResponse struct {
Offers []Offer `json:"offers,omitempty"`
}

// StoreInventoriesResponse type.
type StoreInventoriesResponse = InventoriesResponse

// StoreUploadResponse type.
type StoreUploadResponse struct {
Success bool `json:"success"`
Expand All @@ -383,6 +386,9 @@ type ProductsResponse struct {
Products []Product `json:"products,omitempty"`
}

// StoreProductsResponse type.
type StoreProductsResponse = ProductsResponse

type ProductEditNotFoundResponse struct {
ID string `json:"id"`
ExternalID string `json:"externalId,omitempty"`
Expand Down
Loading
Loading