ADR-011: Версионность каталога — нужна ли для управления обновлениями меню

Статус

Accepted — двухуровневое версионирование (товары + каталог).

Принятое решение

Двухуровневое версионирование:

  1. Товары версионные — каждое изменение (поля, техкарта) создаёт новую версию товара
  2. Каталог = версионный список ссылок на конкретные версии товаров (draft → published → archived)
  3. При изменении товара → новая версия товара → draft каталога с обновлённой ссылкой
  4. Неизменённые товары — ссылки остаются прежними
  5. Published каталог “заморожен” — изменение товара не ломает published

Контекст

Сейчас каталог мутабельный без версионности (ADR-008, BR 1.7). Франшиза меняет каталог → изменения мгновенно видны всем. Меню франчайзи (BR 1.11) версионируется отдельно.

Проблема

Франшиза добавила 10 новых товаров, изменила описания 5 существующих, убрала 3. Это большое обновление каталога. Что происходит:

Без версионности (текущее решение):

  1. Каждое изменение применяется мгновенно
  2. Франчайзи не знает что каталог обновился — нет уведомления “каталог изменился”
  3. Новые товары недоступны (default deny) — но франчайзи не знает что появились новые товары для его ТТ, пока франшиза не разрешит и франчайзи сам не заглянет в редактор меню
  4. Удалённые товары скрываются от клиентов мгновенно — франчайзи видит “недоступен” в меню, но не понимает почему
  5. Нет понятия “версия каталога 2.0” — только непрерывный поток изменений

С версионностью каталога (предлагаемая логика):

  1. Франшиза работает с черновиком каталога — изменения не видны никому
  2. Франшиза публикует новую версию каталога → франчайзи получает уведомление “Каталог обновлён до v5”
  3. Франчайзи сам решает когда обновить своё меню под новый каталог — открывает diff (что добавлено, что убрано, что изменилось), обновляет меню в удобное время
  4. До обновления меню — клиенты видят прежнее меню (по опубликованному меню + старые товары)
  5. Это управляемый процесс, а не “каталог поменялся → всё мгновенно поехало”

Ключевой вопрос

Текущий подход (мутабельный каталог) означает что франшиза при любом изменении может сломать меню франчайзи — удалить товар который продаётся, деактивировать категорию. Формула видимости (5 шагов) защищает клиента, но франчайзи не контролирует когда изменения до него дойдут.

Версионность каталога даёт франчайзи контроль: “Я вижу что каталог обновился. Я обновлю своё меню в понедельник, когда смена закончится.”

Рассмотренные варианты

A. Без версионности (текущее решение)

Каталог мутабельный. Изменения мгновенные. Меню франчайзи версионируется отдельно. Защита клиента — через формулу видимости.

ПлюсМинус
ПростоФраншиза может “сломать” меню мгновенно
Как в iikoФранчайзи не контролирует когда обновления доходят
Меньше кодаНет понятия “версия каталога” — сложно отслеживать что изменилось

B. Версионность каталога (draft → published)

Каталог версионируется как меню: франшиза работает с черновиком, публикует версию. Франчайзи видит уведомление и сам решает когда адаптировать меню.

ПлюсМинус
Франчайзи контролирует когда обновитьСложнее: нужна версионность всех сущностей каталога (товары, категории, модификаторы)
Франшиза может подготовить большое обновлениеДва “слоя” версионности (каталог + меню) — сложнее понять
Уведомление “каталог обновлён”Что если франчайзи игнорирует обновление месяц?
Diff “что изменилось”Версионность каталога целиком (снапшот) — тяжёлая модель данных

C. Каталог мутабельный + уведомления об изменениях (компромисс)

Каталог без версионности (как сейчас). Но при изменениях — уведомление франчайзи: “Франшиза добавила 10 товаров, убрала 3”. Франчайзи не контролирует когда изменения применяются к каталогу, но знает о них и может обновить меню.

ПлюсМинус
Простая реализация (аудит-лог + уведомления)Франчайзи не контролирует — удалённый товар пропадёт мгновенно
Франчайзи информированНе решает проблему “сломанного меню”
Не нужна версионность

Влияние на архитектуру

Если Вариант A (без версионности)

  • Catalog Service: мутабельные CRUD, без lifecycle
  • Меню франчайзи: при каждом открытии редактора видит актуальный каталог
  • Удалённые/деактивированные товары мгновенно скрываются от клиентов
  • ADR-008 (аудит-лог) даёт историю, но не контроль

Если Вариант B (версионность)

  • Catalog Service: draft/published lifecycle для каталога целиком
  • Нужна модель “catalog_version”: снапшот или diff-based
  • Меню франчайзи: при открытии редактора видит последнюю published версию каталога
  • Франшиза может работать с черновиком каталога параллельно
  • Notification Service: уведомление франчайзи о новой версии
  • Значительно сложнее — затрагивает все сущности (товары, категории, модификаторы, прейскуранты)

Если Вариант C (уведомления)

  • Catalog Service: мутабельные CRUD (как сейчас)
  • Добавить: Kafka-событие catalog.updated → Notification Service → push/email франчайзи
  • Аудит-лог (ADR-008) используется для формирования “что изменилось”
  • Меню франчайзи: при открытии видит актуальный каталог + баннер “Каталог обновлён, проверьте меню”

Дополнительное требование: отчёт по переходу ТТ на новый каталог

Независимо от выбранного варианта — франшизе нужно видеть какие ТТ перешли на актуальный каталог, а какие нет.

Зачем

Франшиза опубликовала обновление каталога (или просто внесла важные изменения). Ей нужно знать:

  • ТТ “Центр” — меню обновлено под новый каталог ✅
  • ТТ “Вокзал” — меню НЕ обновлено, работает по старому составу ⚠
  • ТТ “Фудкорт” — меню НЕ обновлено 3 недели ❌

Без этого отчёта франшиза не контролирует единообразие сети.

Как реализуется в каждом варианте

Вариант A (без версионности): Сложно — нет понятия “версия каталога”. Можно косвенно: сравнить menu.updated_at с catalog_changelog.last_change_at. Если меню давно не обновлялось после изменений каталога → пометка “возможно устарело”.

Вариант B (версионность): Естественно — каждое меню ссылается на catalog_version_id. Отчёт: SELECT stores WHERE menu.catalog_version_id < current_catalog_version. Чётко видно кто на какой версии.

Вариант C (уведомления): Средне — можно отслеживать: уведомление отправлено → меню обновлено после уведомления или нет. Таблица catalog_update_notifications: { franchisee_id, notified_at, menu_updated_after: boolean }.

Этот отчёт — сильный аргумент в пользу Варианта B

Только при версионности каталога можно точно сказать “ТТ работает на каталоге v3, а актуальный — v5”. Варианты A и C дают лишь приближение.


Решение

Ожидает решения.

Вопросы для обсуждения:

  1. Насколько критична проблема “франшиза сломала меню”? Это реальный сценарий или теоретический?
  2. Готовы ли к сложности версионности каталога? Это значительно больше чем версионность меню.
  3. Достаточно ли уведомлений (Вариант C) вместо полной версионности?
  4. Насколько важен отчёт “какие ТТ перешли на новый каталог”? Это аргумент за Вариант B.

Ссылки