erp-kds — BR 5.1

Новый репозиторий

Создаётся в Шаге 6. Имя: nearbyErp/erp-kds. Структура — копия erp-pos-desktop (monorepo: apps/, packages/).

Контракты

Стек

  • Фреймворк: Tauri 2 (Rust + React + TypeScript)
  • Targets: Android (production) + Windows (для разработки)
  • Frontend: React 18 + TypeScript, без UI-фреймворка (vanilla CSS/CSS Modules — как в erp-pos-desktop)
  • State: React useState + custom hooks
  • Хранилище: SQLite через tauri-plugin-sql
  • Транспорт: native fetch + WebSocket через IKdsTransport interface
  • Updater: @tauri-apps/plugin-updater
  • Менеджер пакетов: pnpm + workspaces

Структура репо

erp-kds/
├── apps/
│   └── kds/
│       ├── src/                  ← React UI
│       │   ├── pages/
│       │   │   ├── RegistrationPage.tsx
│       │   │   ├── PinLoginPage.tsx
│       │   │   ├── StationSelectPage.tsx
│       │   │   ├── OrderListPage.tsx
│       │   │   ├── OrderDetailPage.tsx
│       │   │   └── SettingsPage.tsx
│       │   ├── components/
│       │   ├── hooks/
│       │   │   ├── useTransport.ts
│       │   │   ├── useSession.ts
│       │   │   └── useOrders.ts
│       │   ├── lib/
│       │   │   ├── colors.ts
│       │   │   ├── audio.ts
│       │   │   └── deviceId.ts
│       │   ├── App.tsx
│       │   └── main.tsx
│       ├── src-tauri/            ← Rust + SQLite
│       │   ├── src/
│       │   │   ├── main.rs
│       │   │   └── lib.rs
│       │   ├── Cargo.toml
│       │   └── tauri.conf.json   ← targets: android + windows
│       ├── package.json
│       └── vite.config.ts
├── packages/
│   ├── api-client/               ← KdsTransport + impls
│   │   ├── src/
│   │   │   ├── types.ts
│   │   │   ├── KdsTransport.ts (interface)
│   │   │   ├── CloudTransport.ts
│   │   │   ├── MockTransport.ts
│   │   │   └── index.ts
│   │   └── package.json
│   ├── domain/                   ← бизнес-типы
│   │   ├── src/
│   │   │   ├── Order.ts
│   │   │   ├── KitchenStation.ts
│   │   │   ├── KdsSettings.ts
│   │   │   └── index.ts
│   │   └── package.json
│   └── ui/                       ← переиспользуемые компоненты
│       ├── src/
│       │   ├── OrderCard.tsx
│       │   ├── StatusChip.tsx
│       │   ├── SoundBanner.tsx
│       │   └── index.ts
│       └── package.json
├── pnpm-workspace.yaml
├── package.json
├── tsconfig.base.json
└── README.md

Что делаем

Bootstrap (этап C — 0.5 нед)

  • Создать репо nearbyErp/erp-kds (пользователь делает руками, я скаффолжу)
  • pnpm create tauri-app apps/kds — Tauri 2 + React + TypeScript template
  • cd apps/kds/src-tauri && cargo tauri android init — добавить Android target
  • Настроить tauri.conf.json:
    • productName: "ERP KDS"
    • identifier: "ru.nirbi.erp.kds"
    • bundle.android.minSdkVersion: 29 (Android 10+)
  • pnpm-workspace.yaml — настройка monorepo
  • Создать packages/api-client, packages/domain, packages/ui (skeleton)
  • Скопировать bff-client.ts паттерн из erp-pos-desktop для основы транспорта
  • Базовый App.tsx с роутингом (react-router) и одной заглушкой страницы

