Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

10 changed files with 202 additions and 353 deletions

View File

@ -1,21 +0,0 @@
Лицензия MIT (MIT)
Авторские права (c) 2024 Павел Синицин
Настоящим предоставляется бесплатное разрешение любому лицу, получившему копию
этого программного обеспечения и сопутствующей документации (в дальнейшем "Программное обеспечение"), использовать
Программное обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние,
публикацию, распространение, сублицензирование и/или продажу копий
Программного обеспечения, а также лицам, которым предоставляется данное Программное обеспечение, при соблюдении
следующих условий:
Указанное выше уведомление об авторских правах и данное разрешение должны быть включены во все
копии или значительные части этого Программного обеспечения.
Программное обеспечение предоставляется "КАК ЕСТЬ", без каких-либо гарантий, явных или
подразумеваемых, включая, но не ограничиваясь, гарантии товарной пригодности, пригодности
для конкретной цели и ненарушения прав. Ни в коем случае авторы или
владельцы авторских прав не несут ответственности за любые претензии, убытки или другие обязательства, будь то в иске по
договору, деликту или ином,
возникающем из, связанного с Программным обеспечением или использования Программного обеспечения или других действий с
Программным обеспечением.

133
README.md
View File

@ -1,133 +0,0 @@
# API клиент бизнес-платформы IEK
## Содержание
- [Начало работы](#начало-работы)
- [Установка](#установка)
- [Использование](#использование)
- [Доступные методы](#доступные-методы)
- [Используемые инструменты](#используемые-инструменты)
- [Авторы](#авторы)
- [Лицензия](#лицензия)
## Начало работы
Эти инструкции помогут вам запустить копию проекта на вашем локальном компьютере для целей разработки и тестирования.
#### Установка Go
Убедитесь, что у вас установлена последняя версия Go. Инструкции по установке можно найти на официальном
сайте [Go](https://golang.org/doc/install).
Пример:
```sh
go version go1.23.1
```
### Установка
Пошаговая инструкция по созданию окружения.
1. Установите проект с помощью `go get`
```sh
go get -u gitea.24example.ru/spavelit/bpiek
```
2. Установите зависимости
```sh
go mod tidy
```
### Использование
Инструкции по использованию вашего проекта.
#### Запуск приложения
Пример:
```sh
go run main.go
```
#### Пример использования
Примечание:
Добавьте пример кода, чтобы пользователи могли быстро начать работу с вашим проектом.
```go
package main
import (
"encoding/json"
"fmt"
bpiek "gitea.24example.ru/spavelit/bpiek/api"
)
func main() {
credentials := bpiek.Credentials{
Username: "mail@example.ru",
Password: "password",
}
api := bpiek.NewApi(credentials)
result, err := api.GetRemainsAndPlanresidues()
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(result[1], "", " ")
fmt.Print(string(b))
}
```
### Доступные методы
В данном разделе приведены основные методы, доступные в API клиенте для бизнес-платформы IEK:
1. `NewApi(credentials bpiek.Credentials)`
- Создает новый экземпляр API клиента с предоставленными учетными данными.
2. `GetParentCategories() ([]model.Category, error)`
- Возвращает массив категорий каталога 1-ого уровня.
3. `GetCategories() ([]model.Category, error)`
- Возвращает массив с категориями.
4. `GetTreeCategories() ([]model.TreeCategories, error)`
- Возвращает дерево категорий.
5. `GetProducts() ([]model.Product, error)`
- Возвращает массив с продукцией.
6. `GetProductByArticle(article string) (model.Product, error)`
- Возвращает товар по артикулу.
7. `GetRemainsAndPlanresidues() ([]model.ShortProduct, error)`
- Возвращает массив, в котором содержатся актуальные цены
и остатки товаров.
Эти методы могут использоваться для взаимодействия с бизнес-платформой IEK в рамках вашего проекта. Подробная
документация каждого метода доступна в исходниках или официальной документации БП IEK.
## Используемые инструменты
Список инструментов и библиотек, которые использовались при создании проекта.
* [GoLang](https://golang.org/) - Язык программирования.
* [Resty](https://github.com/go-resty/resty) - Simple HTTP and REST client library for Go.
## Авторы
* **Павел Синицин** - *Rosar-L* - [Gitea](https://gitea.24example.ru/spavelit/)
## Лицензия
Этот проект лицензирован под лицензией MIT - подробности смотрите в файле [LICENSE.md](LICENSE.md).

View File

@ -5,27 +5,22 @@ import (
"gitea.24example.ru/spavelit/bpiek/model"
)
type (
Api struct {
Client *client.Client
}
Credentials struct {
Username string
Password string
}
type Api struct {
Client *client.Client
}
Method interface {
GetParentCategories() ([]model.Category, error) // Возвращает массив категорий каталога 1-ого уровня.
GetCategories() ([]model.Category, error) // Возвращает массив с категориями
GetTreeCategories() ([]model.TreeCategories, error) // Возвращает дерево категорий
GetProducts() ([]model.Product, error) // Возвращает массив с продукцией
GetProductByArticle(article string) (model.Product, error) // Возвращает товар по артикул
GetRemainsAndPlanresidues() ([]model.ShortProduct, error) // Возвращает массив, в котором содержатся актуальные цены и остатки товаров.
}
)
type Method interface {
GetParentCategories() ([]model.Category, error)
GetCategories() ([]model.Category, error)
GetTreeCategories() ([]model.TreeCategories, error)
func NewApi(credentials Credentials) Method {
GetProducts() ([]model.Product, error)
GetProductByArticle(article string) (model.Product, error)
GetRemainsAndPlanresidues() ([]model.ShortProduct, error)
}
func NewApi(credentials client.Credentials) Method {
return &Api{
Client: client.NewClient(credentials.Username, credentials.Password),
Client: client.NewClient(credentials),
}
}

View File

@ -6,13 +6,13 @@ import (
"gitea.24example.ru/spavelit/bpiek/utils"
)
var _categories []model.Category
var _parentCategories []model.Category
var _treeCategories []model.TreeCategories
var categories []model.Category
var parentCategories []model.Category
var treeCategories []model.TreeCategories
func (a *Api) GetCategories() ([]model.Category, error) {
if len(_categories) > 0 {
return _categories, nil
if len(categories) > 0 {
return categories, nil
}
parentCategories, err := a.GetParentCategories()
@ -22,26 +22,23 @@ func (a *Api) GetCategories() ([]model.Category, error) {
}
for _, category := range parentCategories {
_categories = append(_categories, category)
categoriesAndProduct, err := a.GetCategoriesAndProductsBySlugParentCategory(category.Slug)
if err != nil {
return nil, err
}
if len(categoriesAndProduct.Categories) != 0 {
_categories = append(_categories, categoriesAndProduct.Categories...)
categories = append(categories, categoriesAndProduct.Categories...)
}
}
return _categories, nil
return categories, nil
}
func (a *Api) GetParentCategories() ([]model.Category, error) {
if len(_parentCategories) > 0 {
return _parentCategories, nil
if len(parentCategories) > 0 {
return parentCategories, nil
}
apiResponse, err := a.Client.HTTPClient.R().SetResult(&model.CategoryResponse{}).Get("client/catalog")
@ -59,9 +56,9 @@ func (a *Api) GetParentCategories() ([]model.Category, error) {
return nil, errors.New("no categories found")
}
_parentCategories = result
parentCategories = result
return _parentCategories, nil
return parentCategories, nil
}
func (a *Api) GetCategoriesAndProductsBySlugParentCategory(slug string) (*model.CategoriesAndProductsBySlugParentCategoryResponse, error) {
@ -81,20 +78,34 @@ func (a *Api) GetCategoriesAndProductsBySlugParentCategory(slug string) (*model.
}
func (a *Api) GetTreeCategories() ([]model.TreeCategories, error) {
if len(_treeCategories) > 0 {
return _treeCategories, nil
if len(treeCategories) > 0 {
return treeCategories, nil
}
tree := map[string]interface{}{}
categories, err := a.GetCategories()
parentCategories, err := a.GetParentCategories()
if err != nil {
return nil, err
}
utils.ConvertListToNestedDict(categories, tree)
for _, parent := range parentCategories {
tree[parent.Slug] = map[string]interface{}{
"name": parent.Name,
"slug": parent.Slug,
"url": parent.Url,
"children": map[string]interface{}{},
}
_treeCategories = utils.ConvertToNestedList(tree)
categoriesAndProduct, err := a.GetCategoriesAndProductsBySlugParentCategory(parent.Slug)
if err != nil {
return nil, err
}
return _treeCategories, nil
utils.ConvertListToNestedDict(categoriesAndProduct.Categories, tree)
}
treeCategories = utils.ConvertToNestedList(tree)
return treeCategories, nil
}

View File

@ -49,12 +49,7 @@ func (a *Api) GetProductByArticle(article string) (model.Product, error) {
"error getting product by article: " + article)
}
product, ok := apiResponse.Result().(*model.Product)
if !ok {
return model.Product{}, errors.New("failed to parse product from response")
}
return *product, nil
return apiResponse.Result().(model.Product), nil
}
func (a *Api) GetRemainsAndPlanresidues() ([]model.ShortProduct, error) {
@ -82,7 +77,7 @@ func (a *Api) GetRemainsAndPlanresidues() ([]model.ShortProduct, error) {
return nil, errors.New("file remains and planresidues not found")
}
result := apiResponse.Result().(*model.RemainsAndPlanresiduesResponse)
result := apiResponse.Result().(model.RemainsAndPlanresiduesResponse)
if len(result.Products) != 0 {
remainsAndPlanresidues = append(remainsAndPlanresidues, result.Products...)

View File

@ -1,12 +1,15 @@
package client
import (
"github.com/go-resty/resty/v2"
)
import "github.com/go-resty/resty/v2"
// import (
// "net/http"
// "net/url"
// )
const (
AuthApiUrl = "https://bp.iek.ru/oauth/login"
BaseApiUrl = "https://bp.iek.ru/api/catalog/v1/"
AUTH_API_URL = "https://bp.iek.ru/oauth/login"
BASE_API_URL = "https://bp.iek.ru/api/catalog/v1/"
)
type (
@ -24,18 +27,18 @@ type (
}
)
func NewClient(username string, password string) *Client {
func NewClient(credentials Credentials) *Client {
authSuccess := &AuthSuccess{}
client := resty.New()
client.SetBaseURL(BaseApiUrl)
client.SetBaseURL(BASE_API_URL)
response, err := client.R().
SetFormData(map[string]string{
"username": username,
"password": password,
"username": credentials.GetUsername(),
"password": credentials.GetPassword(),
}).
SetResult(&authSuccess).
Post(AuthApiUrl)
Post(AUTH_API_URL)
if err != nil {
panic(err)
@ -46,7 +49,7 @@ func NewClient(username string, password string) *Client {
}
client.SetHeader("Content-Type", "application/json")
client.SetHeader("Authorization", authSuccess.TokenType+" "+authSuccess.AccessToken)
client.SetHeader("Authorization", "Bearer "+authSuccess.AccessToken)
return &Client{
HTTPClient: client,

17
client/credential.go Normal file
View File

@ -0,0 +1,17 @@
package client
type (
// Credentials provides constant credential values.
Credentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
)
func (c *Credentials) GetUsername() string {
return c.Username
}
func (c *Credentials) GetPassword() string {
return c.Password
}

View File

@ -1,15 +1,15 @@
package model
type Category struct {
Slug string `json:"slug"` // Слаг категории
Name string `json:"name"` // Название категории
Url string `json:"url"` // Ссылка на скачивание файла с содержимым категории
ApiUrl string `json:"apiUrl"` // Относительный адрес категории
Slug string `json:"slug"`
Name string `json:"name"`
Url string `json:"url"`
ApiUrl string `json:"apiUrl"`
}
type TreeCategories struct {
Slug string `json:"slug"` // Слаг категории
Name string `json:"name"` // Название категории
Url string `json:"url"` // Относительный адрес категории
Children []TreeCategories `json:"children"` // Children nested categories in TreeCategories
Slug string `json:"slug"`
Name string `json:"name"`
Url string `json:"url"`
Children []TreeCategories `json:"children"`
}

View File

@ -2,168 +2,150 @@ package model
type (
ImageVariant struct {
Url string `json:"url"` // Ссылка
Ext string `json:"ext"` // Расширение
Width int `json:"width"` // Ширина
Url string `json:"url"`
Ext string `json:"ext"`
Width int `json:"width"`
}
Complects struct {
Article string `json:"article"` // Артикул
Name string `json:"name"` // Наименование
Quantity int `json:"quantity"` // Количество
Article string `json:"article"`
Name string `json:"name"`
Quantity int `json:"quantity"`
}
LeftPeriod struct {
Name string `json:"name"` // Название характеристики
Value string `json:"value"` // Значение характеристики
Name string `json:"name"`
Value string `json:"value"`
}
LeftPeriodRaw struct {
Lifespan struct {
Limit string `json:"limit"` // Предельное значение
Value string `json:"value"` // Значение
Units string `json:"units"` // Единицы измерения
} `json:"lifespan"` // Срок службы
Warranty struct {
Value string `json:"value"` // Значение
Units string `json:"units"` // Единицы измерения
} `json:"warranty"` // Гарантийный срок
Lifespan interface{} `json:"lifespan"`
Warranty interface{} `json:"warranty"`
}
DesignFeatures struct {
ImageUrl string `json:"imageUrl"` // Ссылка на изображение
Description string `json:"description"` // Описание
ImageUrl string `json:"imageUrl"`
Description string `json:"description"`
}
Video struct {
Name string `json:"name"` // Наименование
Description string `json:"description"` // Описание
Url string `json:"url"` // Ссылка
Type string `json:"type"` // Тип (ссылка на видео-хостинг или прямая ссылка на скачивание); Enum: "url" "file"
Name string `json:"name"`
Description string `json:"description"`
Url string `json:"url"`
Type string `json:"type"`
}
Software struct {
Name string `json:"name"` // Наименование
Description string `json:"description"` // Описание
Url string `json:"url"` // Ссылка
Size int `json:"size"` // Размер
Name string `json:"name"`
Description string `json:"description"`
Url string `json:"url"`
Size int `json:"size"`
}
Analog struct {
Article string `json:"article"` // Артикул товара
Name string `json:"name"` // Полное название товара
ShortName string `json:"shortName"` // Краткое название
Description string `json:"description"` // Описание
ImageUrl string `json:"imageUrl"` // Фото товара (основное)
ImageUrls []string `json:"imageUrls"` // Все фото товара
ImageVariants []ImageVariant `json:"imageVariants"` // Вариации изображений
IsArchived bool `json:"isArchived"` // Архивный или нет
Tm string `json:"tm"` // Торговая марка
Article string `json:"article"`
Name string `json:"name"`
ShortName string `json:"shortName"`
Description string `json:"description"`
ImageUrl string `json:"imageUrl"`
ImageUrls []string `json:"imageUrls"`
ImageVariants []ImageVariant `json:"imageVariants"`
IsArchived bool `json:"isArchived"`
Tm string `json:"tm"`
}
WarehouseData struct {
WarehouseId string `json:"warehouseId"` // Идентификатор склада
WarehouseName string `json:"warehouseName"` // Наименование склада
AvailableAmount int `json:"availableAmount"` // Доступное количество
WarehouseId string `json:"warehouseId"`
WarehouseName string `json:"warehouseName"`
AvailableAmount int `json:"availableAmount"`
Incoming []struct {
DateBegan string `json:"dateBegan"` // Дата начала периода поступления на склад
DateEnd string `json:"dateEnd"` // Дата окончания периода поступления на склад
Amount int `json:"amount"` // Ожидаемое количество
Type string `json:"type"` // Тип поступления, production - поступление после производства, shipping - доставка на склад
} // Ближайшие поступления
DateBegan string `json:"dateBegan"`
DateEnd string `json:"dateEnd"`
Amount int `json:"amount"`
Type string `json:"type"`
}
}
Etim struct {
Features []struct {
Id string `json:"id"` //
Name string `json:"name"` // Название свойства
Sort int `json:"sort"` // Порядок сортировки по умолчанию
Unit string `json:"unit"` // Единицы измерения
Value string `json:"value"` // Значение свойства
ValueUnion string `json:"value_union"` // Код значения
} `json:"features"` // Features represents a list of product features with detailed information.
Id string `json:"id"`
Name string `json:"name"`
Sort int `json:"sort"`
Unit string `json:"unit"`
Value string `json:"value"`
} `json:"features"`
Class struct {
Id string `json:"id"` //
Name string `json:"name"` // Название класса
} `json:"class"` // ETIM-класс товара
Id string `json:"id"`
Name string `json:"name"`
} `json:"class"`
}
LogisticParams struct {
Name string `json:"name"` // Название параметра
NameOrig string `json:"nameOrig"` // Название характеристики (исходное)
Name string `json:"name"`
NameOrig string `json:"nameOrig"`
Value struct {
Group string `json:"group"` // Значение для группового варианта
Individual string `json:"individual"` // Значение для индивидуального варианта
Transport string `json:"transport"` // Значение для транспортного варианта
} `json:"value"` // Value represents group, individual, and transport logistics values in JSON format.
Group string `json:"group"`
Individual string `json:"individual"`
Transport string `json:"transport"`
} `json:"value"`
}
LogisticParamsData struct {
SinglePackage struct {
Multiplicity int `json:"multiplicity"` // Кратность
Unit string `json:"unit"` // Единицы измерения
} `json:"singlePackage"` // Для индивидуальной упаковки
Multiplicity int `json:"multiplicity"`
Unit string `json:"unit"`
} `json:"singlePackage"`
}
ShortProduct struct {
Article string `json:"article"` // Артикул товара
Name string `json:"name"` // Полное наименование товара
Multiplicity int `json:"multiplicity"` // Кратность продажи
PriceBase float64 `json:"priceBase"` // Базовая цена с НДС
PriceRrc float64 `json:"priceRrc"` // Рекомендованная розничная цена (РРЦ) с НДС
Available float64 `json:"available"` // Значение остатка
Units string `json:"units"` // Единицы измерения
WarehouseData []WarehouseData `json:"warehouseData"` // Информация по складам
Article string `json:"article"`
Name string `json:"name"`
Multiplicity int `json:"multiplicity"`
PriceBase int `json:"priceBase"`
PriceRrc int `json:"priceRrc"`
Available int `json:"available"`
Units string `json:"units"`
WarehouseData []WarehouseData `json:"warehouseData"`
}
Product struct {
Article string `json:"article"` // Артикул товара
Name string `json:"name"` // Полное наименование товара
ShortName string `json:"shortName"` // Краткое название
Description string `json:"description"` // Описание
CategoryName string `json:"categoryName"` // Название категории
Category string `json:"category"` // Относительный путь до категории в каталоге
Slug string `json:"slug"` // Слаг товара
Tm string `json:"tm"` // Торговая марка
Url string `json:"url"` // Ссылка на товар
IsArchived bool `json:"isArchived"` // Архивный или нет
ImageUrl string `json:"imageUrl"` // Фото товара (основное)
ImageUrls []string `json:"imageUrls"` // Все фото товара
ImageVariants []ImageVariant `json:"imageVariants"` // Вариации изображений
ImageUrlsVariants []interface{} `json:"imageUrlsVariants"` // Все вариации изображений
Advantages string `json:"advantages"` // Преимущества
Etim Etim `json:"etim"` // ETIM характеристики товара
Complects []Complects `json:"complects"` // Комплектация и сопутствующие товары
Complectations string `json:"complectations"` // Комплектация
Files []interface{} `json:"files"` // Список файлов, относящихся к товару (ГЧ, КД, CAD-модели и т.д.)
LeftPeriod []LeftPeriod `json:"leftPeriod"` // Характеристики срока службы
LeftPeriodRaw LeftPeriodRaw `json:"leftPeriodRaw"` // Гарантийные показатели
LogisticParams []LogisticParams `json:"logisticParams"` // Логистические характеристики
LogisticParamsData LogisticParamsData `json:"logisticParamsData"` // Подробные логистические характеристики
Novelty bool `json:"novelty"` // Новинка или нет
DesignFeatures []DesignFeatures `json:"designFeatures"` // Отличительные особенности
Videos []Video `json:"videos"` // Видео по товару
Software []Software `json:"software"` // ПО по товару
Banner string `json:"banner"` // Текст баннера
LastModified string `json:"lastModified"` // Дата последнего изменения
CountryOfProduction string `json:"countryOfProduction"` // Страна производства
FirstSaleDate string `json:"firstSaleDate"` // Дата начала продаж
Feacn string `json:"feacn"` // Код ТН ВЭД
Multiplicity int `json:"multiplicity"` // Кратность продажи
PriceBase float64 `json:"priceBase"` // Базовая цена с НДС
PriceRrc float64 `json:"priceRrc"` // Персональная цена с НДС
PricePersonal float64 `json:"pricePersonal"` // Рекомендованная розничная цена (РРЦ) с НДС
Available int `json:"available"` // Значение остатка
Units string `json:"units"` // Единицы измерения
Family string `json:"family"` // Family specifies the family category of the product.
Series string `json:"series"` // Series is the series of the product.
IndPacking []string `json:"indPacking"` // Ссылки на фото упаковки
Analogs []Analog `json:"analogs"` // Аналоги
Related []Analog `json:"related"` // Совместно применяемые изделия
QrCode string `json:"qrCode"` // QR код со ссылкой на товар в Бизнес платформе
IsOutOfAssortment bool `json:"isOutOfAssortment"` // Выведенный из ассортимента
IsOutOfProduction bool `json:"isOutOfProduction"` // Выводимый из ассортимента
WarehouseData []WarehouseData `json:"warehouseData"` // Информация по складам
ShortName string `json:"shortName"`
Description string `json:"description"`
CategoryName string `json:"categoryName"`
Category string `json:"category"`
Slug string `json:"slug"`
Tm string `json:"tm"`
Url string `json:"url"`
IsArchived bool `json:"isArchived"`
ImageUrl string `json:"imageUrl"`
ImageUrls []string `json:"imageUrls"`
ImageVariants []ImageVariant `json:"imageVariants"`
Advantages string `json:"advantages"`
Etim Etim `json:"etim"`
Complects []Complects `json:"complects"`
Complectations string `json:"complectations"`
Files []interface{} `json:"files"`
LeftPeriod []LeftPeriod `json:"leftPeriod"`
LeftPeriodRaw LeftPeriodRaw `json:"leftPeriodRaw"`
LogisticParams []LogisticParams `json:"logisticParams"`
LogisticParamsData LogisticParamsData `json:"logisticParamsData"`
Novelty bool `json:"novelty"`
DesignFeatures []DesignFeatures `json:"designFeatures"`
Videos []Video `json:"videos"`
Software []Software `json:"software"`
Banner string `json:"banner"`
LastModified string `json:"lastModified"`
CountryOfProduction string `json:"countryOfProduction"`
FirstSaleDate string `json:"firstSaleDate"`
Feacn string `json:"feacn"`
Family string `json:"family"`
Series string `json:"series"`
IndPacking []string `json:"indPacking"`
Analogs []Analog `json:"analogs"`
Related []Analog `json:"related"`
QrCode string `json:"qrCode"`
IsOutOfAssortment bool `json:"isOutOfAssortment"`
IsOutOfProduction bool `json:"isOutOfProduction"`
}
)

View File

@ -1,32 +1,32 @@
package model
type CategoryResponse struct {
Categories []Category `json:"categories"` // Массив категорий 1-го уровня
Categories []Category `json:"categories"`
}
type CategoriesAndProductsBySlugParentCategoryResponse struct {
Date string `json:"date"` // Дата формирования файла
Slug string `json:"slug"` // Слаг категории 1-го уровня
Name string `json:"name"` // Название категории 1-го уровня
Url string `json:"url"` // Относительный адрес категории 1-го уровня
Categories []Category `json:"categories"` // Массив всех входящих категорий
Products []Product `json:"products"` // Массив всех входящих товаров
Date string `json:"date"`
Slug string `json:"slug"`
Name string `json:"name"`
Url string `json:"url"`
Categories []Category `json:"categories"`
Products []Product `json:"products"`
}
type NewProductsResponse struct {
Data struct {
Products []Product `json:"products"` // Список новинок
} `json:"data"` // Список новинок
Products []Product `json:"products"`
} `json:"data"`
Meta struct {
Page int `json:"page"` // Текущая страница
TotalPages int `json:"totalPages"` // Всего страниц
TotalCount int `json:"totalCount"` // Всего элементов
PageSize int `json:"pageSize"` // Размер страницы
} `json:"_meta"` // Параметры пагинации
Page int `json:"page"`
TotalPages int `json:"totalPages"`
TotalCount int `json:"totalCount"`
PageSize int `json:"pageSize"`
} `json:"_meta"`
}
type RemainsAndPlanresiduesResponse struct {
Date string `json:"date"` // Дата создания файла
Products []ShortProduct `json:"products"` // Массив остатков по товарам
Date string `json:"date"`
Products []ShortProduct `json:"products"`
}