Демо-стенд «Шаурма Арбат»
Полная синтетика на тестовом VPS erp-test.nirbi.ru. Создана 2026-05-04 через admin-bff/POS-bff API (заводилось скриптом, эмулирующим UI).
Логины
| Роль | Пароль | |
|---|---|---|
| Admin (главное ЮЛ) | admin@erp.local | admin123 |
| Партнёр-владелец | partner@test.local | Test123! |
| Менеджер ТТ | ivan@test.local | Test123! (PIN 1111) |
| Кассир Арбат | anna@test.local | Test123! (PIN 2222) |
| Кассир Сокольники | oleg@test.local | Test123! (PIN 3333) |
| Бариста Арбат | maria@test.local | Test123! (PIN 4444) |
| Курьер | petr@test.local | Test123! (PIN 5555) |
ЮЛ + ТТ
| ТТ | ЮЛ | UUID ТТ |
|---|---|---|
| Арбат-флагман | главное (10000000-…001) | fe4b54a9-2cc1-458f-9d0e-338bbc51df76 |
| Сокольники | главное | 6e02dffe-e344-4859-909b-68059cb39385 |
| Партнёр — Бауманская | c64da7bd-7534-4c75-809b-bcc7e71abe87 | 47c128b9-1f7d-4f01-b6ad-795795b50e7a |
График: 10:00–22:00 (Бауманская до 23:00), Europe/Moscow.
Каталог
- 8 категорий: Шаурма / Бургеры / Снеки / Напитки → {Холодные, Горячие → {Кофе}} / Десерты
- 20 ингредиентов
- 3 кухонные станции: Холодный цех / Горячий цех / Бар
- 4 группы модификаторов: Размер (S/M/L), Соус, Без чего-то, Дополнительно
- 15 продуктов: 4 шаурмы, 2 бургера, 2 снека, 2 хол.напитка, 3 кофе, 2 десерта — все с фото (Unsplash)
- 11 техкарт (для всех
dish-продуктов) — с заполненными cold/hot loss% (мясо 25%, овощи 5%, лепёшка 3%, кофе 10%) - 5 modifier-tech-cards: M (+25г курицы), L (+50г курицы), +Мясо (+100г), +Сыр (+30г), +Соус (+30мл)
- Все 11 dish-продуктов имеют
assembly_time(45-240с) иkitchen_station_id→ kitchen ETA считается корректно - 1 прейскурант «Базовый» (default) с ценами товаров и опций
- 3 time-tariffs (happy hours): Утренний кофе -20% (8-11 пн-пт), Бизнес-ланч -15% (12-15 пн-пт), Happy Hour напитки -10% (17-19 пт-вс)
- 2 menu-availabilities: Завтрак (Кофе 7-12), Десерты (14-22)
Цены (₽): Шаурма Классическая 290, Острая 310, Говядина 350, Сырная 320, Чизбургер 250, Двойной 350, Картофель 120, Наггетсы 180, Кола 80, Сок 120, Эспрессо 100, Латте 180, Капучино 170, Чизкейк 220, Маффин 120. Размер: M +50, L +100. Дополнительно: Сыр +50, Мясо +100, Соус +30.
Склад
3 warehouses (по одному на ТТ, auto-bootstrap при создании ТТ). 3 receipt acts проведены — стартовые поставки (Арбат — полная, Сокольники — 70%, Бауманская — 50% от Арбата).
Stock balances: 60 строк (20 ингредиентов × 3 склада).
Зал
17 zal_tables: 8 на Арбате (4 на 4 чел + 4 на 6 чел), 5 на Сокольниках, 4 на Бауманской.
Зарплата
3 salary formulas:
- Менеджер ТТ — 60 000 ₽/мес фиксированный, норма 160 ч
- Кассир — 250 ₽/час + 1.5x overtime (375 ₽/ч)
- Курьер — 200 ₽/час + 1.5x overtime (300 ₽/ч)
20 shift_records (4 сотрудника × 5 рабочих дней прошлой недели, 10:00–18:30 с обедом 13:00–13:30).
PayKeeper
3 PaykeeperAccount (по одному на ТТ) + 3 PaykeeperTerminal — все с одинаковыми creds koala-test sandbox (общий с Koala_TG_app).
| ТТ | account_id | terminal_id |
|---|---|---|
| Арбат | ac1a270f-4230-401b-a5bb-88eead762c5b | 2e5af560-4b80-4afb-bb26-9780e54de667 (SYNTH-ARBAT-1) |
| Сокольники | c951bba0-e661-4af0-aa50-f83b0bec72b8 | 637c9a03-540a-4a62-8e10-1a3e2433ac49 (SYNTH-SOKOLNIKI-1) |
| Бауманская | a2c34269-58dc-4a67-b476-97b55c07abbd | 00697ce5-9129-4318-a7f5-9f1dd1133370 (SYNTH-BAUMANSKAYA-1) |
Webhook URLs (3 на каждый account: informer / refund / receipt) — например для Арбата:
https://erp-test.nirbi.ru/pk-webhooks/informer/ac1a270f-4230-401b-a5bb-88eead762c5b
Webhook в ЛК PK не переключён
ЛК koala-test всё ещё указывает на Koala_TG_app (
https://user.koalanearby.ru/php/api/payment/webhook). Нужно согласовать с коллегой и переключить хотя бы для одного account_id (предлагается Арбат-флагман).
Стоп-листы
- Арбат: «Шаурма Острая курица» (причина: «Закончился острый перец»)
- Сокольники: категория «Десерты» (причина: «Нет в наличии»)
Оба проверены через POS-меню под cashier-токеном — товары/категории корректно скрыты.
POS-устройства + смены + заказы
| Device | UUID device_id | ТТ |
|---|---|---|
| POS-Арбат-1 | b0e4a21c-172c-4a12-a5ac-04a6aa50eaea | Арбат |
| POS-Сокольники-1 | 0ed454e5-e9c7-46d1-81df-0b3961e82241 | Сокольники |
2 смены открыты (Анна на Арбате, Олег на Сокольниках, fiscal_cycle=1).
7 заказов созданы:
- Арбат cash 470₽ (Анна): Шаурма Классическая M + Соус чесночный + Кола 0.5
- Арбат card 550₽ (Анна, RRN: 123456789012): Чизбургер + Картофель + Латте
- Арбат cash 860₽ (Анна, клиент Дмитрий Иванов): 2× Шаурма Говядина + 2× Кола
- Арбат card 400₽ (Анна, RRN: 222333444555, клиент Светлана Петрова): Латте + Чизкейк
- Арбат cash 410₽ (Анна): Шаурма Классическая + Картофель
- Арбат cash 410₽ (Анна): Шаурма Классическая + Картофель
- Сокольники cash 550₽ (Олег): Шаурма с говядиной L + Острый соус + Эспрессо
Клиенты
5 customers:
- Дмитрий Иванов (+79161112233) — есть заказ
- Светлана Петрова (+79165554433) — есть заказ
- Михаил Соколов (+79263011234)
- Елена Морозова (+79166669900)
- Алексей Волков (+79263030399)
4 customer_groups:
- VIP (static)
- Постоянные клиенты (dynamic, потратили ≥5000 ₽ за всё время)
- Спящие (dynamic, ≥60 дней без заказа)
- Майские именинники (dynamic, birthday_month=5)
Backup
Полные дампы всех 15 БД в ~/erp/backups/synth-pre-2026-05-04/ на VPS — точка отката.
Что не сделано (вне scope синтетики)
- Webhook в ЛК PK не переключён на наш adapter (нужно согласование с коллегой Koala_TG_app)
- DeliveryZones — нет UI и не созданы (заказы только takeaway/dine-in)
- Закрытие смены / Z-отчёт — не делалось
- POS terminals (фискальные терминалы в
store_db.pos_terminals) — пусто, ФН-номера не привязаны (для физических касс) - Customer addresses — пусто (для delivery-заказов)
- External menus / Aggregator bindings — пусто (Yandex.Eda / Delivery Club не подключены)
- Price list assignment на ТТ → POS не пересчитывает цены (известный баг D.2 —
PATCH stores/{id} {price_list_id}сохраняется в БД, но POS catalog menu не использует это поле; нужно копать в pos-bfffetchStorePriceListId) - Partial refund restock — реализован только full refund, partial требует мэппинг refund_cart на recipe_items (отдельная задача)
- Modifier-tech-cards в auto-write-off —
OrderItem.modifiersхранит только group_name+option_name без modifier_option_id, поэтому списание модификаторов пропускается (отдельная задача — расширить ModifierEntry с UUID)
Что заработало после фиксов 2026-05-05
BUG-1 — auto-write-off ингредиентов. Закрытие заказа (POST /orders/{id}/complete) → событие order.completed → warehouse-service создаёт WriteOffAct со status=“posted” и автоматически списывает ингредиенты по техкарте.
BUG-2 — restock на refund. Refund заказа (POST /pos/refunds) → событие order.refunded (с is_full_refund=true) → warehouse-service создаёт обратный акт AUTO-RESTOCK-… и восстанавливает ингредиенты.
Изменения:
erp-order-service: payloadorder.completed/order.refundedтеперь содержитitems[]сproduct_id,product_name,quantityerp-warehouse-service: новыйOrderEventConsumer(Kafka-listener),OrderInventoryService(расчёт списания + создание акта),KafkaConfigс DLT/safeRecoverer
Known issues
— все обнаруженные баги Phase 1 исправлены 2026-05-05.
Исправлено сегодня (помимо BUG-1 и BUG-2)
- D.2 Price list assignment на ТТ —
UpdateStoreRequestне имел поляpriceListId, PATCH stores игнорировал. Добавлено поле + mapping → проверено: Шаурма 290₽ → 145₽ при назначении Промо-50. - Customer summary 500 —
OrderRepository.aggregateByCustomer{Since}объявлял возвратObject[]напрямую, Hibernate иногда оборачивал какObject[]{innerArray}, отсюдаClassCastExceptionвOrderService:959. Исправлено:List<Object[]>+ safe-unwrap helperfirstRow(). Customer-service membership recompute теперь работает: Дмитрий (потратил 6110₽) послеorder.completedавтоматически добавляется в группу «Постоянные клиенты» (≥5000₽). - POS-bff activeStoreId для owner of franchise / partner —
requireCashiermiddleware всегда бралstoreIds[0]изscope.store_ids. Для scopeall_franchise(admin@erp.local) иlegal_entity_ids(партнёры) поле пустое, поэтому activeStoreId=null → URL/by-store/null→ 400 INVALID_PARAMETER на всех табах кроме каталога. Фикс: для не-store_idsscope доверяемX-Active-Storeheader без проверки (бэкенд валидируетfranchise_idownership). Проверено —/pos/tablesвозвращает 8 столов Арбата под admin-токеном. - BUG-3 closeWithPayment не публиковал order.completed —
OrderService.closeWithPaymentставил status=closed + completedAt, но публиковал толькоorder.paid. В результате auto-write-off, customer recompute и POS UI listeners (что слушаютorder.completed/order.closed/order.status.changed) не срабатывали для заказов закрытых через/pos/orders/{id}/close-with-payment— это dominant close path на desktop POS (быстрый кассовый flow). Фикс — добавил все 3 publish’а как в legacyclose()(line 538-540). Проверено: после closeWithPayment Курица 29.850 → 29.550 → 29.400 кг при 2-х заказах (списание 0.150 кг × n шаурм). - BUG-4 markReadyInternal не выставлял order.ready_at + не двигал items.kitchen_status —
/pos/kitchen-queue/{id}/mark-readyменял толькоorder.status="ready".order.ready_atоставался null,order_items.kitchen_status="pending". Это ломало kitchen-queue UI (фильтр по kitchen_status показывал заказ как «в работе») и репорты, которые джойнят ready_at. Фикс: установкаorder.ready_at=now, перебор всехorder_itemsсkitchen_station_id != null→kitchen_status=READY+kitchen_ready_at=now. Проверено: после mark-ready оба item стали ready, ready_at=01:14:41.
Не дотестировано (отдельные задачи)
- J Aggregator → Order — нет mock-webhook для имитации Yandex.Eda
- L PayKeeper paid flow с реальным informer webhook — не переключено в ЛК koala-test (общий с Koala_TG_app)
- A.4 quirk pos-bff
activeStoreId = scope.store_ids[0]для manager с 3 ТТ — фронт не передаётX-Active-Storeheader. Не баг, но плохо UX (остаётся для scope=store_ids— теперь header работает корректно для owner of franchise / partner)
Ссылки
- Workflow
- PayKeeper docs
- VPS:
sshpass -p '...' ssh root@185.152.93.77