Chain Admin → POS → KDS — Test Plan

Сквозная цепочка: каталог/настройки во франш-админке → меню и оформление заказа на POS → отображение и прогон статусов на KDS. Цель — ловить баги маршрутизации (kitchen_station_id), пропагации (стопы, прейскурант, модификаторы), денормализации позиций и status-flow между сервисами.

Зона: cross-cutting (T2 = Каталог-источник, T3 = ТТ/Заказы-приёмник). Прогон совместный или одним тестером. Приоритет: этот пакет = регрессия №1 после любого изменения в Catalog Service, Order Service, POS, KDS или pos-bff (WebSocket). AREA-код: CHAIN (новый, добавлен к перечню в index.md).

Контекст архитектуры

Admin (Franchise back-office)
   │  REST/CRUD
   ▼
Catalog Service ──Kafka──► catalog.product.upserted/deleted
                          catalog.modifier_group.upserted/deleted
                          catalog.kds_settings.updated  (BR 5.1)
   │
   │ GET /menu (BR 1.16) — вычисляемое меню ТТ с прейскурантом и стоп-листом
   ▼
POS Desktop (Tauri)  ──── pos-bff (Node/Fastify)
   │   POST /orders, /items, status changes (Order Service)
   │   WS subscribe: kds_settings, stop-list, menu invalidation
   ▼
Order Service: new → in_progress → ready → closed | cancelled
   │
   │ pos-bff WebSocket broadcast
   ▼
KDS Desktop ── фильтрация по kitchen_station_id ── статусы позиций

Подготовка стенда

#ЧтоКак
P1УчёткиFranchise admin, Cashier (PIN на POS), KDS-оператор (PIN). Получить у тест-лида
P2ТТ с привязкой1 ТТ с активным прейскурантом, минимум 2 кухонные станции (Кухня, Бар)
P3Тестовый каталогМинимум: 2 «кухонных» товара (requires_kitchen=true, kitchen_station_id=Кухня), 1 «барный» (Бар), 1 «не-кухонный» (requires_kitchen=false — например бутылочный напиток), 1 товар с группой модификаторов
P4Стоп-листЧистый перед прогоном (GET /stop-list?store_id=X → [])
P5KDS-экраныОткрыты 2 окна: фильтр Кухня и фильтр Бар. Залогинены под PIN
P6DevToolsНа POS — Network/WS вкладка для проверки событий. На KDS — то же

Этап 1 — Admin → POS (пропагация каталога)

Изменение в админке → проверка на POS (refresh меню или WS-инвалидация).