KdsTransport (etap E — параллельно с D)

  • packages/api-client/src/KdsTransport.ts — интерфейс из BR 5.1 §3.3:

    interface KdsTransport {
      login(pin, deviceId): Promise<{ jwt, employee, availableStations }>;
      listKitchenStations(): Promise<KitchenStation[]>;
      listOrders(stationIds): Promise<Order[]>;
      subscribeOrderStream(stationIds, onEvent): Unsubscribe;
      setItemStatus(orderId, itemId, status): Promise<void>;
      setKdsStatusForStation(orderId, stationId, status): Promise<void>;
      getRecipe(productId): Promise<Recipe | null>;
      getKdsSettings(): Promise<KdsFranchiseSettings>;
      checkForUpdate(): Promise<UpdateInfo | null>;
      registerDevice(adminCreds, storeId, name): Promise<void>;
    }
  • CloudTransport.ts — реализация через pos-bff REST + WebSocket

    • HTTP-клиент с keepAlive: false (как admin-bff fix)
    • WebSocket с auto-reconnect (exponential backoff 5s → 30s)
    • JWT в Authorization: Bearer header, X-Device-Id в каждом запросе
  • MockTransport.ts — in-memory data + симулятор новых заказов

    • Время-симулятор: setInterval создаёт случайные тестовые заказы каждые 30 сек
    • Используется в dev-режиме (Windows cargo tauri dev)
    • Активируется через env VITE_USE_MOCK_TRANSPORT=true

Экраны (этап D — 2 нед)

  • RegistrationPage — admin-login + выбор ТТ + имя устройства, генерация device_id (SQLite)
  • PinLoginPage — 4 цифры + цифровая клавиатура + anti-bruteforce
  • StationSelectPage — multi-select станций после PIN
  • OrderListPage — главный экран с карточками/списком, цвет, звуки, WS
  • OrderDetailPage — карточка заказа с per-station блоками + кнопки Готово + модалка техкарты
  • SettingsPage — звук/layout/transport/updater/logout/смена ТТ

Hooks

  • useTransport() — инициализация transport (CloudTransport или MockTransport)
  • useSession() — JWT, user, selected_stations из SQLite + auto-logout таймер
  • useOrders(stationIds) — initial REST + WebSocket subscribe, optimistic updates на статусы

Tauri SQLite

  • src-tauri/migrations/01_init.sql:

    • config — key-value store (device_id, transport_mode, локальные оверрайды настроек)
    • session — JWT, expires_at, user_id, last_activity_at, selected_station_ids (JSON)
  • src/lib/deviceId.tsensureDeviceId(): при первом запуске генерирует UUID, сохраняет в SQLite

Audio

  • src/lib/audio.tsAudioManager класс:
    • Loop sounds через HTML Audio API
    • Управление volume
    • Метод playRepeating(soundFile, intervalSec), stop()
  • apps/kds/src-tauri/icons/sounds/ — встроенные mp3-файлы (bell.mp3, chime.mp3, buzzer.mp3, marimba.mp3, digital.mp3, alarm.mp3, siren.mp3, bell-loud.mp3) — упакованы в APK

In-app Updater

  • Включить tauri-plugin-updater в Cargo.toml + tauri.conf.json
  • Manifest endpoint: https://erp-test.nirbi.ru/api/v1/kds/updates/latest (через pos-bff)
  • В SettingsPage — кнопка «Проверить обновления»
  • Background timer (24h) — auto-check + toast уведомление при новой версии

CI/CD (этап F3)

  • .github/workflows/build-android.yml:

    • Trigger: push на main, manual
    • Steps:
      • Checkout
      • Setup Node 22 + pnpm + Rust + Android SDK
      • pnpm install
      • cargo tauri android build --apk --target aarch64
      • Подписать APK через secret keystore (GitHub Secrets: ANDROID_KEYSTORE, KEY_ALIAS, KEY_PASS)
      • Загрузить APK в наш MinIO bucket (или GitHub Releases)
      • Обновить manifest latest.json (новая версия + URL + signature)
  • .github/workflows/build-windows.yml (опц.):

    • Build для разработчика — Windows .exe для тестов

Тесты

  • Unit:
    • MockTransport тесты симулятора
    • Hook useOrders — обработка WS-событий
  • Manual smoke:
    • Установить APK на тестовый планшет, прогнать сценарии из BR 5.1 §10 «Verification»

Pilot чек-лист (этап F4)

  • Установить APK на тестовый планшет в demo-coffee
  • Зарегистрировать устройство (demo@nirbi.ru / admin123 → ТТ demo)
  • Создать сотрудника-повара с PIN и kds.access
  • Привязать товары в catalog к станциям
  • Пробить заказ на POS Desktop → убедиться что появляется на KDS за ≤2 сек
  • Прогнать все сценарии из спеки §3
  • Тестировать неделю реального использования

Зависимости

  • ⛔ pos-bff endpoints должны быть готовы до KDS экранов (иначе только MockTransport)
  • ⛔ Бэкенд миграции применены на VPS
  • ⛔ Android-планшет для тестирования (модель уточняется)

Ссылки