Сессия 2026-05-12 — Полный обход admin-панели на проде
Переключились на прод-стенд admin.nirbi.ru/admin (см. memory project_prod_stand_admin.md). Старая регрессия POS/KDS на erp-test.nirbi.ru (F66-F76) заморожена до возврата к POS/KDS.
Цель
Последовательно пройти все разделы admin-панели на проде, найти пользовательские баги/проблемы. Без POS и KDS интеграции — это позже.
Скоуп этой сессии
Разделы по порядку (план уточним по факту первой навигации):
- Логин → дашборд / стартовая
- Юридические лица / Франшизы
- Торговые точки (ТТ)
- Сотрудники + Роли + Права
- Каталог: категории, товары, модификаторы, прейскуранты, стоп-листы
- Меню / доступность
- Склад / поставки (если есть в этом стенде)
- Заказы (admin view, не POS)
- Отчёты / аналитика
- Настройки
⛔ Не трогаем: POS-flow, KDS-flow, оплаты через PayKeeper.
Сетап
- Учётка:
admin@erp.local/<password — см. private/creds.md>(Администратор, all_franchise) - Браузер: Playwright (chromium)
- Скриншоты:
test-base/screenshots/2026-05-12-admin-prod-walkthrough/
Карта sidebar (снято 2026-05-12)
Dashboard /admin
Юридические лица /admin/legal-entities
Торговые точки /admin/stores
Сотрудники
├ Список /admin/employees
├ Роли /admin/roles
├ Расписание /admin/schedule
├ Шаблоны смен /admin/schedule/templates
├ Активность /admin/activity/employees
├ Терминалы /admin/activity/terminals
├ Формулы зарплаты /admin/payroll/formulas
└ Ведомости /admin/payroll
Каталог
├ Товары /admin/catalog/products
├ Модификаторы /admin/catalog/modifiers
├ Категории /admin/catalog/categories
├ Прейскуранты /admin/catalog/price-lists
├ Временные тарифы /admin/catalog/time-tariffs
├ Расписание меню /admin/catalog/menu-availability
├ Внешние меню /admin/external-menus
├ Ингредиенты /admin/catalog/ingredients
├ Стоп-листы /admin/catalog/stop-lists
└ Кухонные станции /admin/catalog/kitchen-stations ← KDS-adjacent, скип в этой сессии
Склад
├ Остатки /admin/warehouse/inventory
├ Приёмки /admin/warehouse/receipt-acts
└ Списания /admin/warehouse/write-off-acts
Заказы
├ Активные /admin/orders/active
├ История /admin/orders/history
├ Очередь кухни /admin/kitchen ← KDS, скип
├ Журнал транзакций /admin/transactions
└ Мониторинг смен /admin/shifts/monitor
Финансы
└ Чаевые (Нетмонет) /admin/tips
Настройки KDS ← скип
└ Звуки и пороги /admin/kds-settings
Устройства ← POS/KDS, скип
└ POS и KDS /admin/devices
Скоуп этой сессии (после снятия карты)
В работе: Юр.лица, ТТ, Сотрудники (всё), Каталог (без «Кухонные станции»), Склад, Заказы (без «Очередь кухни»), Финансы.
Откладываем до возвращения к POS/KDS: Кухонные станции, Очередь кухни, Настройки KDS, Устройства.
Что сделали — chronological log
Этап 0: Логин + dashboard (2026-05-12 ~11:26 MSK)
- URL
https://admin.nirbi.ru/admin/login→ форма «Войдите в систему» - Логин
admin@erp.local/<password — см. private/creds.md>→https://admin.nirbi.ru/admin(dashboard «Добро пожаловать, Admin!») - Console: только 2× 404 на
/favicon.ico— отдельная мелочь, см. ниже. - На dashboard виден блок «Информация о пользователе»: Роль: «—» (прочерк), Franchise ID: (пусто). У admin-пользователя должна быть роль или хотя бы что-то осмысленное.
Этап 1: Снятие карты sidebar
- Раскрыл все collapsible-секции, см. карту выше.
Этап 2: Юр.лица — список + карточка главного ЮЛ + создание
Список /admin/legal-entities — таблица из 3 baseline-записей:
- ООО Франшиза Главное (Франшиза, Активен, 1 ТТ, Главное)
- ИП Иванов Партнёр (Франчайзи, Активен, 0 ТТ)
- ООО Петров и Ко (Франчайзи, Приостановлен, 0 ТТ)
Фильтры: поиск по названию/ИНН, статус (Все/Активен/Приостановлен), тип (Все/Франшиза/Франчайзи). Кнопки «Импорт» и «+ Создать».
Карточка ЮЛ /admin/legal-entities/10000000-0000-0000-0000-000000000001 — 3 вкладки:
- Реквизиты ✓ — Основные данные / Банковские / Контакты (поля Банк/БИК/Р-с/К-с/Телефон/Email все «—»)
- Торговые точки ✓ — заглушка «Привязано 1 ТТ. Перейти к списку →» (без фильтра по ЮЛ)
- PayKeeper ✓ — info-блок «PayKeeper теперь настраивается на странице ТТ»
В backlog (BUG-005) упоминались вкладки «Информация», «Сотрудники», «Документы» — их в текущем UI нет, заменены на Реквизиты/ТТ/PayKeeper. BUG-005 устарел.
🐛 F76 — Ссылка «1 ТТ» в блоке Основные данные ведёт на список ЮЛ. href="/admin/legal-entities" вместо /admin/stores (с фильтром по ЮЛ или без). Пользователь кликает «1 ТТ», ожидая увидеть ТТ — попадает обратно в тот же список ЮЛ. Скрин: F76-le-card-1tt-link-broken.png. Severity: 🟢 Minor (не блокирует, но запутывает).
Где смотреть: admin-spa, компонент карточки ЮЛ, в блоке «Основные данные» поле «Торговые точки» — <Link to="/admin/stores?legal_entity_id=..."> или хотя бы /admin/stores. Сейчас просто /admin/legal-entities.
Редактирование ЮЛ (/edit) — форма открывается без ошибок (BUG-006 не воспроизводится у admin-пользователя — возможно фикснут, возможно специфичен для другой роли — verify позже). Тип ЮЛ и Статус в форме не редактируются.
Создание ЮЛ (/new) — wizard в 2 шага. Шаг 1: только «Франчайзи» доступен (логично — Головное уже создано). Шаг 2 — большая форма (Основные/Банк/Контакты/Договор/Владелец/Права).
🐛 F77 — Форма создания франчайзи не валидирует форматы ИНН/ОГРН/Email на клиенте. При нажатии «Создать» с явно невалидными значениями (ИНН=12345 5 цифр, ОГРН=1234567 7 цифр, Email ЮЛ=notanemail, Email владельца=owner_no_at_sign) — UI не показывает ни одной ошибки формата. Единственная ошибка — Дата договора: Обязательное поле (т.к. она пустая). Если бы дата была заполнена, форма попыталась бы отправиться. Скрин: F77-le-new-no-format-validation.png. Severity: 🟡 Major.
Где смотреть: admin-spa, форма /admin/legal-entities/new. Нужна клиентская валидация:
ИНН: ровно 10 или 12 цифр (placeholder уже намекает)ОГРН: ровно 13 или 15 цифрEmail(и ЮЛ, и владельца): regex/HTML5 type=emailБИК/Р-с/К-с: ровно 9 / 20 / 20 цифр (если значения заданы) Также проверить серверную валидацию — fallback на 400. Не submit’ил на прод (создаст мусорный ЮЛ), нужно согласие пользователя для теста с реальной отправкой.
Хорошее (✓): при выходе из формы с несохранёнными изменениями браузер показывает confirm Есть несохранённые изменения. Покинуть страницу?. UX корректен.
Этап 3: Торговые точки
- Список
/admin/stores: 1 ТТ «ТТ Smoke 001», Москва, ООО Франшиза Главное, Опубликована. - Карточка ТТ: 6 вкладок (Информация ✓, Меню ✓ — пусто, Терминалы ✓ — 1 терминал «Терминал 1» ФН/РН ККТ, Интеграции ❌, Столы ✓ — пустая карта, Кухня — пропущена как KDS).
- 🐛 F78 —
/admin/stores/<id>→ вкладка Интеграции →GET /api/v1/admin/paykeeper/accounts/by-store/<id>→ 500. UI «Не удалось загрузить данные PayKeeper». Severity 🟡 Major. СкринF78-store-integrations-paykeeper-500.png. Где смотреть:payments-service, handlerpaykeeper/accounts/by-store/{store_id}. Вероятно отсутствует обработка случая «нет привязки» — должен возвращать 200 сnull, не 500. - Форма
/admin/stores/new: required-поля используют HTML5 native validation (browser popup) — отличается от формы ЮЛ с кастомными сообщениями. Inconsistency UX, PROPOSAL. - Время в карточке ТТ выводится с секундами (
09:00:00) — UX-мелочь, PROPOSAL.
Этап 4: Сотрудники (Список/Роли/Расписание/Шаблоны/Активность/Терминалы/Формулы/Ведомости)
- Список сотрудников
/admin/employees: 2 сотрудника — Admin Admin (Администратор), Тест Тестов ("Кассир"— с кавычками). - Роли
/admin/roles: 2 роли —"Кассир"(Пользовательская) и Администратор (Системная). Карточка роли: 4 таба прав (Общее/Back-office/POS/Зарплата). - 🐛 F79 — Названия с кавычками везде: роль
"Кассир", товар"Латте 0.3", категория"Кофе", модификатор"Молоко", ингредиент"Молоко 3.2%", прейскурант"Базовый". Скорее всего — общий input-component не trim’ит и не запрещает кавычки в начале/конце. Severity 🟢 Minor (сквозной). СкринF79-role-name-with-quotes.png. Где смотреть: общий form-input компонент для названий, либо отдельные валидаторы при создании. Нуженtrim()+ запрет открывающих/закрывающих кавычек. - 🐛 F80 — Stale JWT (~15 мин), SPA не редиректит на login и не обновляет токен. При истечении API возвращают 401, экраны рендерятся пустыми / с ошибками («Не удалось загрузить»). Severity 🟡 Major. Воспроизведено при открытии
/admin/roles/<id>после 15+ мин активности. СкринF80-jwt-expired-no-redirect.png. Где смотреть:admin-spaHTTP-клиент — нет интерсептора 401 → logout/redirect. Также нет refresh-token flow (если планируется). - Форма создания роли
/admin/roles/new: поле «Название» безrequiredатрибута — клиент пропустит пустое название. Замечание к F79. - Расписание/Шаблоны смен/Активность/Терминалы/Формулы зарплаты/Ведомости — открываются без 500. Замечание: в «Формулы зарплаты» формула с типом «По роли», но поле «Роль/Сотрудник» = «—» (неполные данные).
Этап 5: Каталог
- Товары
/admin/catalog/products: 1 товар"Латте 0.3". Карточка: 3 вкладки (Информация/Модификаторы/Техкарта). - Подмечено: техкарта
"Латте 0.3"—Выход: 0 г, при наличии ингредиента 0.2л. Скорее всего unit-конверсия (л → г) не сделана, или просто баг расчёта. - Модификаторы: 1 модификатор
"Молоко"(Группа, 3 опции). - Категории: 1 категория
"Кофе". - Прейскуранты: 1 прейскурант
"Базовый"(По умолчанию). Назначено ТТ: 0, но в карточке «ТТ Smoke 001» поле «Прейскурант» = «По умолчанию (дефолтный)». Совпадает с backlog BUG-051 (default применяется неявно). Подтверждаю верность. - Временные тарифы / Расписание меню / Внешние меню / Ингредиенты / Стоп-листы — открываются без ошибок.
- Кухонные станции — пропущено (KDS).
Этап 6: Склад
- Остатки/Приёмки/Списания — все открываются, пусто, без ошибок.
Этап 7: Заказы
- Активные/История/Журнал транзакций/Мониторинг смен — открываются, пусто, без ошибок. «Очередь кухни» — пропущено (KDS).
Этап 8: Финансы → Чаевые (Нетмонет)
- 🔴 F81 — Mock-данные в проде.
/admin/tipsотображает: Кофейню Тверскую, Кофейню Арбат, 4 «официантов» (Анна Белова, Борис Котов, Елена Сидорова, Максим Петров), десятки «заказов» №№ 12, 23, 75, 95, 104, …, 479 — всех нет ни в одном другом разделе системы. На франшизе только ТТ «ТТ Smoke 001» и 2 сотрудника (Admin Admin, Тест Тестов). - Сетевой анализ: при загрузке страницы — ни одного запроса к
/api/.../tips-подобным эндпоинтам. Только/api/v1/admin/auth/me. Данные захардкожены во фронтенде. - Severity: 🔴 Critical. На проде пользователь видит фейковые финансовые цифры (13 950 ₽ «общая сумма чаевых», топ «официантов», 45 транзакций). Может принять рабочие решения на основе мусора.
- Скрин:
F81-tips-fake-data-or-leak.png. Где смотреть:admin-spa, маршрут/admin/tips— компонент содержит hardcoded array. Нужно: убрать mock, заменить на реальный API-вызов; если API ещё не готов — показать «Раздел в разработке» / скрыть пункт из sidebar.
Findings этой сессии
| ID | Sev | Зона | Title | Status |
|---|---|---|---|---|
| F76 | 🟢 | legal-entities | Ссылка «1 ТТ» в карточке ЮЛ ведёт на /admin/legal-entities (сам список) | open |
| F77 | 🟡 | legal-entities | Форма создания франчайзи: нет клиентской валидации ИНН/ОГРН/Email | open |
| F78 | 🟡 | stores/integrations | ТТ → Интеграции → 500 на GET paykeeper/accounts/by-store/<id> | open |
| F79 | 🟢 | catalog/employees/roles | Названия с кавычками везде (роль, товар, категория, ингредиент, модификатор, прейскурант) — нет trim/sanitize | open |
| F80 | 🟡 | auth-rbac | Stale JWT (15 мин), SPA не редиректит на login, нет refresh | open |
| F81 | 🔴 | finance/tips | Чаевые (Нетмонет) показывают frontend-hardcoded mock-данные на проде | open |
PROPOSAL:
- Inconsistent form validation UX (ЮЛ — кастомные ошибки, ТТ — HTML5 native).
- Время в карточке ТТ показывается с секундами
09:00:00. - Поле «Название роли» в форме создания не required на клиенте.
Подтверждение backlog:
- BUG-005 → retracted (UI карточки ЮЛ переделан: Реквизиты/ТТ/PayKeeper вместо Информация/Сотрудники/Документы).
- BUG-006 не воспроизводится у admin (специфично для другой роли — verify-needed под Manager/Franchisee).
- BUG-051 подтверждён: default-прейскурант применяется неявно, ТТ не имеет привязки в БД.
Наблюдение dashboard:
- Поле «Роль: —» для admin-пользователя — by-design или баг? Не критично, отложено.
Этап 9: Глубокий проход — E2E связность, edge-cases, состояния, каскады
После reality-check от пользователя — проход «по верхам» дополнен глубокими сценариями. Создан [TEST] товар + [TEST] категория, проверены связность, фильтры/поиск, edge-данные, удаление/восстановление, каскад.
Создание [TEST] объектов
- Создан товар
[TEST] Капучино 0.4(POST /catalog/products → 201, idd1224622-a76d-4bce-bee8-64bf2cc3411e). - Создана категория
[TEST] Кофейная(через+ Добавить категориюс leading/trailing пробелами[TEST] Кофейная— пробелы обрезаны при сохранении). - Привязана категория к товару через edit-форму — сохранилось.
Связность (положительная)
- ✓ [TEST] товар появился в поиске стоп-листов сразу.
- ✓ [TEST] категория появилась в селекте категории товара сразу.
- ✓ После привязки — фильтр товаров «Все категории» →
[TEST] Кофейнаякорректно фильтрует. - ✓ Поиск по «капу» (нижний регистр) находит «Капучино» — case-insensitive работает.
- ✓ Inline toggle статуса (Активен/Неактивен) в списке товаров — работает.
- ✓ Восстановление из «Удалённые» товары — работает (связь с категорией сохраняется).
Каскады
- ✓ Удаление категории, к которой привязан товар → 422 «Невозможно удалить: в категории есть товары». Backend защищает, UI показывает понятное сообщение. Хороший пример обработки 422.
Новые находки этого этапа
| ID | Sev | Where | What |
|---|---|---|---|
| F82 | 🟢 | catalog/products/new | Поля Вес брутто/нетто/Калории/Белки/Жиры/Углеводы не имеют min=0. Принимают -5, -100 без HTML5-валидации. (Поля «Сортировка» и «Время приготовления» min=0 настроены — inconsistency) |
| F83 | 🟢 | catalog/products/new | Поле «Цвет (HEX для POS)» принимает любой текст («не хекс») — нет pattern-валидации |
| F84 | 🟡 | catalog/products/new | «Сохранить» беззвучно ничего не делает при HTML5-инвалид (popup не виден если поле вне viewport). На форме ЮЛ — кастомные сообщения. Inconsistency |
| F85 | ⚠️ XSS-warning | catalog/products/new | Название принимает <script>alert(1)</script> без sanitization на клиенте. Серверная sanitization не проверена. Если render через innerHTML — XSS-risk |
| F86 | 🔴 / BUG-060 | stores/menu | GET /api/v1/admin/catalog/menu/<store> → 500. UI показывает «Нет товаров в меню» вместо ошибки → скрывает 500 за пустым состоянием. BUG-060 подтверждён |
| F87 | 🟢 | catalog/products/ | Карточка товара не отображает поле «Категория», даже если назначена. В списке колонка есть |
| F88 | 🟢 | catalog/categories | Confirm-диалог удаления оборачивает имя в кавычки: Удалить категорию ""Кофе""? — двойные кавычки на F79-данных. Visual glitch |
Дополнения к старым находкам
- F79 уточнён: trim для пробелов работает на категории — но кавычки
"..."остаются в названиях везде. То есть существует выборочная санитизация (trim есть, dequote — нет). Также backend принял<script>в названии товара (F85). - F80 повторно подтверждён: через 15 мин 401 на
/api/v1/admin/auth/meбез редиректа на login.
Не покрыто этим заходом (нужен отдельный)
- Concurrency (правка одного объекта в 2 вкладках) — не сделано.
- Permissions/RBAC под Manager/Franchisee — отложено (требует владельца партнёра, а пользователь сказал «без новых аккаунтов»).
- E2E «ТТ → опубликовать → снять → удалить» — частично.
- Поиск/фильтры везде — частично (только товары).
- Длинные строки (1000+ символов), большие числа, дата в будущем — не до конца.
- Загрузка файлов (фото товара, импорт ЮЛ.xlsx) — не трогал.
Артефакты [TEST]-объектов
- Товар
[TEST] Капучино 0.4(idd1224622-a76d-4bce-bee8-64bf2cc3411e) → в «Удалённые» товары. - Категория
[TEST] Кофейная(ide450d896-4d92-4ad2-9c4a-82cc1c590b00) → удалена насовсем.
Этап 10: Расширенный проход (после reality-check #2)
После повторного вопроса «почему остановились» продолжен глубокий проход.
[TEST] ТТ flow (Опубликовать/Снять/Удалить + edge)
- Создана
[TEST] ТТ Капучино(id157dffc5-bc7f-4c43-8905-03b5abb9268f) с минимально валидными данными. - ✓ Опубликована → статус «Опубликована», кнопка «Снять с публикации».
- ✓ Снято → статус снова «Черновик». Состояние «Приостановлена» из фильтра — отдельный flow, не воспроизводилось через этот UX.
- ✓ Удалена в конце прохода.
- 🐛 F89 — селект «Прейскурант» в edit ТТ: две опции с пометкой «(дефолтный)» (null-placeholder + реальный default). Путает.
- ℹ️ Поле «Юридическое лицо» в edit — disabled с подписью «ЮЛ нельзя изменить после создания». ✓ Хорошо.
Concurrency (2 вкладки)
- Открыл одну ТТ в двух вкладках, изменил имя в обеих, сохранил последовательно.
- 🐛 F90 — Last-write-wins: вторая правка тихо затёрла первую. Нет optimistic-lock, нет диалога «данные изменились». Major.
Edge-данные на форме ТТ
- 🐛 F91 (CRITICAL) — PATCH ТТ с длинным именем (516 char + 🔥💩 + ёёё) → 500. UI беззвучен — пользователь стоит на /edit без feedback. Backend не валидирует длину строки.
- ✓ F92 / +: HTML5
type="email"валидирует email в форме ТТ. Это положительно — но inconsistency с формой ЮЛ (там F77 пропустила email без @).
Backlog regressions (подтверждены)
- 🐛 F93 / BUG-018-019 — Save шаблона смены → 500 (
PUT /api/v1/admin/shift-templates/<id>). UI беззвучен. Backlog подтверждён. - 🐛 F94 / BUG-023 — Save формулы зарплаты «По роли» → 500 (
PUT /api/v1/admin/salary-formulas/<id>). Backlog подтверждён. - 🐛 F95 / BUG-024 — Экспорт CSV ведомости → 422. URL составлен криво:
?store_id=&period=2026-05/export(пустой store_id + period с прилипшим/export). Backlog подтверждён. - ✓ BUG-007 verify-needed — Поиск сотрудников по «Тест» нашёл «Тест Тестов» под admin. Возможно фикс или специфично для другой роли.
- ✓ BUG-002 verify-needed — Фокус в input не теряется после первого символа (поверка на форме «Сотрудника»). Не воспроизводится у admin.
Прейскуранты и каталог
- Создан
[TEST] Премиумпрейскурант, удалён. Confirm-диалог «Это действие необратимо» ✓. - 🐛 Save цен в прейскуранте без UI-feedback — нет «Сохранено» или toast. Мелочь.
- 🐛 F98 (CRITICAL) — Кнопка «Дублировать» товар → 500 (
POST products/<id>/duplicate). UI беззвучен. - 🐛 F99 (CRITICAL) — Кнопка «+ Дочерняя» категория создаёт на корневом уровне, parent_id не сохраняется. Иерархия категорий сломана.
Роли и i18n
- Тест дубликата имени роли → backend 409 ✓. Но:
- 🐛 F96 — Backend возвращает английскую ошибку «Role with this name already exists», UI выводит её сырой. Локализация ошибок не настроена.
- ✓ Клиентская валидация роли с пустым именем → русское «Название роли обязательно» — локализовано.
- 🐛 F97 — «Отмена» в форме
/admin/roles/newидёт history.back (на предыдущую страницу), а не на список ролей.
Этап 11: Финальный добор (после второго reality-check)
Набивка для пагинации
- Создано 30 [TEST] товаров через тот же endpoint
/api/v1/admin/catalog/productsчто и UI. Поле в payload —unit_of_measure(snake_case). - ✓ Пагинация работает: «Показано 1–20 из 33», 2 страницы, кнопки Назад/Вперёд.
- ✓ Сортировка «Название A-Я» работает:
"<[(Unicode 34 vs 91),«Латте 0.3»идёт первым, потом[TEST].... - ✓ Все 30 [TEST] товаров удалены batch-DELETE’ом по тому же endpoint.
Удалённые роли
- Создан + удалён [TEST] DeleteMe → появился в «Удалённые роли».
- ✓ «Восстановить» из ⋮ меню работает, роль возвращается в активные.
- Окончательно удалён 2-м DELETE.
Внешние меню
- Создано [TEST] Меню для ТВ → /admin/external-menus/
/edit. Видны шаблоны (Сетка/Список/Слайдер/Текст), каталог товаров, привязка к ТТ, выбор прейскуранта (динамический/конкретный). - Удалено.
- Подмечено: «Скачать HTML» доступно у draft-меню до публикации (возможно by-design).
Временные тарифы
- Открыл
/admin/catalog/time-tariffs/<store>→ «+ Создать тариф» → попытка submit без дней недели → ✓ кастомное сообщение «Выберите хотя бы один день недели».
Расписание меню
- Открыл
/admin/catalog/menu-availability/<store>→ «+ Добавить расписание» → submit без названия → ✓ кастомное сообщение «Имя обязательно».
PayKeeper-импорт сотрудников
- 🔴 F100 —
/admin/employees/import-from-paykeeper→GET /api/v1/admin/paykeeper/accounts?status=active→ 502 Bad Gateway. UI шумит «Нет активных интеграций PayKeeper», скрывая 5xx. Связано с F78. Возможно весь PK-сервис down или routing сломан.
Импорт ЮЛ
- ✓ Скачивание шаблона
legal_entities_template.xlsxработает. - Реальный импорт не тестировал (нужен файл).
AI-улучшение товара
- 🐛 F101 — Кнопка «Улучшить с помощью AI» в редакторе товара кликается, но никакой реакции (ни запроса, ни модалки, ни тоста). Фича не имплементирована, но UI показывает кнопку.
Артефакты этапа
- [TEST] Капучино 0.4 (id
d1224622-...) — остался в soft-delete. Hard-delete 404 (видимо такого endpoint нет). Подкупает админ почистит позже. - Стенд чист от других [TEST] объектов.
Положительные подтверждения (этап 10)
- ✓ Backend защищает от каскадных конфликтов (категория с товарами → 422 с понятным сообщением).
- ✓ Уникальность имени роли (409 + текст).
- ✓ Confirm-диалоги на деструктивных действиях, с пометкой «Это действие необратимо».
- ✓ Trim leading/trailing пробелов в категории.
- ✓ PIN-валидация: блокирует буквы и >4 цифр.
- ✓ Восстановление из «Удалённые» сохраняет связь с категорией.
- ✓ Поиск товаров: case-insensitive, по части слова.
- ✓ Фильтр по категории работает.
- ✓ Inline toggle статуса в списке товаров работает.
- ✓ ЮЛ нельзя изменить у существующей ТТ (disabled-поле).
- ✓ Шаблон XLSX для импорта ЮЛ скачивается корректно.
- ✓ Цены модификаторов в прейскуранте отображаются с привязкой к товару.
Этап 12: Подготовка к POS/KDS
Регистрация устройств
Сегодня же на стенде поднимали POS и KDS:
- POS-устройство POS-814800 на ТТ Smoke 001 — Online (после починки модуля POS-onboarding силами Сано через накат
erp-pos). - KDS — после диагностики через Grafana + Loki (nginx access-logs в namespace
ingress-nginx) обнаружили баг ingress-роутинга: Tauri-клиенты сReferer: tauri.localhostмаршрутизировались наpos-bffнезависимо от path. POST/api/v1/admin/auth/login→ pos-bff → 404 «Route not found». Сано пофиксил в коде KDS-клиента. После переустановки KDS зарегистрировался.
Детальный док по KDS-блокеру: test-base/archive/KDS-login-route-not-found-2026-05-12.md.
Назначения admin’у на ТТ
Чтобы PIN-логин на KDS работал, понадобилось:
- Задать PIN admin’у = 9999 (PATCH employees) — UI висел F102/F103, фактически записалось.
- Привязать роль «Администратор» admin’а к ТТ Smoke 001 (раньше «Магазины: —»). UI снова висел F102, прошло через прямой PATCH с
{ roles: [{ role_id, store_ids: [...] }] }.
Этап 13: Наполнение стенда для POS/KDS-прогона
Запрос пользователя: «Наполнить меню реалистичными данными, чтобы работал весь функционал, включая временные акции».
Что было создано (через UI + batch через тот же endpoint что UI)
| Сущность | Количество | Детали |
|---|---|---|
| Категории | 12 | Кофе, Напитки, Напитки холодные, Горячие напитки, Завтраки, Супы, Горячее, Гарниры, Салаты, Закуски, Десерты, Выпечка |
| Ингредиенты | 13 | Молоко 3.2%, Говядина, Куриное филе, Свинина, Форель, Картофель, Лук, Морковь, Мука, Яйцо, Сахар, Соль, Сыр |
| Модификаторы | 5 (14 опций) | Молоко (Обычное/Безлактозное/Овсяное), Сироп (Ваниль/Карамель/Шоколад), Размер порции (Малая/Средняя/Большая), Соус (Сметана/Майонез/Кетчуп/Горчица), Без сахара |
| Товары | 67 | Распределены по категориям 4–9 в каждой; после удалили «Капустный с морковью» (дубль) |
| Цены в прейскуранте «Базовый» | 82 | Товары + модификатор-опции, диапазон 80–400 ₽ (random) |
| Временные тарифы | 3 | Завтрак −15% (07:00–11:00 Пн-Вс / категория Завтраки), Бизнес-ланч −25% (12:00–16:00 Пн-Пт / Супы+Горячее+Гарниры), Счастливый час −10% (14:00–17:00 Пн-Пт / Кофе+Десерты) |
| Расписание меню | 1 | Завтраки 07:00–11:00 Пн-Вс — категория Завтраки скрывается из POS вне окна |
| Стоп-лист | 2 | «Латте 0.3» (Тест, ранее) + «Уха из форели» (Нет рыбы) |
| Картинки товаров | 68 (все) | 64 из Wikipedia (точное соответствие блюду), 4 — из Unsplash (товары без подходящих Wiki-статей) |
Корректировки по картинкам и категориям (после ревью пользователя)
- Перенесены из Кофе в Горячие напитки: Какао, Чай чёрный пакетированный, Чай зелёный пакетированный, Чай чёрный в чайнике.
- Прицельно переснаряжены картинки: Куриная лапша (суп с курицей), Запечённая форель (готовое блюдо), Рис отварной, Макароны (спагетти), Овощи на пару (рататуй), Соленья ассорти (соленья), Слойка с сыром (хачапури), 3 пирожка (разные).
Наблюдение по архитектуре (не баг — но в memory)
- Картинки товаров принимаются POS-меню только из
minio.nirbi.ru. PATCHimage_urlс внешним URL (Unsplash) → admin-bff пишет в БД, но POS-меню эту картинку не отдаёт. Загрузка должна идти черезPOST /api/v1/admin/catalog/products/<id>/imageс FormData — backend кладёт в MinIO и возвращает minio-URL.
Итог
✅ Все 9 разделов admin-панели (без POS/KDS) пройдены:
- Юр.лица (полностью)
- Торговые точки (включая карточку, без вкладки «Кухня»)
- Сотрудники — 8 подпунктов
- Каталог — 9 подпунктов (без «Кухонные станции»)
- Склад — 3 подпункта
- Заказы — 4 подпункта (без «Очередь кухни»)
- Финансы — 1 подпункт
🆕 6 новых находок (F76–F81), 1 retracted (BUG-005), 1 подтверждение (BUG-051), 1 verify-needed (BUG-006).
Артефакты:
- Скрины:
test-base/screenshots/2026-05-12-admin-prod-walkthrough/(6 файлов). - Эта сессия:
test-base/sessions/2026-05-12-admin-prod-walkthrough.md.