Smoke Test — Production Deploy

Когда использовать

Сразу после того, как админ выкатил все сервисы в k8s (или на VPS) и говорит «вроде поднялось». Цель — за 30–40 минут глазами тестировщика убедиться, что каждый микросервис собрался, отвечает и работает в связке с остальными.

Тест не проверяет бизнес-логику в глубину — для этого есть E2E тест-кезс — ИП от аккаунта до закрытия смены и E2E Test Scenarios. Здесь только «живой / мёртвый».

Как читать этот документ

Каждый шаг устроен одинаково:

👉 Что нажать в интерфейсе
✅ Что должно произойти
🟢 Какой сервис подтверждён живым

Если на шаге что-то пошло не так — остановись и зови админа, не имеет смысла идти дальше: следующие шаги опираются на текущий.

Подготовка

  • URL админки: https://erp-test.nirbi.ru (или прод-URL, который дал админ)
  • Тестовый аккаунт владельца франшизы: demo@nirbi.ru / admin123 (демо-тенант) либо созданный админом свежий
  • Браузер: Chrome / Firefox в обычном режиме (НЕ инкогнито — нужны localStorage и cookies)
  • Открыть DevTools (F12) → вкладка Network и Console — пусть будут открыты всю сессию, чтобы видеть 500-е и красные ошибки
  • POS Desktop: установлен на тестовой машине (или планшет с Android-сборкой POS, если есть)

Блок 0. Базовые health-check’и (1 минута)

Перед тем как лезть в UI — быстро прокликать, что фронт вообще открывается.

ШагЧто нажатьОжиданиеПроверяет
0.1Открыть https://erp-test.nirbi.ruОткрывается страница логина (логотип, поля Email / Пароль, кнопка «Войти»)🟢 Nginx + Admin BFF + Admin Web
0.2F12 → ConsoleНет красных ошибок типа «failed to fetch», «502», «net::ERR_…»🟢 SSL + сеть

Если на 0.1 страница не открывается или висит «502 Bad Gateway» — дальше не идём, проблема в инфре (nginx, BFF упал, контейнер не стартовал).


Блок 1. Авторизация → Auth Service

1.1 Логин

👉 Ввести email + пароль владельца, нажать «Войти»
✅ - Редирект на /dashboard
   - Сверху справа имя пользователя
   - В меню слева видно разделы: Дашборд, Торговые точки, Каталог,
     Склад, Сотрудники, Роли, Заказы, Клиенты, Интеграции
🟢 Auth Service (выдал JWT) + User Service (нашёл пользователя по email)
   + Admin BFF (прокинул запрос)

Если type=individual (ИП)

Раздел «Юридические лица» не виден — это нормально, так задумано в BR 1.4.4.

1.2 /auth/me работает

👉 F12 → вкладка Network → перезагрузить страницу
✅ Найти запрос GET /api/v1/admin/auth/me — статус 200, в ответе:
   { user, franchise, scope, permissions: [...] }
🟢 Auth Service (агрегация permissions) + Redis (кэш scope) + User Service

Если permissions пустой — у пользователя нет прав, дальнейшие шаги работать не будут. Зови админа.


Блок 2. Юридические лица → User Service (только для type=corporate)

Для ИП (individual) этот блок пропускается — у них одно главное ЮЛ создаётся при bootstrap.

2.1 Открыть список ЮЛ

👉 Меню «Юридические лица»
✅ Открывается список (минимум одна запись — главное ЮЛ франшизы),
   нет ошибки 403/500
🟢 User Service (List endpoint)

2.2 Создать ЮЛ Франчайзи

👉 «Добавить» → выбрать тип «Франчайзи» → заполнить:
   - Название: «ООО Тест Франчайзи»
   - ИНН: 7700000000
   - Email владельца: franchisee.smoke@example.com
   - Пароль: TempPass123!
   - Режим прав: «Полный доступ» (системная роль «Администратор»)
   👉 Сохранить
✅ - ЮЛ появилось в списке
   - В таблице «Сотрудники» появился новый сотрудник с email franchisee.smoke@…
