|
|
@@ -0,0 +1,282 @@
|
|
|
+# DirectoryService
|
|
|
+## Назначение
|
|
|
+
|
|
|
+DirectoryService - доменный сервис каталога. Отвечает за справочники (категории, бренды), выборки и сортировки по товарам, разрешение внешних идентификаторов в внутренние `productId`, а также приём пакетных обновлений справочников от интеграции (1С/другие источники). Дополнительно предоставляет вспомогательные выборки (случайные товары) и служебные списки внешних файлов, требующих загрузки.
|
|
|
+
|
|
|
+## Публичные методы DirectoryService
|
|
|
+
|
|
|
+### Справочники и внешние данные
|
|
|
+
|
|
|
+* `GetProductIdsFromExt(extIds[]): int[]` - сопоставить внешние идентификаторы товара с внутренними `productId`. 
|
|
|
+* `GetBrandsAsync(categoryId = 0): Brand[]` - получить бренды (опционально отфильтрованные по категории). 
|
|
|
+* `GetCategoriesAsync(): Category[]` - получить дерево/список категорий. 
|
|
|
+* `GetAllProductsExtAsync(): ProductExt[]` - получить полные внешние данные по товарам (для импорта/синхронизаций). 
|
|
|
+* `GetAllCategoriesExtAsync(): CategoryExt[]` - получить внешние данные по категориям. 
|
|
|
+
|
|
|
+### Выборки по каталогу
|
|
|
+
|
|
|
+* `QueryProductsIdsByCategoriesAsync(categoriesId[], intersectIds[], withUnpublished): int[]` - вернуть `productId` по категориям; если `intersectIds` непустой, результат ограничивается пересечением; флаг `withUnpublished` управляет включением неопубликованных. 
|
|
|
+* `QueryProductsIdsByBrandsAsync(brandsId[], intersectIds[], withUnpublished): int[]` - аналогично, но по брендам. 
|
|
|
+* `QueryProductsAsync(productIds[]): Product[]` - вернуть товары по списку `productId`. 
|
|
|
+* `GetProductsRandomAsync(count): Product[]` - получить случайную подборку товаров. 
|
|
|
+* `SortProductsIdsByPriceAsync(productIds[], desc = false): int[]` - отсортировать список `productId` по цене (по возрастанию по умолчанию; `desc = true` - по убыванию). 
|
|
|
+
|
|
|
+### Обновления и служебные операции
|
|
|
+
|
|
|
+* `UpdateDirectoryAsync(pack): void` - принять пакет обновления справочников (используется интеграцией). 
|
|
|
+* `GetFileExtIdsToNeedUploadAsync(take): string[]` - вернуть внешние идентификаторы файлов, которые необходимо догрузить (служебно для синхронизации медиа). 
|
|
|
+
|
|
|
+## Особенности использования
|
|
|
+
|
|
|
+* **Пересечения фильтров:** методы `QueryProductsIdsBy*` умеют ограничивать выдачу множеством `intersectIds` - удобно для постфильтрации, когда уже есть базовый набор `productId`.
|
|
|
+* **Публикация:** флаг `withUnpublished` позволяет явно включать/исключать неопубликованные позиции (для админских сценариев).
|
|
|
+* **Синхронизация:** `UpdateDirectoryAsync` и выборки `*ExtAsync` - контракт обмена с мастер-системой.
|
|
|
+
|
|
|
+## Взаимодействие c другими сервисами
|
|
|
+
|
|
|
+DirectoryService взаимодействует со следующими сервисами:
|
|
|
+
|
|
|
+* BusinessService - (get only) запрашивает данные об остатках товара.
|
|
|
+* SearchService - (set only) отправляет набор данных для поискового индексирования.
|
|
|
+* FileDirectoryService - (set get) резервиет записи для отложенной загрузки и проверяет загруженны ли файлы.
|
|
|
+
|
|
|
+## Модели
|
|
|
+
|
|
|
+Каждая модель данных имеет 2 представления:
|
|
|
+
|
|
|
+* **DBO (DataBase Object)** - минимальная структура, которая соответствует схеме хранения в базе (Id, внешние ключи, простые поля).
|
|
|
+* **Полные модели** - наследники DBO, которые маппятся автоматически (`AutoMapper`) и содержат дополнительные поля: связи (Brand, Attributes), вычисляемые величины (остатки, рейтинг), технические коллекции (файлы для выгрузки, ProductsCount и пр.).
|
|
|
+
|
|
|
+Такой подход позволяет:
|
|
|
+
|
|
|
+ 1. Отделять «источник истины» (БД) от бизнес-логики.
|
|
|
+ 2. Явно контролировать, какие поля выгружаются наружу.
|
|
|
+ 3. Безопасно обновлять модели без прямого доступа к БД.
|
|
|
+
|
|
|
+Полные модели наследуются от соответствующих DBO и получают дополнительные поля (связи, вычисляемые значения, служебные коллекции). Это позволяет хранить в БД «сырые» данные, а наружу отдавать обогащённые объекты.
|
|
|
+
|
|
|
+Далее представлены полные модели. Если интересно, что представляет DBO смотрите ниже таблицы БД.
|
|
|
+
|
|
|
+> Все модели *Ext относятся к сервису Connector1CService. Их описание там. В угоду продуктивности нарушены правила зависимости и Directory производит некоторые *Ext инстансы, хотя описаны они в Connector1CService.
|
|
|
+
|
|
|
+### Product
|
|
|
+
|
|
|
+```
|
|
|
+string ExtId //Внешний ИД (мастер-система)
|
|
|
+int Id //ИД товара
|
|
|
+int CategoryId //ИД категории (группы товаров)
|
|
|
+string Article //Артикул
|
|
|
+string Name //Наименование
|
|
|
+string NameSEO //SEO-наименование (переписывает Name)
|
|
|
+string Description //Описание
|
|
|
+string DescriptionSEO //SEO-описание (переписывает Description)
|
|
|
+string[] BarCodes //Штрих-коды
|
|
|
+int UnitCode //Код единицы измерения по ОКЕИ
|
|
|
+int BrandId //ИД бренда
|
|
|
+FileRecord[] Fotos //Фото-файлы
|
|
|
+FileRecord[] Files //Другие файлы
|
|
|
+decimal Price //Базовая цена
|
|
|
+float WeightKg //Вес, кг
|
|
|
+Volume SizeM //Габариты: ширина/длина/высота в метрах
|
|
|
+float VolumeM //Объём (альтернативное поле)
|
|
|
+VATCodeEnum VATCode //Код НДС
|
|
|
+TradeAgentSignEnum TradeAgentSign //Признак торгового агента
|
|
|
+TradeAgent TradeAgent //Данные торгового агента
|
|
|
+bool IsPublished //Флаг публикации
|
|
|
+bool IsDeleted //Флаг удаления
|
|
|
+long UpdateTimestamp //Таймштамп обновления
|
|
|
+Brand? Brand //Связь: бренд (полная модель)
|
|
|
+ProductAttribute[] Attributes //Связанные атрибуты (полные модели)
|
|
|
+float Rate //Средняя оценка (не хранится в БД)
|
|
|
+decimal Remainder //Остаток на складе (не хранится в БД)
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: `Product` - «обогащённая» надстройка над `ProductDBO`: кроме полей хранения включает связи (`Brand`, `Attributes`) и витринные показатели (`Rate`, `Remainder`).
|
|
|
+
|
|
|
+### Category
|
|
|
+
|
|
|
+```
|
|
|
+string ExtId //Внешний ИД (мастер-система)
|
|
|
+int Id //ИД категории
|
|
|
+int ParentId //ИД родителя
|
|
|
+int SortIndex //Порядок сортировки
|
|
|
+string Name //Название категории
|
|
|
+string IconSVG //Иконка (SVG)
|
|
|
+long UpdateTimestamp //Таймштамп обновления
|
|
|
+bool IsDeleted //Флаг удаления
|
|
|
+int ProductsCount //Количество товаров в категории (не хранится в БД)
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: `Category` добавляет счётчик товаров `ProductsCount` для витрины/фильтров; базовые поля приходят из `CategoryDBO`.
|
|
|
+
|
|
|
+### Brand
|
|
|
+
|
|
|
+```
|
|
|
+string ExtId //Внешний ИД (мастер-система)
|
|
|
+int Id //ИД бренда
|
|
|
+string Name //Название бренда
|
|
|
+FileRecord LogoFile //Логотип бренда (файл)
|
|
|
+long UpdateTimestamp //Таймштамп обновления
|
|
|
+bool IsDeleted //Флаг удаления
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: Полная модель `Brand` повторяет поля DBO и используется как связанная сущность в `Product`; логотип хранится как `FileRecord`.
|
|
|
+
|
|
|
+### ProductAttribute
|
|
|
+
|
|
|
+```
|
|
|
+int ProductId //ИД товара
|
|
|
+int AttributeTypeId //ИД типа атрибута
|
|
|
+string Value //Значение атрибута
|
|
|
+long UpdateTimestamp //Таймштамп обновления
|
|
|
+ProductAttributeType Type //Тип атрибута (полная модель)
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: В отличие от DBO, здесь сразу есть связанный `Type` с метаданными атрибута; пара (ProductId, AttributeTypeId) уникальна.
|
|
|
+
|
|
|
+### ProductAttributeType
|
|
|
+
|
|
|
+```
|
|
|
+string ExtId //Внешний ИД (мастер-система)
|
|
|
+int Id //ИД типа атрибута
|
|
|
+int CategoryId //ИД категории, к которой относится тип
|
|
|
+ProductAttributeTypeEnum TypeEnum //Семантика (числовой/строковый и т. п.)
|
|
|
+string Name //Название атрибута
|
|
|
+int SortIndex //Порядок сортировки
|
|
|
+long UpdateTimestamp //Таймштамп обновления
|
|
|
+bool IsDeleted //Флаг удаления
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: Тип атрибута задаёт метаданные для значений, по нему собираются фильтры/характеристики в карточке товара.
|
|
|
+
|
|
|
+### FileRecord
|
|
|
+
|
|
|
+```
|
|
|
+string ExtId //Внешний ИД файла (в мастер-системе)
|
|
|
+string Id //ИД загруженного файла (FilesService)
|
|
|
+string Category //Категория файла (для правил хранения/превью)
|
|
|
+string Tag //Тег/назначение (например, 'main', 'manual')
|
|
|
+string Format //Формат/расширение или дополнительная помета
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: `FileRecord` хранится как JSON внутри сущностей каталога (товары, бренды) и связывает их с файловым сервисом.
|
|
|
+
|
|
|
+### QueryResult
|
|
|
+
|
|
|
+```
|
|
|
+long Id //Идентификатор сохранённого запроса
|
|
|
+int UserId //ИД пользователя
|
|
|
+string Query //Текст поискового запроса
|
|
|
+string[] LastQueries //Последние запросы пользователя (размер настраивается)
|
|
|
+DateTimeOffset Created //Когда создан результат
|
|
|
+DateTimeOffset ActualUntil //Актуальность результата (до какого времени)
|
|
|
+Category[] Categories //Категории по результатам запроса
|
|
|
+Product[] Products //Товары по результатам запроса
|
|
|
+int ProductsTotal //Общее число товаров по запросу
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: Служебная модель для отдачи результатов поиска с «памятью» последних запросов и порцией витринных данных.
|
|
|
+
|
|
|
+### TradeAgent
|
|
|
+
|
|
|
+```
|
|
|
+string Inn //ИНН торгового агента
|
|
|
+string OrgName //Название организации
|
|
|
+string Phone //Контактный телефон
|
|
|
+string Address //Адрес организации
|
|
|
+```
|
|
|
+
|
|
|
+Комментарий: TradeAgent - вложенный объект внутри Product, содержит основные реквизиты организации-продавца. Эти данные не лежат в товарной таблице напрямую, а подгружаются и маппятся в модель при синхронизации.
|
|
|
+
|
|
|
+## DB
|
|
|
+
|
|
|
+Содержит таблицы и индексы
|
|
|
+
|
|
|
+```
|
|
|
+-- Migration 1
|
|
|
+pack_sync (
|
|
|
+ Id INTEGER PRIMARY KEY,
|
|
|
+ LastPackId INTEGER NOT NULL DEFAULT 0,
|
|
|
+ LastPackTimestamp INTEGER NOT NULL DEFAULT 0
|
|
|
+);
|
|
|
+
|
|
|
+product_attribute_types (
|
|
|
+ Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ ExtId TEXT NOT NULL DEFAULT '',
|
|
|
+ CategoryId INTEGER NOT NULL DEFAULT 0,
|
|
|
+ TypeEnum INTEGER NOT NULL DEFAULT 0,
|
|
|
+ Name TEXT NOT NULL DEFAULT '',
|
|
|
+ SortIndex INTEGER NOT NULL DEFAULT 0,
|
|
|
+ IsRange INTEGER NOT NULL DEFAULT 0,
|
|
|
+ UpdateTimestamp INTEGER NOT NULL DEFAULT 0
|
|
|
+);
|
|
|
+
|
|
|
+brands (
|
|
|
+ Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ ExtId TEXT NOT NULL DEFAULT '',
|
|
|
+ Name TEXT NOT NULL DEFAULT '',
|
|
|
+ LogoFile TEXT NOT NULL DEFAULT '',
|
|
|
+ UpdateTimestamp INTEGER NOT NULL DEFAULT 0
|
|
|
+);
|
|
|
+
|
|
|
+categories (
|
|
|
+ Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ ExtId TEXT NOT NULL DEFAULT '',
|
|
|
+ ParentId INTEGER NOT NULL DEFAULT 0,
|
|
|
+ SortIndex INTEGER NOT NULL DEFAULT 0,
|
|
|
+ Name TEXT NOT NULL DEFAULT '',
|
|
|
+ IconSVG TEXT NOT NULL DEFAULT '',
|
|
|
+ UpdateTimestamp INTEGER NOT NULL DEFAULT 0
|
|
|
+);
|
|
|
+
|
|
|
+product_attributes (
|
|
|
+ ProductId INTEGER NOT NULL,
|
|
|
+ AttributeTypeId INTEGER NOT NULL,
|
|
|
+ Value TEXT NOT NULL DEFAULT '',
|
|
|
+ UpdateTimestamp INTEGER NOT NULL DEFAULT 0,
|
|
|
+ PRIMARY KEY (ProductId, AttributeTypeId)
|
|
|
+);
|
|
|
+
|
|
|
+products (
|
|
|
+ Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ ExtId TEXT NOT NULL DEFAULT '',
|
|
|
+ CategoryId INTEGER NOT NULL DEFAULT 0,
|
|
|
+ Article TEXT NOT NULL DEFAULT '',
|
|
|
+ Name TEXT NOT NULL DEFAULT '',
|
|
|
+ NameSEO TEXT NOT NULL DEFAULT '',
|
|
|
+ Description TEXT NOT NULL DEFAULT '',
|
|
|
+ DescriptionSEO TEXT NOT NULL DEFAULT '',
|
|
|
+ BarCodes TEXT NOT NULL DEFAULT '[]',
|
|
|
+ UnitCode INTEGER NOT NULL DEFAULT 0,
|
|
|
+ BrandId INTEGER NOT NULL DEFAULT 0,
|
|
|
+ Fotos TEXT NOT NULL DEFAULT '[]',
|
|
|
+ Files TEXT NOT NULL DEFAULT '[]',
|
|
|
+ Price TEXT NOT NULL DEFAULT 0,
|
|
|
+ WeightKg REAL NOT NULL DEFAULT 0,
|
|
|
+ SizeM TEXT NOT NULL DEFAULT '{}',
|
|
|
+ VolumeM REAL NOT NULL DEFAULT 0,
|
|
|
+ IsPublished INTEGER NOT NULL DEFAULT 0,
|
|
|
+ UpdateTimestamp INTEGER NOT NULL DEFAULT 0
|
|
|
+)
|
|
|
+```
|
|
|
+
|
|
|
+```
|
|
|
+-- Migration 2
|
|
|
+-- Add IsDeleted
|
|
|
+
|
|
|
+ALTER TABLE product_attribute_types ADD IsDeleted BOOLEAN NOT NULL DEFAULT FALSE;
|
|
|
+ALTER TABLE brands ADD IsDeleted BOOLEAN NOT NULL DEFAULT FALSE;
|
|
|
+ALTER TABLE categories ADD IsDeleted BOOLEAN NOT NULL DEFAULT FALSE;
|
|
|
+ALTER TABLE products ADD IsDeleted BOOLEAN NOT NULL DEFAULT FALSE;
|
|
|
+```
|
|
|
+
|
|
|
+```
|
|
|
+-- Migration 3
|
|
|
+-- Add VatCode+Comissioner
|
|
|
+
|
|
|
+ALTER TABLE products ADD VATCode INTEGER NOT NULL DEFAULT 0;
|
|
|
+ALTER TABLE products ADD TradeAgentSign INTEGER NOT NULL DEFAULT 0;
|
|
|
+ALTER TABLE products ADD TradeAgent TEXT NOT NULL DEFAULT '{}';
|
|
|
+```
|
|
|
+
|
|
|
+[Назад](/index.md)
|