ADR-0016: Расширяемые словари kind для графа поставщиков
Status: accepted Date: 2026-04-17 Deciders: команда проекта
Контекст
Если SupplierRole.kind и SupplierRelationship.kind сделать hardcoded enum’ами, любое расширение словаря потребует деплоя. В реальности набор будет расти: появятся специфичные роли (например, “сертифицированный сервис-партнёр”) и новые типы отношений.
Пользователь явно запросил расширяемый словарь.
Альтернативы:
- A: Hardcoded enum в коде.
- B: Полностью свободные строки.
- C: БД-словарь с известным
semantic_handler.
Решение
Variant C: БД-словари supplier_role_kind и supplier_relationship_kind с обязательным указанием semantic_handler.
- Каждый kind —
code(машинный) +display_name+semantic_handler+ описание. semantic_handler— фиксированный enum в коде (известная семантика: MANUFACTURER, WAREHOUSE_OPERATOR, AGGREGATES, RESELLS, …). Расширение этого enum’а — через ADR.- Несколько
codeмогут разделять одинsemantic_handler(разные нюансы одной семантики). - Новый
codeсsemantic_handler = GENERIC— fallback: сохраняется как связь, но не используется в SupplyChainTrace builder. - Управление словарями — через admin UI, event-sourced.
Стартовый набор сидируется при инициализации: на старте закладываем 7 ролей и 8 типов отношений.
Обновлённый стартовый набор supplier_relationship_kind:
code | semantic_handler | Описание |
|---|---|---|
aggregates | AGGREGATES | Агрегатор (marketplace) опубликовал товар на своей витрине. |
resells | RESELLS | Дистрибьютор перепродаёт товар производителя. |
is_agent_of | AGENT_OF | Агент заключает сделки от имени производителя/дистрибьютора. |
uses_api_of | USES_API_OF | Поставщик использует технический API другого. |
uses_warehouse_of | USES_WAREHOUSE_OF | Поставщик хранит товар на чужом складе. |
subsidiary_of | SUBSIDIARY_OF | Юр-лицо входит в группу. |
exclusive_for | EXCLUSIVE_FOR | Эксклюзивный контракт. |
listed_on | LISTED_ON | Seller размещён на агрегаторе (marketplace_seller → marketplace). Добавлен ADR-0026. |
Обновлённый стартовый набор supplier_role_kind — включает marketplace_seller (ADR-0026) как легитимную роль в рамках агрегатора.
Supplier-to-Tracium mapping aggregates
Та же схема «расширяемый справочник + фиксированный semantic_handler» применяется к маппингу идентификаторов поставщика на канонические сущности Tracium. Это требуется, потому что каждый поставщик приносит собственные:
- коды характеристик (ETM:
ConfigCharCode/ConfigCharIdVal); - коды классификации (ETM:
gdsClassTree— 3 уровня); - коды производителей (ETM:
Info/search/r-manuf—(id, value=mnf_code, label)).
Вместо того чтобы тащить это в core, выделяем три aggregate’а в Catalog BC:
| Aggregate | Владелец | Что маппит |
|---|---|---|
SupplierCharacteristicMapping | Catalog (со-владение с Enrichment) | (supplier_ref, supplier_char_code) → Characteristic.key + unit_override? |
SupplierClassificationMapping | Catalog | (supplier_ref, supplier_class_code) → [ClassificationTag] (multi-tag) |
SupplierManufacturerMapping | Catalog | (supplier_ref, supplier_manufacturer_code) → Manufacturer.id |
Правила:
- Aggregate event-sourced (аудит: кто/когда добавил mapping, как он эволюционировал).
- Каждая запись имеет
confidence + source (declared|imported|inferred)+ optionalreviewed_by_moderation_case. - Отсутствие mapping — валидное состояние. Observer → Matching получает supplier code as-is, попадает в Moderation BC (
manufacturer_alias_proposal, новые кейсыcharacteristic_mapping_proposal,classification_mapping_proposal). - Справочник
supplier_dictionary_sourceсодержит описание методов, которыми mapping можно пополнять (info_endpoint,sggds_file,manual_csv,ml_inferred).
Warehouse kind
WarehouseKind (введён ADR-0025) ставится в ряд с TrustLevel — фиксированный enum, расширяется только через ADR (не admin UI), потому что от него зависит алгоритм lead_time и visibility predicates.
Последствия
Плюсы
- Гибкость: новый kind заводится в продакшене без деплоя.
- Безопасность: код всегда знает, как обработать (через semantic_handler), даже неизвестный code.
- Локализация: display_name можно добавлять без deploy.
- Audit: история словарей event-sourced.
Минусы
- Двухуровневая модель (code → semantic) сложнее для разработчика, чем enum.
- Введение принципиально новой семантики всё равно требует кода (нового semantic_handler).
- Консистентность данных: при удалении kind из словаря — что делать с существующими entity, его использующими (запрет удаления, archival).
Нейтральные последствия
- Trust level остаётся фиксированным enum — у него критичная семантика для conflict resolution.
Рассмотренные альтернативы
A: Hardcoded enum
Не удовлетворяет требование расширяемости.
B: Свободные строки без семантики
Потеря безопасности обработки (builder не знает, что делать с новым kind).
Ссылки
../../10-business/contexts/supplier-network.md../../10-business/contexts/catalog.md- ADR-0013 (suppliers as graph).
- ADR-0024 (supplier connector contract) — Capabilities.DictionaryExports использует эти aggregate’ы как приёмник.
- ADR-0025 (price & stock observation extensions) —
WarehouseKindenum. - Сценарий:
../../10-business/scenarios/supplier-dictionary-sync.md.