🟢 User Service (атомарная транзакция ЮЛ + владелец)

Блок 3. Торговые точки → Store Service

3.1 Создать ТТ

👉 Меню «Торговые точки» → «Добавить»
   - Название: «ТТ Smoke 001»
   - Адрес: Москва, ул. Тестовая, 1
   - Телефон: +7 (495) 000-00-00
   - ЮЛ: главное ЮЛ
   - Расписание: Пн-Вс 09:00-23:00
   👉 Сохранить
✅ ТТ появилась в списке со статусом «Черновик»
🟢 Store Service (CRUD)

3.2 Опубликовать ТТ

👉 Открыть «ТТ Smoke 001» → кнопка «Опубликовать»
✅ Статус меняется на «Опубликована» (зелёный бейдж)
🟢 Store Service (state-машина)

3.3 Привязать POS-терминал

👉 Карточка ТТ → вкладка «POS-терминалы» → «Добавить»
   - Заводской номер ФН: 9999000099990001
   - РН ККТ: 0001234567000001
   👉 Сохранить
✅ Терминал появился в списке, статус active
🟢 Store Service (POSTerminalController)

Блок 4. Каталог → Catalog Service ⭐ (главный по объёму)

4.1 Создать категорию

👉 Меню «Каталог» → вкладка «Категории» → «Добавить»
   - Название: «Кофе»
   👉 Сохранить
✅ Категория «Кофе» появилась в дереве слева
🟢 Catalog Service (categories CRUD) + Kafka (событие catalog.category.upserted)

4.2 Создать товар

👉 Вкладка «Товары» → «Добавить»
   - Название: «Латте 0.3»
   - Категория: Кофе
   - Цена: 250
   - КБЖУ: 120 ккал, 5/4/15
   👉 Сохранить
✅ Товар появился в списке внутри категории «Кофе»
🟢 Catalog Service (products CRUD) + Kafka (catalog.product.upserted)

Это и есть «создал товар → каталог-сервис работает чётко». Если получилось — самый объёмный сервис жив.

4.3 Создать группу модификаторов

👉 Вкладка «Модификаторы» → «Добавить группу»
   - Название: «Молоко»
   - Тип выбора: один из
   - Опции: Обычное (0₽), Безлактозное (+30₽), Овсяное (+50₽)
   👉 Сохранить
✅ Группа «Молоко» появилась в списке с тремя опциями
🟢 Catalog Service (modifier_group_upserted в Kafka)

4.4 Привязать модификатор к товару

👉 Открыть товар «Латте 0.3» → вкладка «Модификаторы» → добавить группу «Молоко»
👉 Сохранить
✅ В карточке товара видно «Молоко (3 опции)»

4.5 Создать прейскурант

👉 Вкладка «Прейскуранты» → «Добавить»
   - Название: «Базовый»
   - Привязать к ТТ «ТТ Smoke 001»
   - Цены: Латте 0.3 → 280₽
   👉 Сохранить и применить
✅ Прейскурант создан и применён
🟢 Catalog Service (price-list module)

4.6 Стоп-лист

👉 Меню «Стоп-листы» → выбрать ТТ «ТТ Smoke 001» →
   найти «Латте 0.3» → переключатель «В стоп»
✅ Появляется иконка «🚫 в стопе» рядом с товаром
🟢 Catalog Service (stoplist per-store)

После этого вернуть переключатель обратно — иначе позже на POS товара не будет.


Блок 5. Склад → Warehouse Service

5.1 Создать ингредиент

👉 Меню «Склад» → «Ингредиенты» → «Добавить»
   - Название: «Молоко 3.2%»
   - Единица: л
   👉 Сохранить
✅ Ингредиент в списке
🟢 Warehouse Service (ingredients CRUD)

5.2 Создать техкарту для товара

👉 Открыть товар «Латте 0.3» → вкладка «Техкарта» →
   «Создать» → добавить ингредиент «Молоко 3.2%», 0.2 л
   👉 Сохранить
✅ Техкарта сохранилась, видна себестоимость
🟢 Warehouse Service (recipes)

5.3 Акт приёмки