TCДействие в админкеОжидание на POSSeverity при багеBug-якорь
TC-CHAIN-001Создать новый товар, привязать к категории, активироватьПоявляется в меню ТТ (после рефреша / WS-обновления) с корректной ценой из дефолтного прейскурантаCritical
TC-CHAIN-002Изменить name товараНа POS отображается новое имя; в открытом несохранённом заказе — старое (денормализация — см. этап 4)Major
TC-CHAIN-003Изменить base_price товараЕсли в прейскуранте ТТ нет переопределения — на POS новая цена. Если есть override — цена из прейскурантаCriticalсвязано с BUG-050
TC-CHAIN-004Soft-delete товараПропадает из меню POS. В уже созданных заказах (new) — позиция остаётсяCritical
TC-CHAIN-005Восстановить soft-deleted товарПоявляется в меню POSMajor
TC-CHAIN-006Снять галочку «Доступно во всех точках» в карточке товараТовар пропадает с POS этой ТТMajorBUG-031 (галочка возвращается после Save)
TC-CHAIN-007Установить флаг is_admin_onlyТовар не виден на POS под ролью CashierMajor
TC-CHAIN-008Установить is_open_priceНа POS при добавлении в заказ — диалог ввода цены, без цены не добавляетсяMajor
TC-CHAIN-009Установить is_by_weightНа POS — диалог ввода веса; total = price × weightMajor
TC-CHAIN-010Установить is_alcohol / is_tobaccoНа POS — соответствующее поведение (возрастная блокировка / спец-чек)Minor
TC-CHAIN-011Деактивировать категориюВсе товары категории прячутся с POSMajorBUG-040 (активация не каскадная — проверить обратное)
TC-CHAIN-012Изменить порядок категорий в админкеПорядок отображения на POS меняетсяMinor
TC-CHAIN-013Создать модификатор и привязать к товаруНа POS у товара появляется блок модификаторов с min/maxMajor
TC-CHAIN-014Установить min=1, max=2 для группыНа POS нельзя добавить товар без выбора, нельзя выбрать >2MajorBUG-044 (валидации может не быть)
TC-CHAIN-015Удалить группу модификаторов в админке (привязанная к товару)На POS у товара модификаторов нет; в открытом заказе — модификаторы остаются (денорм)Major
TC-CHAIN-016Изменить цену опции модификатораНа POS новая цена при выборе опции в новой позицииMajor
TC-CHAIN-017Создать прейскурант, привязать к ТТ, переопределить цену товараНа POS этой ТТ — цена из прейскурантаCriticalBUG-051 (привязка ТТ к прейскуранту может не работать)
TC-CHAIN-018Изменить цену в прейскурантеНа POS новая цена для новых позиций; в new-позициях — старая (денорм)Major
TC-CHAIN-019Прейскурант: цена = 0 на товареТовар на POS с ценой 0 (или скрыт по бизнес-правилу — уточнить со спекой)Minor
TC-CHAIN-020Поставить товар в стоп-лист ТТНа POS товар грейется/блокируется. Кнопка «Добавить» неактивнаCriticalсвязан с BUG-049
TC-CHAIN-021Снять товар со стоп-листаНа POS товар снова доступенCritical
TC-CHAIN-022Поставить категорию в стоп-листВсе товары категории заблокированы на POSMajor
TC-CHAIN-023Стоп-лист поставлен во время оформления заказа (товар уже в позиции new)Позиция остаётся, но добавить ещё нельзяMajorexploratory — race condition
TC-CHAIN-024Изменить настройки KDS франшизы (/admin/kds/settings)KDS-экраны при «Применить» / перезапуске подтягивают свежие настройки. WS-событие catalog.kds_settings.updated доставляется (P1)MajorBR 5.1

Cross-cut Этапа 1 — sanity

  • Под Cashier (POS) недоступны admin-only товары
  • Меню POS соответствует GET /api/v1/catalog/menu?store_id=X (BR 1.16) — сверить через DevTools
  • При смене прейскуранта без перезапуска POS — нужна инвалидация (если её нет — баг)

Этап 2 — POS → KDS (маршрутизация заказа)

Создание заказа на POS → проверка появления и фильтрации на KDS.

TCСценарийОжиданиеSeverityТип
TC-CHAIN-030Cashier создаёт заказ по столику с 1 кухонным товаромЗаказ появляется на KDS-Кухня в течение ≤ 2 сек. Не появляется на KDS-БарCriticalSmoke
TC-CHAIN-031Заказ только из «не-кухонных» товаров (requires_kitchen=false)На KDS не появляется ни на одном экранеMajorFunctional
TC-CHAIN-032Заказ-микс: кухня + барКухонная позиция → KDS-Кухня; барная → KDS-Бар. Заказ-обёртка с одним номеромCriticalFunctional
TC-CHAIN-033Заказ-микс: кухня + не-кухонныйНа KDS-Кухня — только кухонная позиция, не-кухонная не светитсяMajorEdge
TC-CHAIN-034Товар с модификаторами (выбраны 2 опции)На KDS видны: имя товара, выбранные опции, цена (или без цены — уточнить UX)MajorFunctional
TC-CHAIN-035Позиция с комментарием кассира («без лука»)Комментарий отображается на KDS под названиемMajorFunctional
TC-CHAIN-036Заказ с указанием стола №XKDS показывает №стола / зону / номер заказаMajorFunctional
TC-CHAIN-037Quantity > 1 одного товараНа KDS — отображение либо «×N», либо N карточек (по UX-спеке)MinorFunctional
TC-CHAIN-038Два кассира одновременно создают заказы на одну ТТОба заказа появляются на KDS, нет коллизии номеров (per-store per-day)CriticalEdge
TC-CHAIN-039Заказ создан на ТТ-AНа KDS ТТ-B он не появляется (multi-tenancy)CriticalNegative/RBAC
TC-CHAIN-040Изменить kitchen_station_id товара в админке после появления на KDSСуществующая позиция остаётся на исходном KDS (денорм). Новые позиции — на новой станцииMajorEdge
TC-CHAIN-041Удалить позицию из заказа в new на POSПозиция исчезает с KDSCriticalFunctional
TC-CHAIN-042Добавить позицию в new на POS (заказ уже отправлен)Позиция появляется на KDS на нужной станцииCriticalFunctional
TC-CHAIN-043KDS оффлайн (отключить сеть на 30 сек), создать 2 заказа, восстановить сетьПосле reconnect — KDS подтягивает пропущенные заказы. Если не подтягивает — баг (P0 KDS pull / WS replay)CriticalEdge
TC-CHAIN-044Refresh KDS (F5 / перезапуск Tauri)Текущие активные заказы восстанавливаются из бэкаMajorEdge

