Кухонный экран
Источники требований
- BR 5.1 — KDS Android — основная BR
- KDS Architecture Research — индустриальный анализ и обоснование архитектуры
- BR 2.5 — справочник кухонных станций (Phase 1 без KDS)
Референс
YumaKitchen: обработка заказов, настройки, установка
KDS — отдельное Android-приложение (Tauri 2 + React + SQLite), которое ставится на планшет на кухне или баре. Заменяет бумажные кухонные чеки: повар видит «свои» заказы (по выбранным станциям), отмечает готовность позиций, нажимает «Готово» по станции — заказ уезжает с экрана и кассир получает сигнал «можно подавать».
В P0 транспорт — облако: устройство стучится в pos-bff через интернет. LAN-режим (через POS Desktop как hub) — отложен в BR 5.2; полный offline — в BR 5.3.
§1. Сущности
KDS Device
Устройство-планшет, регистрируется при первом запуске. Хранится в kds_devices (User Service).
| Поле | Обязательность | Описание |
|---|---|---|
id | Авто | UUID. Генерируется на устройстве при первом запуске, сохраняется в SQLite. Передаётся в каждом запросе как X-Device-Id. |
franchise_id | Обязательно | Из JWT первого логина |
store_id | Обязательно | ТТ, к которой привязано устройство. Выбирается при регистрации — далее фиксирована до явной смены |
name | Опционально | Понятное имя — «Планшет горячего цеха», «Бар-1» (задаётся в админке) |
app_version | Обязательно | Версия установленного APK (передаётся при логине, обновляется при смене) |
last_user_id | Опционально | Последний логинившийся сотрудник (для аудита) |
current_user_id | Опционально | Активная сессия — null если нет |
last_seen_at | Авто | Heartbeat при каждом запросе |
revoked_at | Опционально | Soft-удаление админом (force-logout) |
created_at | Авто |
KDS Session
Активная сессия повара после PIN-логина. Хранится в Auth Service / pos-bff side (сессия + JWT).
device_id— на каком устройствеuser_id— кто залогиненselected_station_ids— массив UUID станций, выбранных при логинеstarted_at,last_activity_at,closed_atexpires_at— auto-логаут через 30 мин неактивности- JWT-токен живёт пока сессия активна
§2. Бизнес-правила
2.1. Регистрация и привязка устройства
- Первый запуск: приложение генерирует UUID устройства, сохраняет в SQLite. Показывает экран «Регистрация»: ввод email + пароля владельца/менеджера → выбор ТТ из списка ТТ его франшизы → сохранение
device_id + franchise_id + store_idв БД черезPOST /api/v1/pos/kds/devices/register. - Привязка к ТТ зафиксирована: смена ТТ — отдельное действие в Settings с подтверждением паролем и ре-регистрацией устройства.
- PIN-логин повара: после регистрации экран PIN. PIN ищет сотрудника в этой ТТ (PIN уникален per-ТТ согласно Сотрудники).
2.2. Multi-station при логине
После PIN — экран multi-select станций франшизы. Повар может выбрать одну или несколько. Например, маленькое кафе кладёт один планшет на «Кухня + Бар»; большая кухня держит планшеты только на «Горячий цех» каждый.
2.3. Видимость заказа
Заказ появляется на KDS если выполняются все условия:
order.store_id = device.store_id(та же ТТ)order.status = 'accepted'(кассир нажал «Начать готовку» на POS — см. Заказы)- В заказе есть позиция с
product.requires_kitchen=trueИproduct.kitchen_station_id IN session.selected_station_ids
Заказ уходит с экрана когда:
- Все позиции выбранных станций перешли в
kitchen_status=ready - Или заказ перешёл в
ready/closed/cancelled
Невыбранные станции этого же заказа отображаются в карточке серым (контекст: «там тоже что-то готовят»), без управления.
2.4. Статусы позиций
Каждая позиция (order_items) имеет kitchen_status:
pending (создана) → preparing (повар тапнул "В работе") → ready (повар тапнул "Готово")
Откат ready → preparing запрещён на KDS. Если ошибка — отмена через POS кассиром (полная отмена заказа или возврат после).
2.5. Кнопка «Готово» по станции
В карточке заказа — отдельный блок per-станция и отдельная кнопка «Готово». Активна когда все позиции этой станции в статусе ready. Тап → массовое закрытие, заказ уезжает с экрана если это была последняя выбранная станция.
2.6. Цвет карточки по времени
Каждый заказ имеет expected_ready_at. Цвет карточки на KDS:
- Зелёный —
now < expected_ready_at - yellow_threshold_minutes - Жёлтый —
now ≥ expected_ready_at - yellow_threshold_minutes - Красный —
now ≥ expected_ready_at + red_threshold_minutes(просрочка)
Пороги — per-станция в Кухонных станциях (yellow_threshold_minutes, red_threshold_minutes).
Если в заказе позиции нескольких выбранных станций — берётся минимум (самая «жёсткая» окраска побеждает).
На устройстве в Settings можно локально переопределить пороги (для тестирования).
2.7. Звуковое + визуальное оповещение
- На каждый новый заказ — звук
- Звук повторяется каждые
new_order_repeat_seconds(per-франшиза, default 30) пока повар не открыл карточку - При просрочке — другой, более тревожный звук
- Звуки и интервал — из Настройки KDS (per-франшиза)
- На устройстве можно локально переопределить громкость и отключить звук вообще
2.8. Отмена заказа в процессе готовки
Если кассир отменил заказ когда тот был на KDS:
- Звуковой сигнал «Заказ отменён»
- На карточке заказа появляется красное оверлей-уведомление «Отменён» на 2–3 секунды
- Карточка автоматически уезжает с экрана
- Логи остаются в Order Service для аудита (отменённые заказы не теряются)
2.9. Жизненный цикл сессии
stateDiagram-v2 [*] --> unregistered : Первый запуск unregistered --> registered : Email админа + выбор ТТ registered --> session_active : PIN + multi-select станций session_active --> registered : Logout / auto-logout 30 мин session_active --> session_active : Sleep / wake (короткий блок экрана) registered --> registered : Reboot устройства (требует PIN заново) registered --> revoked : Админ удалил устройство в админке revoked --> unregistered : Повторная регистрация (email + ТТ)
Поведение:
- После reboot устройства — обязательный повторный PIN (security)
- После sleep/wake (короткий блок) — auto-resume если JWT не истёк
- После 30 мин неактивности — auto-logout, требуется новый PIN
- После «Logout» — сессия закрыта, экран PIN
2.10. Permissions
kds.access— обязательное право для PIN-логина в KDS. Без него —403 KDS_ACCESS_DENIED.kds.settings.edit— право менять локальные настройки устройства (звуки/пороги/layout) и регистрировать новые устройства / удалять.
См. Роли.
2.11. Multi-tenancy
В JWT есть franchise_id. pos-bff фильтрует все запросы (заказы, станции, настройки) по этому полю — пересечение между франшизами невозможно.
2.12. Settings sync
В P0 — pull: устройство забирает настройки франшизы (звуки, пороги, статус «удалено» соседних станций) при:
- Каждом логине
- Перезапуске приложения
- Явном тапе «Применить настройки» в Settings
Live push через WebSocket — отложен в P1.
2.13. Транспорт (P0)
- HTTPS REST + WSS WebSocket к
https://erp-test.nirbi.ru/api/v1/pos/... - Live-обновления через WS-канал
wss://...kds/stream?station_ids=... - При потере связи — красный баннер «Нет связи». Заказы продолжают отображаться (in-memory кэш). Действия пользователя складываются в очередь и синхронизируются при reconnect.
- В Settings — переключатель транспорта
Облако/Локальная сеть/Авто. В P0 рабочий только «Облако», остальные disabled с подсказкой «Будет в BR 5.2».
2.14. In-app updater
- В Settings — кнопка «Проверить обновления»
- Auto-check каждые 24 часа в фоне (опционально, настраивается)
- Tauri-updater plugin: проверяет manifest на
https://updates.nirbi.ru/kds/latest.json→ если новая версия → показывает dialog → скачивает APK → ставит (Android запросит подтверждение пользователя один раз) - На pilot-этапе очень упрощает выкатку патчей
§3. Сценарии использования
3.1. Утренний запуск кухни
- Повар включает планшет на креплении
- Открывает KDS (или приложение уже автозапущено и держит экран)
- Вводит PIN
- Выбирает галочку «Горячий цех» из списка станций франшизы
- Видит экран «Ожидание заказов» с названием станции
3.2. Маленькое кафе на одном планшете
- Бариста-повар включает планшет
- PIN
- Выбирает галочки «Кухня» и «Бар»
- Заказы обоих станций отображаются вместе; в карточке группировка «Кухня: …», «Бар: …»; у каждой группы своя кнопка «Готово»
3.3. Новый заказ
- Кассир пробивает «Карбонара + Цезарь» в POS
- Кассир тапает «Начать готовку» — заказ →
accepted - Order Service публикует
order.status_changed(Kafka) pos-bff(Kafka consumer) видит событие, фильтрует подписчиков поstation_ids, пушит через WS- На KDS «Горячий цех» ≤2 сек появляется зелёная карточка с «Карбонара» (Цезарь — на «Холодном цехе», в карточке отображается серым)
- Звучит звуковой сигнал, повторяется каждые 30 сек
3.4. Готовка
- Повар открывает карточку (звук перестаёт повторяться)
- Тапает «В работе» на «Карбонара» →
kitchen_status=preparing→ синий цвет - Готовит, тапает «Готово» →
kitchen_status=ready→ зелёный с галочкой - Кнопка «Готово» по станции «Горячий цех» становится активной (это была последняя позиция)
- Тап → все позиции «Горячего цеха» закрываются; так как других выбранных станций в этом заказе у повара нет — заказ уезжает с экрана
- POS у кассира видит «Заказ готов к подаче»
3.5. Просрочка
- Заказ висит дольше нормы (
now > expected_ready_at - 5 мин) - За 5 мин до срока — карточка становится жёлтой
- После срока — красной + тревожный звук
- Повар видит, ускоряется или связывается с менеджером
3.6. Просмотр техкарты
- Стажёр не помнит рецепт «Карбонары»
- В карточке тап «?» рядом с блюдом
- Открывается модалка с техкартой (название, ингредиенты, порядок, фото если есть)
- Возврат к карточке
3.7. Отмена заказа
- Гость передумал, попросил отменить
- Кассир в POS отменяет (
cancelled) - На KDS звук «Заказ отменён», красное оверлей-уведомление 2–3 сек
- Карточка уезжает с экрана
3.8. Потеря соединения
- Wi-Fi отключился
- KDS показывает красный баннер «Нет связи»
- Текущие заказы остаются на экране (in-memory кэш)
- Повар тапает «Готово» — действие в очередь
- Wi-Fi вернулся → KDS отправляет очередь → синхронизация → баннер «Связь восстановлена»
3.9. Конец смены
- Повар тапает «Меню» → «Logout»
- Сессия закрыта, экран PIN
§4. Жизненный цикл позиции на KDS
order_items.kitchen_status:
pending ───[повар тапнул "В работе"]──→ preparing ───[повар тапнул "Готово"]──→ ready
│
▼
(откат запрещён)
При создании позиции (одновременно с accepted заказа) — kitchen_status=pending.
KDS отображает позиции с requires_kitchen=true и фильтром по выбранным станциям.
§5. Экраны (общий обзор)
Детали каждого экрана — в Frontend Specs KDS (создаются в Шаге 3 workflow).
| Экран | Назначение |
|---|---|
| Регистрация устройства | Email + пароль владельца → выбор ТТ → сохранение device_id |
| PIN-логин | Ввод 4-значного PIN + multi-select выбранных станций |
| Список заказов | Карточки или список (выбирается в Settings); фильтр по выбранным станциям; цвет по времени; звук на новый заказ |
| Карточка заказа | Позиции группированы по станциям; кнопка «Готово» per-станция; модификаторы; комментарий гостя; «?» → техкарта |
| Модалка техкарты | Название, ингредиенты, последовательность; опц. фото |
| Settings | Звук, громкость, локальные пороги, layout, transport, in-app updater, смена ТТ, logout |
§6. Ролевая матрица
| Действие | Владелец франшизы | Владелец партнёра | Менеджер | Повар/Бариста | Кассир |
|---|---|---|---|---|---|
| Зарегистрировать устройство (привязать к ТТ) | ✅ | ✅ (свои ТТ) | ✅ | ❌ | ❌ |
| PIN-логин в KDS | ✅ | ✅ | ✅ | ✅ | ❌ |
| Видеть заказы выбранных станций | ✅ | ✅ | ✅ | ✅ | ❌ |
| Менять статус позиции | ✅ | ✅ | ✅ | ✅ | ❌ |
| Закрыть «Готово» по станции | ✅ | ✅ | ✅ | ✅ | ❌ |
| Менять локальные настройки устройства | ✅ | ✅ | ✅ | ❌ | ❌ |
| Сменить ТТ устройства | ✅ | ✅ (свои) | ❌ | ❌ | ❌ |
Permissions:
kds.access— базовая (выдаётся поварам, барменам, менеджерам)kds.settings.edit— управление локальными настройками + регистрация нового устройства
См. Роли.
§7. Hardware
7.1. Минимальные требования
- Android 10+ (API 29+)
- 10–13” экран, 1280×800+
- 3+ ГБ RAM, 32+ ГБ хранилища
- Wi-Fi 5GHz; опц. Ethernet через USB-C для стабильности
7.2. Рекомендованный список
| Сегмент | Модель | Примерная цена |
|---|---|---|
| Бюджет | Lenovo Tab M10 (3rd Gen), Xiaomi Redmi Pad SE | 15–20K ₽ |
| Mid | Samsung Galaxy Tab A9+, Huawei MatePad 11 | 25–35K ₽ |
| Industrial (жирные кухни) | ELO Touch Tablet (IP54) | 60K+ ₽ |
7.3. Что докупает владелец
- Крепление (стенное / подвесное / штатив) — 1.5–5K ₽
- Зарядное 2А+ с кабелем — 1–2K ₽
- Опц. USB-Ethernet — 1K ₽
- Опц. UPS на роутер
§8. Что НЕ входит в P0
- ❌ LAN-hub режим (через POS Desktop) — BR 5.2
- ❌ Полный offline-first (SQLite-репликация state, event-log sync) — BR 5.3
- ❌ Печать кухонных чеков на ESC/POS принтерах — BR 5.4
- ❌ Возврат / отмена заказа с кухни — требует финансовой логики, риск в MVP
- ❌ Курсы подачи (горячее/холодное/десерт) — BR 5.6
- ❌ Bump bar (USB HID) — BR 5.5
- ❌ Загрузка кастомных звуковых файлов (только выбор из встроенных) — BR 5.7
- ❌ Live push настроек франшизы через WS — P1 (в P0 — pull)
- ❌ iOS-сборка — только Android в P0
- ❌ Английский UI — только русский — BR 5.9
§9. In-app updater (детали)
Для пилота критично уметь выкатывать патчи без визита в каждую ТТ.
- Manifest:
https://updates.nirbi.ru/kds/latest.json→{ version, apk_url, signature, release_notes, min_required_version } - Tauri-updater plugin: при тапе «Проверить обновления» (или auto-check 24ч) скачивает manifest, сравнивает с текущей
app_version, если новая — показывает dialog с release notes - Установка: APK скачивается в Tauri scope, запускается Android intent для установки. Пользователь подтверждает один раз («Установить из этого источника»).
- Откат: автоматического роллбэка нет в P0 — если новая версия плохая, заливаем patch-версию вручную.
В P1 — auto-rollback и canary-релизы (5% устройств → проверка → 100%).
§10. Связи с другими модулями
- Кухонные станции — справочник + цветовые пороги per-станция
- Заказы —
kitchen_statusper-item,expected_ready_at, статусная модель - Каталог —
requires_kitchen,kitchen_station_idна товаре, техкарты - Сотрудники — PIN-логин (PIN per-ТТ)
- Роли —
kds.access,kds.settings.edit - Настройки KDS — per-франшиза звуки и общие правила
- Авторизация — JWT, refresh, password-логин владельца для регистрации устройства