👉 Меню «Склад» → вкладка «Приёмка» → «Создать акт»
   - Склад: ТТ Smoke 001
   - Добавить позицию: Молоко 3.2%, 10 л, 80₽/л
   👉 Сохранить как черновик → затем «Провести»
✅ Акт получает статус «Проведён»
   На вкладке «Остатки» видно: Молоко 3.2% — 10 л
🟢 Warehouse Service (acts + остатки + FIFO)

Блок 6. Сотрудники + Роли → User Service

6.1 Создать роль «Кассир»

👉 Меню «Роли» → «Добавить роль»
   - Название: «Кассир Smoke»
   - Permissions: pos.access ✅, orders.create ✅, payments.process ✅
   - Зарплата: 350 ₽/час
   👉 Сохранить
✅ Роль в списке, 0 сотрудников
🟢 User Service (roles + permissions)

6.2 Создать сотрудника-кассира

👉 Меню «Сотрудники» → «Добавить»
   - ФИО: Тестов Тест Тестович
   - Email: cashier.smoke@example.com
   - Телефон: +7 (900) 000-00-00
   - Роль: «Кассир Smoke» на ТТ «ТТ Smoke 001»
   - PIN: 1234
   👉 Сохранить
✅ Сотрудник в списке. PIN установлен (видно «PIN: ✅»)
🟢 User Service (employees + employee_role_stores) + Auth Service (pin_hash)

Блок 7. Клиенты → Customer Service

7.1 Создать клиента

👉 Меню «Клиенты» → «Добавить клиента»
   - Имя: Иван Smoke
   - Телефон: +7 (911) 111-11-11
   - Email: ivan.smoke@example.com
   👉 Сохранить
✅ Клиент в списке
🟢 Customer Service (customers CRUD)

7.2 Создать группу клиентов

👉 Меню «Клиенты» → вкладка «Группы» → «Добавить»
   - Название: «VIP Smoke»
   - Тип: статическая
   👉 Сохранить → открыть → добавить туда Ивана Smoke
✅ В карточке Ивана видна метка «VIP Smoke»
🟢 Customer Service (customer_groups + scheduler)

Блок 8. POS-касса → POS BFF + Auth + Order Service

8.1 PIN-логин на POS

👉 Открыть POS Desktop → выбрать «ТТ Smoke 001» → ввести PIN: 1234
✅ - Открывается экран смены
   - Сверху имя кассира «Тестов Т.Т.»
🟢 POS BFF + Auth Service (pin-login + pos.access check) + User Service (PIN lookup)

8.2 Открыть смену

👉 Кнопка «Открыть смену» → подтвердить
✅ Появляется главный экран кассы с меню (категории слева)
🟢 Order Service (shift open) + Catalog Service (отдача меню)

8.3 Создать заказ

👉 Тапнуть «Кофе» → «Латте 0.3» → выбрать модификатор «Овсяное»
   → «Добавить в заказ»
✅ Позиция в чеке справа: «Латте 0.3, овсяное — 330₽»
   (280 базовая + 50 за овсяное молоко)
🟢 Catalog Service (меню с прейскурантом + модификаторы)
   + Order Service (создание заказа в статусе new)

8.4 Прикрепить клиента

👉 Кнопка «Клиент» → ввести «+7 911» → выбрать Ивана Smoke
✅ Имя клиента появилось в шапке чека
🟢 Customer Service (поиск по phone) + Order Service (привязка)

8.5 Оплата наличными

👉 «К оплате» → способ «Наличные» → ввести сумму → «Подтвердить»
✅ - Заказ закрыт (статус «Оплачен»)
   - На экране «Чек выдан»
🟢 Order Service (фиксация оплаты + переход new → ready → closed)

8.6 Закрыть смену

👉 Меню кассы → «Закрыть смену» → «Z-отчёт»
✅ Открывается отчёт:
   - Выручка: 330₽
   - Заказов: 1
   - По способам оплаты: Наличные 330₽
🟢 Order Service (/internal/orders/shift-report)
   + User Service (агрегатор отчёта смены)

