diff --git a/api/api.go b/api/api.go index 4c97333..2dd8d23 100644 --- a/api/api.go +++ b/api/api.go @@ -5,21 +5,26 @@ import ( "gitea.24example.ru/spavelit/bpiek/model" ) -type Api struct { - Client *client.Client -} +type ( + Api struct { + Client *client.Client + } + Credentials struct { + Username string + Password string + } -type Method interface { - GetParentCategories() ([]model.Category, error) - GetCategories() ([]model.Category, error) - GetTreeCategories() ([]model.TreeCategories, error) + 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) // Возвращает массив, в котором содержатся актуальные цены и остатки товаров. + } +) - GetProducts() ([]model.Product, error) - GetProductByArticle(article string) (model.Product, error) - GetRemainsAndPlanresidues() ([]model.ShortProduct, error) -} - -func NewApi(credentials client.Credentials) Method { +func NewApi(credentials Credentials) Method { return &Api{ Client: client.NewClient(credentials), } diff --git a/api/products.go b/api/products.go index ced26e2..a023304 100644 --- a/api/products.go +++ b/api/products.go @@ -49,7 +49,12 @@ func (a *Api) GetProductByArticle(article string) (model.Product, error) { "error getting product by article: " + article) } - return apiResponse.Result().(model.Product), nil + product, ok := apiResponse.Result().(*model.Product) + if !ok { + return model.Product{}, errors.New("failed to parse product from response") + } + + return *product, nil } func (a *Api) GetRemainsAndPlanresidues() ([]model.ShortProduct, error) { @@ -77,7 +82,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...) diff --git a/client/client.go b/client/client.go index 11551ef..00f6955 100644 --- a/client/client.go +++ b/client/client.go @@ -1,15 +1,13 @@ package client -import "github.com/go-resty/resty/v2" - -// import ( -// "net/http" -// "net/url" -// ) +import ( + "gitea.24example.ru/spavelit/bpiek/api" + "github.com/go-resty/resty/v2" +) const ( - AUTH_API_URL = "https://bp.iek.ru/oauth/login" - BASE_API_URL = "https://bp.iek.ru/api/catalog/v1/" + AuthApiUrl = "https://bp.iek.ru/oauth/login" + BaseApiUrl = "https://bp.iek.ru/api/catalog/v1/" ) type ( @@ -27,18 +25,18 @@ type ( } ) -func NewClient(credentials Credentials) *Client { +func NewClient(credentials api.Credentials) *Client { authSuccess := &AuthSuccess{} client := resty.New() - client.SetBaseURL(BASE_API_URL) + client.SetBaseURL(BaseApiUrl) response, err := client.R(). SetFormData(map[string]string{ - "username": credentials.GetUsername(), - "password": credentials.GetPassword(), + "username": credentials.Username, + "password": credentials.Password, }). SetResult(&authSuccess). - Post(AUTH_API_URL) + Post(AuthApiUrl) if err != nil { panic(err) @@ -49,7 +47,7 @@ func NewClient(credentials Credentials) *Client { } client.SetHeader("Content-Type", "application/json") - client.SetHeader("Authorization", "Bearer "+authSuccess.AccessToken) + client.SetHeader("Authorization", authSuccess.TokenType+" "+authSuccess.AccessToken) return &Client{ HTTPClient: client, diff --git a/client/credential.go b/client/credential.go deleted file mode 100644 index 1ba865a..0000000 --- a/client/credential.go +++ /dev/null @@ -1,17 +0,0 @@ -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 -} diff --git a/model/category.go b/model/category.go index c1bd47e..d05dc2b 100644 --- a/model/category.go +++ b/model/category.go @@ -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"` + Slug string `json:"slug"` // Слаг категории + Name string `json:"name"` // Название категории + Url string `json:"url"` // Относительный адрес категории + Children []TreeCategories `json:"children"` // Children nested categories in TreeCategories } diff --git a/model/product.go b/model/product.go index 66fcbe3..834352b 100644 --- a/model/product.go +++ b/model/product.go @@ -2,150 +2,168 @@ 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 interface{} `json:"lifespan"` - Warranty interface{} `json:"warranty"` + 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"` // Гарантийный срок } 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"` + Name string `json:"name"` // Наименование + Description string `json:"description"` // Описание + Url string `json:"url"` // Ссылка + Type string `json:"type"` // Тип (ссылка на видео-хостинг или прямая ссылка на скачивание); Enum: "url" "file" } 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"` - } + DateBegan string `json:"dateBegan"` // Дата начала периода поступления на склад + DateEnd string `json:"dateEnd"` // Дата окончания периода поступления на склад + Amount int `json:"amount"` // Ожидаемое количество + Type string `json:"type"` // Тип поступления, production - поступление после производства, shipping - доставка на склад + } // Ближайшие поступления } Etim struct { Features []struct { - Id string `json:"id"` - Name string `json:"name"` - Sort int `json:"sort"` - Unit string `json:"unit"` - Value string `json:"value"` - } `json:"features"` + 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. Class struct { - Id string `json:"id"` - Name string `json:"name"` - } `json:"class"` + Id string `json:"id"` // + Name string `json:"name"` // Название класса + } `json:"class"` // ETIM-класс товара } 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"` + 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. } 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 int `json:"priceBase"` - PriceRrc int `json:"priceRrc"` - Available int `json:"available"` - Units string `json:"units"` - WarehouseData []WarehouseData `json:"warehouseData"` + 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"` // Информация по складам } Product struct { - 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"` + 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"` // Информация по складам } ) diff --git a/model/response.go b/model/response.go index 46a6d7d..94ffd88 100644 --- a/model/response.go +++ b/model/response.go @@ -1,32 +1,32 @@ package model type CategoryResponse struct { - Categories []Category `json:"categories"` + Categories []Category `json:"categories"` // Массив категорий 1-го уровня } type CategoriesAndProductsBySlugParentCategoryResponse struct { - Date string `json:"date"` - Slug string `json:"slug"` - Name string `json:"name"` - Url string `json:"url"` - Categories []Category `json:"categories"` - Products []Product `json:"products"` + 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"` // Массив всех входящих товаров } 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"` // Массив остатков по товарам }