Этап 3 — Status-flow (POS ↔ KDS ↔ Order Service)

TCДействиеОжидание во всех 3 местах
TC-CHAIN-050KDS отмечает «Взято в работу» по позиции/заказуOrder: new → in_progress. POS: индикатор «готовится». KDS: позиция перекрашивается
TC-CHAIN-051KDS отмечает «Готово» (все позиции/заказ)Order: in_progress → ready. POS: уведомление «заказ готов». KDS: уезжает с активного экрана (или в архив)
TC-CHAIN-052Кассир закрывает заказ на POS (выдача)Order: ready → closed. KDS не показывает
TC-CHAIN-053Кассир отменяет заказ в new (через UI POS)Order: → cancelled. KDS: позиция исчезает
TC-CHAIN-054Кассир отменяет заказ в in_progressOrder: → cancelled с причиной. KDS: получает уведомление об отмене (визуально)
TC-CHAIN-055Попытка отменить closed заказAPI: отказ (по Order docs — нельзя). UI POS: кнопка отмены недоступна
TC-CHAIN-056Попытка добавить позицию в in_progressAPI: 422 / 409. UI POS: блокирует
TC-CHAIN-057KDS откатывает «Готово» обратно (если функция есть)Order: ready → in_progress. POS: индикатор обратно. Если функции нет — задокументировать как Missing
TC-CHAIN-058Per-position статусы: одна позиция готова, вторая нетЗаказ остаётся in_progress пока не готовы все. Только после последней — ready
TC-CHAIN-059KDS-Кухня закрыл свою позицию, KDS-Бар — нетЗаказ in_progress. KDS-Бар продолжает видеть свою. После закрытия Бара — ready
TC-CHAIN-060Race: два KDS жмут «Готово» по одной позиции одновременноИдемпотентность. Один 200, второй — 200 или 409 (no-op). Не должно быть двойного списания/двойного события
TC-CHAIN-061Per-store per-day numbering: создать заказ в 23:59, оплатить в 00:01Номер по дате создания. С 00:00 нумерация сбрасывается (BR Order #1)

Этап 4 — Денормализация / data integrity

Цель: убедиться что изменения в каталоге не переписывают историю.

TCСценарийОжидание
TC-CHAIN-070Создан заказ → изменить name товара → открыть заказ на POSСтарое имя в позиции; новое имя — только в меню
TC-CHAIN-071Создан заказ → изменить цену в прейскуранте → открыть заказСтарая unit_price в позиции; total не пересчитан
TC-CHAIN-072Создан заказ с модификатором → изменить цену опции → открыть заказСтарая цена опции в позиции
TC-CHAIN-073Создан заказ → soft-delete товар → открыть заказПозиция остаётся видимой и оплачиваемой
TC-CHAIN-074Создан заказ → удалить группу модификаторов → открыть заказМодификаторы в позиции остаются (по referenced_by_product_ids / по денорму)
TC-CHAIN-075Создан заказ → переименовать категорию → KDSНа KDS — category_path на момент создания позиции (или live — уточнить с архитектурой)
TC-CHAIN-076Полный shift-report за деньСуммы соответствуют сумме paid_amount всех closed заказов. RRN/способ оплаты на месте

Этап 5 — RBAC / multi-tenancy

TCРольДействиеОжидание
TC-CHAIN-080Cashier ТТ-APOST /orders с store_id=ТТ-B403
TC-CHAIN-081Cashier ТТ-AGET /orders ТТ-B403 / пусто
TC-CHAIN-082KDS-оператор ТТ-AВидит заказы ТТ-A толькоOK
TC-CHAIN-083ManagerPOST /orders/{id}/completeOK (по Order docs)
TC-CHAIN-084ManagerPOST /orders/{id}/cancel чужой ТТ403
TC-CHAIN-085CashierОтмена чужого заказа в своей ТТ403 (только свой по Order docs)
TC-CHAIN-086FranchiseeGET /orders по ТТ другой ЮЛ403
TC-CHAIN-087PIN-логин на POS без pos.access permissionОтказ
TC-CHAIN-088KDS-PIN-логин под Cashier-PIN (если KDS-PIN отдельный)По спеке — отдельная permission или OK? Зафиксировать факт

Этап 6 — Edge / exploratory / поиск багов

TCСценарийЧто ловим
TC-CHAIN-100Создать пустой заказ (без позиций) → попытка оплатить422 / UI блокирует
TC-CHAIN-101Заказ с 50+ позицийПроизводительность KDS, не падает
TC-CHAIN-102Комментарий 1000+ символовНе ломает UI KDS, не обрезает
TC-CHAIN-103Имя товара 255 символов без пробеловАналог BUG-041 — не ломает KDS-вёрстку
TC-CHAIN-104POS оффлайн → создание заказаЕсли offline-first ещё не реализован (Phase 2.3) — корректное сообщение, не silent fail
TC-CHAIN-105Catalog Service down → POS открытМеню кешируется или ошибка — не белая страница
TC-CHAIN-106Order Service down → попытка создать заказ5xx обработан UI, кассир уведомлён
TC-CHAIN-107Изменить kitchen_station_id на товаре, по которому в in_progress уже находятся 5 позиций на старой станцииСтарые остаются на старой, новые — на новой. Никакого «магического переноса»
TC-CHAIN-108Создать заказ → перезапустить pos-bff (рестарт WS) → KDS должен переподключитьсяHeartbeat / auto-reconnect отрабатывает
TC-CHAIN-109KDS показывает заказ; в админке кто-то soft-delete’ил товар; кассир пытается отменить позициюНе должно ломать ни POS, ни KDS
TC-CHAIN-110Quantity = 0 / отрицательное / дробное на штучном товаре422
TC-CHAIN-111Цена опции модификатора = NULL → выбор опцииОпция бесплатная, не падает
TC-CHAIN-112Time-jump: системные часы на POS уехали на 1 час → создание заказаpaid_at от сервера, не от клиента — корректно

Регрессионный пул (P0)

Минимальный круг после любого изменения в Catalog / Order / pos-bff / POS / KDS:

  1. TC-CHAIN-001, 020, 021 (каталог→POS базовое + стопы)
  2. TC-CHAIN-030, 032, 039 (POS→KDS маршрутизация + multi-tenancy)
  3. TC-CHAIN-050, 051, 052, 053 (полный status-flow по одному заказу)
  4. TC-CHAIN-070, 071 (денормализация)
  5. TC-CHAIN-080, 082 (RBAC по заказам/KDS)

Время прогона: ~25 минут опытным тестером.

Что зафиксировать в репорте прогона

RUN-{date}-CHAIN-{N}
- Тестировщик: {name}
- Версия (commit/тег): {git sha или дата деплоя}
- Прогнано: {N} / 60 кейсов
- Pass: {N} | Fail (новые): {BUG-NNN, ...} | Fail (известные): {BUG-NNN, ...}
- WS-события (sample): catalog.kds_settings.updated — доставлено / нет
- Latency POS→KDS p50 / p95 (sec): {x} / {y}
- Решение: Pass / Pass-with-warnings / Fail

Открытые вопросы (уточнить у тимлида перед прогоном)

  1. WS vs polling — KDS получает заказы через WS, polling или гибрид? От этого зависит поведение TC-CHAIN-043, 108
  2. Per-position vs per-order статусы — KDS управляет позициями отдельно или заказом целиком? От этого зависит TC-CHAIN-058, 059
  3. Откат «Готово» на KDS — поддерживается? (TC-CHAIN-057)
  4. Что с kitchen_station_id-денормом — копируется на момент создания позиции или live (TC-CHAIN-040, 075)
  5. Оффлайн POS — реализовано или Phase 2.3 ещё не начат? (TC-CHAIN-104)
  6. PIN для KDS — отдельный или общий с POS Cashier? (TC-CHAIN-088)