Блок 9. Заказы в админке → Order Service (read-side)

9.1 Список заказов

👉 В админке: Меню «Заказы»
✅ Видно созданный заказ — № заказа, ТТ Smoke 001, 330₽, Оплачен,
   клиент «Иван Smoke»
🟢 Order Service (list endpoint) + Customer Service (denorm имя клиента)

9.2 Детали заказа

👉 Открыть заказ
✅ Видны: позиции, модификатор «овсяное», способ оплаты, время,
   привязанный клиент
🟢 Order Service (детали)

Блок 10. Интеграции → Aggregator Service + Paykeeper Adapter

Эти разделы нужны если соответствующие сервисы заявлены в скоупе деплоя. Если не заявлены — пропускаем.

10.1 PayKeeper — подключить аккаунт

👉 Меню «Интеграции» → «PayKeeper» → «Добавить аккаунт»
   - ЮЛ: главное ЮЛ
   - Host: koala-test.paykeeper.ru
   - Логин/пароль: из секретов админа
   - Informer seed: тестовый
   👉 Сохранить → «Проверить соединение»
✅ Зелёная плашка «Соединение установлено»
🟢 Paykeeper Adapter (HTTP client + AES-GCM шифрование секретов)

10.2 Caталог-синк в PK (BR 3.4)

👉 На карточке аккаунта PK → «Запустить синхронизацию каталога»
✅ Прогресс-бар → отчёт «Синхронизировано N товаров, 0 ошибок»
🟢 Paykeeper Adapter (catalog sync) + Catalog Service (full snapshot endpoint)
   + Kafka (consumer группа)

10.3 Aggregator — подключить ТТ к Яндекс.Еде (если в скоупе)

👉 Меню «Интеграции» → «Агрегаторы доставки» → выбрать ТТ →
   «Подключить Яндекс.Еду» → ввести OAuth credentials → Сохранить
✅ Статус подключения — «Активно»
🟢 Aggregator Service (binding CRUD + OAuth client)

Блок 11. Возврат через PayKeeper (если PK подключён)

Полный сценарий — в PayKeeper — возвраты. Здесь — короткий smoke.

11.1 Создать PK-заказ и оплатить

👉 На POS — выбрать ТТ с подключённым PK-терминалом → создать заказ →
   способ оплаты «PayKeeper» → получить QR/ссылку → оплатить из ЛК PK
✅ Заказ переходит в paid, есть pk_payment_id
🟢 Paykeeper Adapter (invoice + informer webhook) + Order Service

11.2 Полный возврат

👉 В админке: открыть заказ → «Запросить возврат» → полная сумма
✅ - В Kafka событие order.refund_requested
   - Платёж в ЛК PK уходит в refunding → refunded
   - В админке статус заказа «Возвращён» (через webhook или через 3-5 мин через poll)
🟢 Paykeeper Adapter (reverse_payment + RefundCheckScheduler)
   + Order Service (refund_records)

Финальная сводка

После прохождения всех блоков — заполнить таблицу:

СервисБлокиСтатус
Nginx + Admin Web + Admin BFF0, 1.1
Auth Service1, 6.2 (PIN), 8.1
User Service1.1, 2, 3 (через scope), 6
Store Service3
Catalog Service4, 8.2 (меню)
Warehouse Service5
Customer Service7, 8.4, 9.1
Order Service8.3, 8.5, 8.6, 9
POS BFF + POS Desktop8
Paykeeper Adapter10.1, 10.2, 11
Aggregator Service10.3
Kafka (косвенно)4.1, 4.2, 10.2, 11.2
Redis (косвенно)1.2 (кэш scope)
PostgreSQL (косвенно)везде, где «Сохранить»

Если все строки зелёные — деплой принят.

Если хотя бы одна красная — собрать в одном сообщении админу:

  1. Какой блок упал (например, «4.2 — товар не сохраняется»)
  2. Что увидел тестировщик на экране (текст ошибки)
  3. Что в DevTools → Network: статус-код запроса, request URL, тело ответа
  4. Время по МСК — чтобы админ нашёл нужные строки в логах

Ссылки