No description
Find a file
byrsapty 0cea565fd5 Move the shared Drive folder-id field above both auth methods
It only appeared inside the service-account block, so it wasn't visible
when scrolled to the OAuth section — moved to the top of the Google Drive
group since the same field applies to whichever auth method is filled in.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 23:16:49 +03:00
bober_bbq Move the shared Drive folder-id field above both auth methods 2026-09-05 23:16:49 +03:00
bot Add per-100g product pricing and editable order line prices 2026-09-03 20:33:04 +03:00
docs Add backup_remote.py and wire up the rest of the rclone rework 2026-09-05 22:57:59 +03:00
scripts Add opt-in PostgreSQL support alongside default SQLite 2026-08-27 13:31:12 +03:00
tests Add OAuth auth option for the Google Drive backup remote 2026-09-05 23:10:59 +03:00
webapp Add per-100g product pricing and editable order line prices 2026-09-03 20:33:04 +03:00
.env.example Make brand identity reusable for redeploying to other clients 2026-08-25 17:54:29 +03:00
.gitignore Add repo-committed pytest test suite 2026-08-27 13:32:09 +03:00
deploy.sh Make brand identity reusable for redeploying to other clients 2026-08-25 17:54:29 +03:00
provision_client.sh Add backup_remote.py and wire up the rest of the rclone rework 2026-09-05 22:57:59 +03:00
pytest.ini Add repo-committed pytest test suite 2026-08-27 13:32:09 +03:00
README.md Add backup_remote.py and wire up the rest of the rclone rework 2026-09-05 22:57:59 +03:00
requirements-dev.txt Add repo-committed pytest test suite 2026-08-27 13:32:09 +03:00
requirements.txt Add backup_remote.py and wire up the rest of the rclone rework 2026-09-05 22:57:59 +03:00
run_bot.py Initial commit: Bober BBQ Telegram bot + backend + admin + Mini App 2026-08-08 15:50:50 +03:00
run_web.py Add backup_remote.py and wire up the rest of the rclone rework 2026-09-05 22:57:59 +03:00

Bober BBQ — Telegram Bot + Mini App

Повноцінна система для кафе/доставки Bober BBQ: Telegram-бот, Mini App (меню, кошик, оформлення доставки/самовивозу/замовлення в закладі), адмін-панель для персоналу (включно з ручним створенням замовлень), оплата карткою через monobank з автоматичною страховкою на випадок збоїв, опційна фіскалізація чеків через Checkbox (ПРРО), промокоди, оцінки замовлень, налаштовувані кольори інтерфейсу і повний набір адмінських інструментів для щоденної роботи.

Живий продакшн:

Що вміє система

Клієнт (Telegram-бот + Mini App)

  • Перегляд меню за категоріями, кошик, оформлення доставки, самовивозу або замовлення в закладі («У закладі», з номером столика) — все в Mini App, без багатокрокового діалогу в чаті.
  • Замовлення без Telegram: та сама вебапка за адресою webapp.boberbbq.com працює і в звичайному браузері — гість без Telegram-акаунту отримує кошик/історію замовлень через анонімну сесійну cookie (без SMS-верифікації й без реєстрації), а посилання для відстеження статусу замовлення працює навіть якщо cookie загубилась.
  • Оплата карткою (monobank) або готівкою; знижка за самовивіз і мінімальна сума замовлення на доставку — обидва налаштовуються в адмінці.
  • Промокоди — знижка у відсотках, з опційним обмеженням «лише перше замовлення клієнта», мінімальною сумою, лімітом використань і терміном дії. Поле застосування прямо на екрані оформлення.
  • «Мої замовлення»: історія, самостійне скасування (поки замовлення ще не в роботі), повторна спроба оплати карткою в будь-який момент, і «Повторити замовлення» в один клік — товари з минулого замовлення повертаються в кошик (товари, яких більше немає в продажу, коректно пропускаються з попередженням).
  • Після статусу «Виконано» клієнт отримує в Telegram коротке «Як вам замовлення?» з кнопками 15 — оцінка одразу зберігається і видна в адмінці. Функцію можна вимкнути одним перемикачем у Налаштуваннях.
  • PWA: Mini App можна додати на головний екран телефону поза Telegram, іконка автоматично підхоплює лого закладу.
  • Skeleton-заглушки замість «Завантаження…», ілюстровані порожні стани (порожній кошик/меню/список замовлень) замість голого тексту.
  • Форс-мажор: коли в адмінці увімкнено «Тимчасово закрито», Mini App замість меню й кошика показує клієнту анімовану заглушку з поясненням і контактами закладу — на відміну від звичайного графіку роботи (де меню все ще можна переглянути поза годинами), це блокує весь застосунок.
  • Оголошення: адмін може ввімкнути одноразовий спливаючий попап з довільним текстом (вихідний день, зміна графіка, акція тощо) — не блокує застосунок, клієнт закриває його сам, а редагування тексту показує попап повторно навіть тим, хто вже його закривав.

Адмін-панель

  • Замовлення: список з фільтрами й пагінацією (три типи — доставка/самовивіз/у закладі), картка замовлення з візуальним степером статусу (Нове → Підтверджено → Готується → Готове → [Кур'єр] → Виконано), позначення оплати готівкою, скасування з причиною.
  • Нове замовлення — адмін і менеджер можуть створити замовлення вручну (телефонний дзвінок, прийом на місці) прямо з адмінки, з тим самим набором товарів і трьома типами, що й у Mini App; такі замовлення враховуються в статистиці нарівні зі звичайними (атрибутуються спеціальному службовому «клієнту», а не реальному Telegram-акаунту).
  • Товари й категорії: CRUD, сортування, фото, алергени (EU-14).
  • Постачальники: облік поставок, оплат і боргу по кожному; додавання вручну або імпорт з Excel-файлів довільної структури — адмін сам зіставляє, яка колонка за що відповідає (з автопідбором за схожістю назв), рядки без товару (шаблонні/підсумкові) пропускаються самі. Поставку можна опційно одразу зарахувати на склад, якщо назва товару збігається з інгредієнтом. За замовчуванням доступно лише адміністратору — можна відкрити й менеджерам окремим перемикачем.
  • Промокоди: створення, вимкнення/увімкнення, видалення, лічильник використань.
  • Клієнти: список і картка клієнта з історією замовлень.
  • Статистика: звіти за довільний період, графік виручки по днях.
  • Відгуки: середня оцінка, розподіл 1★5★ у вигляді діаграми, стрічка останніх відгуків просто на дашборді, окрема сторінка з фільтром по оцінці й пагінацією для повноцінного розбору фідбеку.
  • Склад (опційно, вмикається одним перемикачем): інгредієнти з залишками, рецептура страв (скільки якого інгредієнта йде на 1 порцію), автоматичне списання при кожному замовленні й повернення при скасуванні, ручні коригування/списання з журналом рухів, і автоматичні заявки на поповнення — з'являються, коли інгредієнт опускається нижче порогу, і самі закриваються, коли поставку зараховано.
  • Фіскалізація (опційно): інтеграція з Checkbox (ПРРО) — вимкнена за замовчуванням, нічого не змінює в роботі, поки не увімкнена в Налаштуваннях. Коли увімкнена — фіскальний чек формується автоматично в момент фактичної оплати (позначення «оплачено готівкою», підтвердження оплати карткою через monobank, оплачене замовлення створене вручну), клієнту чек надсилається в Telegram PDF-документом. Помилки фіскалізації ніколи не блокують замовлення — видно статус і причину на картці замовлення, є кнопка ручного повтору.
  • Вигляд: колір інтерфейсу адмінки і окремо колір Mini App — один пікер кольору на кожен, решта відтінків (для кнопок, бейджів, градієнтів) підбирається автоматично.
  • Розсилка повідомлення всім клієнтам бота.
  • Резервні копії БД: створення, відновлення, видалення з адмінки, плюс опційні автоматичні бекапи через rclone (Google Drive, S3-сумісне сховище або будь-який інший rclone-backend, налаштовується прямо у формі) з ротацією — старі копії видаляються, коли їх стає більше за налаштовану кількість.
  • Адміністратори: ролі admin/manager (RBAC) — менеджер не бачить Налаштування, Адміністраторів, Резервні копії, Статус системи й Журнал дій.
  • Журнал дій (audit log) і Статус системи.
  • CSRF-захист на всіх формах, доступність (контраст кольорів за WCAG AA, aria-label на іконках-кнопках, клавіатурна навігація), адаптивний дизайн під мобільні (бічне меню згортається, широкі таблиці стають списком карток).
  • /health — ендпоінт для зовнішнього uptime-моніторингу.

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

bober-bbq-bot/
├── bober_bbq/                # Flask backend: REST API + адмін-панель + БД
│   ├── api/
│   │   ├── menu.py             # /api/categories, /api/products
│   │   ├── cart.py               # /api/cart — спільний кошик бота й Mini App
│   │   ├── checkout.py            # /api/checkout/delivery, /pickup, /dine-in, промокод-превʼю
│   │   ├── orders.py               # /api/orders — історія, скасування, повторна оплата, повтор замовлення
│   │   ├── payments.py              # вебхук monobank
│   │   ├── settings.py               # /api/settings — публічні налаштування для Mini App
│   │   └── auth.py                    # перевірка підпису Telegram WebApp initData
│   ├── admin/                 # Адмін-панель (Flask-Login + Jinja2)
│   │   ├── routes.py            # дашборд, замовлення, товари, категорії, промокоди, відгуки, налаштування
│   │   ├── inventory.py          # склад: інгредієнти, рецептура, заявки на поповнення
│   │   ├── customers.py           # клієнти й статистика по них
│   │   ├── statistics.py           # звіти за період + графік виручки
│   │   ├── system.py                # статус системи, бекапи (локальні + rclone), очищення БД
│   │   ├── telegram_chats.py         # перевірка підключення чатів доставки/самовивозу
│   │   ├── broadcast.py               # розсилка повідомлення всім клієнтам
│   │   ├── admins.py                   # керування адміністраторами/менеджерами
│   │   └── authz.py                     # RBAC-декоратор (admin-only розділи)
│   ├── payments/monobank.py    # створення інвойсу, статус, перевірка підпису вебхука, тест токена
│   ├── utils/
│   │   ├── reconciliation.py    # фонові job'и: страховка оплати + health-check токена
│   │   ├── inventory.py          # автосписання/повернення складу, автозаявки на поповнення
│   │   ├── backup_remote.py       # автобекапи БД через rclone (Google Drive/S3/інше) з ротацією
│   │   ├── notify_customer.py      # авто-сповіщення клієнта про статус + запит оцінки
│   │   ├── notify_manager.py        # сповіщення менеджера (нове/скасоване замовлення), staff_chat_id() по типу замовлення
│   │   ├── telegram_notify.py        # низькорівневий sendMessage/sendDocument (HTTP, поза aiogram)
│   │   ├── checkbox_prro.py           # опційна фіскалізація через Checkbox (ПРРО)
│   │   ├── theme.py                    # один колір → повна CSS-палітра (адмінка + Mini App)
│   │   ├── promo.py                     # пошук/валідація промокодів, розрахунок знижки
│   │   ├── formatting.py                 # текст замовлення для чату менеджера (3 типи)
│   │   ├── workhours.py                   # графік роботи, чи приймаються замовлення
│   │   └── pricing.py                      # доставка/знижка самовивозу/мінімальна сума
│   ├── templates/admin/        # HTML-шаблони адмінки (адаптивні під мобільні)
│   ├── static/                  # CSS адмінки, завантажені лого/фото товарів
│   ├── models.py                  # SQLAlchemy-моделі + DEFAULT_SETTINGS
│   ├── migrate.py                   # ALTER TABLE для нових колонок (без Alembic, див. нижче)
│   └── app.py                         # Flask app factory, CSRF, роздача Mini App, /health
├── bot/                      # Telegram-бот (aiogram 3) — тонкий шар
│   ├── handlers/                # /start, меню (кнопка Mini App), контакти, оцінка замовлення (callback)
│   ├── services/                  # order_service, cart_service (спільні з чекаут-API)
│   └── main.py                      # точка входу (long polling)
├── webapp/                   # Telegram Mini App (Vite + React + TypeScript)
│   ├── public/manifest.json     # PWA-маніфест (Add to Home Screen поза Telegram)
│   └── src/
│       ├── pages/                 # Menu, Cart, Checkout (+ промокод), Orders (+ повтор), Contacts
│       ├── components/              # Skeleton, EmptyState та інші перевикористовувані блоки
│       ├── telegram.ts                # обгортка над Telegram WebApp SDK
│       └── icons.tsx                    # inline SVG-іконки (заміна емодзі, що криво рендерились)
├── run_web.py               # Продакшн-запуск backend (waitress) + планувальник (APScheduler)
├── run_bot.py                # Запуск бота
├── deploy.sh                  # Одна команда: git pull → deps → build → restart
└── requirements.txt

Ключові рішення

  • Уся покупка — в Mini App. Перегляд меню, кошик і повне оформлення замовлення (адреса/ім'я/телефон/час/спосіб оплати, промокод) — звичайна форма в Mini App, без багатокрокового діалогу в чаті. Кошик спільний для бота й Mini App (одна таблиця cart_items, прив'язана до telegram_id).
  • Бот — тонкий. /start, меню з кнопкою Mini App, контакти, автосповіщення про статус замовлення й запит оцінки. Бот і backend працюють в одному Flask app-контексті напряму через SQLAlchemy, без зайвого HTTP-стрибка — bot/main.py пушить flask_app.app_context() один раз на старті, тож будь-який хендлер (включно з callback'ами на inline-кнопки оцінки) звертається до db.session так само, як і веб-бекенд.
  • Самообслуговування клієнта. У «Мої замовлення» клієнт може сам скасувати замовлення, поки воно ще не в роботі (статус «Нове» або «Підтверджено»), повторно відкрити оплату карткою в будь-який момент (кожен клік створює свіжий інвойс monobank, тож стара протухла сторінка оплати ніколи не блокує клієнта), і повторити минуле замовлення одним натисканням.
  • Оплата картою (monobank) з подвійною страховкою.
    • Вебхук monobank підтверджує оплату миттєво (підпис перевіряється ECDSA-ключем, який видає сам monobank).
    • На випадок, якщо вебхук не дійшов (мережевий збій, зміна домену тощо) — фоновий job раз на 10 хв напряму звіряє статус неоплачених card-замовлень з API monobank і донараховує оплату сам (bober_bbq/utils/reconciliation.py).
    • Окремий job раз на годину перевіряє, чи досі робочий токен monobank, і одразу пише власнику в Telegram, якщо ні — щоб «тихий» збій оплати не залишився непоміченим.
    • Тестовий режим оплати (окремий токен, перемикається в адмінці) — можна прогнати весь цикл оплати фейковою карткою без реальних грошей, перш ніж вмикати бойовий токен.
  • Фіскалізація ніколи не блокує замовлення. checkbox_prro.py — повністю опційний модуль: коли вимкнено — жодного мережевого виклику; коли увімкнено — будь-яка помилка Checkbox (мережа, неправильні дані, збій API) ловиться, пишеться в Order.fiscal_status/fiscal_error і не перериває обробку оплати. Триггер — момент фактичної оплати (не створення замовлення): orders_mark_paid для готівки, вебхук і реконсиляція monobank для картки, ручне створення вже оплаченого замовлення в адмінці — усі три місця викликають один спільний maybe_fiscalize().
  • Схема БД без Alembic. db.create_all() створює нові таблиці, але ніколи не додає колонки до вже існуючих. Замість повноцінних міграцій — bober_bbq/migrate.py: список ALTER TABLE ... ADD COLUMN, кожен виконується лише якщо колонки ще немає. Викликається на кожному старті (run_web.py і bot/main.py), безпечно й ідемпотентно. Додаючи нове поле в модель — не забути додати рядок сюди.
  • CSRF-захист. Flask-WTF під'єднано глобально; публічний /api/* явно виключений з CSRF-перевірки — кожен вкладений під-blueprint (menu, cart, checkout, orders, settings, payments, me) виключається окремо, бо csrf.exempt() на батьківському blueprint не гарантовано каскадується на дочірні. Усі форми адмінки містять прихований csrf_token.
  • Замовлення без Telegram (гість). require_customer_auth (bober_bbq/api/auth.py) — те саме, що й require_telegram_auth (перевірка підпису X-Telegram-Init-Data), але коли підпису немає — замість 401 віддає доступ анонімному «гостю»: TelegramUser з від'ємним telegram_id (allocate_guest_telegram_id(), bober_bbq/models.py), прив'язаному до сесійної Flask-куки. Той самий принцип, що й WALKIN_TELEGRAM_ID = -1 для ручних замовлень з адмінки, тільки кожен гість отримує свій унікальний id, щоб кошики різних людей не змішувались. Кожне замовлення (і гостьове, і Telegram) отримує Order.tracking_token — випадковий рядок для перегляду статусу за посиланням /webapp/?track=<token> (GET /api/checkout/track/<token>, без авторизації) — на випадок, якщо сесійна кука загубиться. Персонал/адмінка (розсилка, статистика клієнтів, PDF-чеки Checkbox) явно виключають і walk-in, і гостей — вони не «справжні» повторні клієнти.
  • Промокоди зберігають знижку у відсотках і опційно: мінімальну суму замовлення, ліміт використань, термін дії, обмеження «лише перше замовлення». Знижка від промокоду підсумовується зі знижкою за самовивіз (обидві незалежні), а не замінює її. Валідація єдина для превʼю-ендпоінту («Застосувати» в Mini App) і для реального оформлення замовлення — щоб клієнт ніколи не побачив «діє», а потім отримав відмову при оформленні з інших причин.
  • Адмінка адаптивна під мобільні — бічне меню згортається в висувну панель, широкі таблиці на телефоні перетворюються на список карток замість горизонтального скролу.

Швидкий старт (локально)

  1. Залежності (Python 3.11+, Node 20+):
pip install -r requirements.txt
cd webapp && npm install && npm run build && cd ..
  1. Скопіюйте .env.example.env і заповніть BOT_TOKEN, OWNER_IDS, WEBAPP_URL/BACKEND_PUBLIC_URL (публічний HTTPS-домен — Telegram Mini App і вебхук monobank не працюють по HTTP).

  2. Запустіть backend (API + адмінка + Mini App):

python run_web.py

Адмінка: http://localhost:8000/admin. Перший запуск створює таблиці й демо-меню (bober_bbq/seed.py) — заміните на реальне через адмінку. Токен і решту налаштувань оплати monobank теж редагуються в адмінці (Налаштування → Оплата карткою), .env-значення лише запасні на випадок, якщо адмінка ще не налаштована.

  1. Бот (окремий процес):
python run_bot.py

Локальна розробка Mini App (гаряче перезавантаження)

cd webapp
npm run dev

Vite проксує /api/* на http://localhost:8000. Поза Telegram справжнього initData немає — у режимі app.debug=True API приймає ?dev_user_id=<число> як заглушку (вимкнено в проді).

Продакшн-сервер

Проєкт розгорнутий на окремому VPS (Debian 13, публічна IP), домен webapp.boberbbq.com, HTTPS — справжній сертифікат Let's Encrypt через nginx + certbot (автопоновлення налаштоване стандартним certbot.timer).

Інтернет → nginx (443, TLS через Let's Encrypt) → 127.0.0.1:8000 (waitress)

Структура на сервері

/opt/bober-bbq-bot/                     # git-клон репозиторію (власник: claude)
/opt/bober-bbq-bot/.venv/               # Python venv
/opt/bober-bbq-bot/.env                 # BOT_TOKEN / SECRET_KEY / запасні значення (не в git)
/etc/nginx/sites-available/bober-bbq    # reverse proxy 443 → 127.0.0.1:8000
/etc/letsencrypt/live/webapp.boberbbq.com/   # TLS-сертифікат
/etc/systemd/system/bober-bbq-web.service
/etc/systemd/system/bober-bbq-bot.service
/var/log/bober-bbq-web.log
/var/log/bober-bbq-bot.log

Сервіси запускаються від імені користувача claude (не root), керування через sudo.

Керування сервісами

ssh claude@<IP сервера>

# статус
sudo systemctl status bober-bbq-web bober-bbq-bot nginx

# логи наживо
tail -f /var/log/bober-bbq-web.log
tail -f /var/log/bober-bbq-bot.log

# перезапуск після зміни .env або коду
sudo systemctl restart bober-bbq-web bober-bbq-bot

Оновлення коду на сервері

Одна команда:

bash /opt/bober-bbq-bot/deploy.sh

Робить git pull, ставить Python- і npm-залежності, збирає Mini App і перезапускає обидва сервіси (а разом з ними — migrate(), який підхоплює нові колонки БД).

systemd-юніти запускають сервіси від імені claude, тому команди systemctl в них і в deploy.sh виконуються з sudo — при інтерактивному запуску буде запит пароля.

Якщо змінювались лише шаблони/статика (без Python-коду) — рестарт сервісу не обов'язковий: TEMPLATES_AUTO_RELOAD = True підхоплює зміни на льоту. Але якщо змінювались і Python, і шаблони одночасно, варто рестартувати одразу після git pull, а не чекати — інакше в проміжку старий процес може спробувати відрендерити новий шаблон, що посилається на ще не зареєстрований роут, і віддати 500 на один випадковий запит.

Моніторинг

GET /health повертає {"status": "ok"} (200) після реальної перевірки з'єднання з БД, або {"status": "error", ...} (503) — саме цей ендпоінт має пінгувати зовнішній uptime-сервіс (UptimeRobot, Better Uptime тощо), щоб дізнатись про падіння сайту раніше за скаргу клієнта.

Фонові job'и (APScheduler, всередині bober-bbq-web)

Стартують разом з run_web.py, окремого сервісу не потребують:

Job Періодичність Що робить
reconcile_payments кожні 10 хв звіряє неоплачені card-замовлення за останні 6 год напряму з monobank — страховка на випадок пропущеного вебхука
monobank_token_health щогодини пінгує токен monobank; якщо робочий токен раптом перестав діяти — пише власнику (OWNER_IDS) в Telegram
backup_remote щогодини (перевіряє) якщо увімкнено й минув налаштований інтервал — вивантажує свіжий бекап через rclone (Google Drive/S3/інше) і чистить застарілі копії; при збої пише власнику в Telegram

Налаштування в адмінці (без доступу до сервера)

Адмінка → Налаштування охоплює майже все, що раніше вимагало правки .env і рестарту:

  • Заклад: назва, лого (використовується і як іконка Mini App/PWA — оновлюється автоматично при зміні лого), телефон, адреса, графік роботи, Instagram/карта.
  • Доставка й самовивіз: вартість доставки, поріг безкоштовної доставки, мінімальна сума замовлення на доставку, знижка самовивозу.
  • Telegram-чати для сповіщень про нові замовлення (окремо доставка й самовивіз).
  • Сповіщення клієнтів: автоповідомлення про зміну статусу замовлення і — окремим перемикачем — запит оцінки (15) після «Виконано».
  • Оплата карткою (monobank): бойовий токен, тестовий токен + перемикач тестового режиму, кнопка «Перевірити» (звіряє токен з monobank без створення платежу), опис платежу (шаблон з {number}), показ/приховання списку товарів на сторінці оплати monobank.
  • Вигляд: колір адмінки й колір Mini App окремо (по одному пікеру кольору — решта відтінків підбирається автоматично).
  • Фіскалізація (ПРРО Checkbox): вимкнена за замовчуванням; логін, пароль касира, ліцензійний ключ каси, кнопка «Перевірити підключення», перемикач «надсилати чек клієнту в Telegram».
  • Промокоди — окремий розділ («Промокоди» в меню): створення, вимкнення, видалення.
  • Відгуки клієнтів — окремий розділ («Відгуки»): середня оцінка, розподіл по зірках, фільтр і пагінація.
  • Розсилка повідомлення всім клієнтам бота.
  • Резервні копії БД: створення, відновлення, видалення — прямо з адмінки, плюс автоматичні бекапи через rclone з ротацією (Адмінка → Резервні копії → тип сховища: Google Drive / S3-сумісне / інше, з покроковою інструкцією налаштування прямо на сторінці для кожного).
  • Облік сировини: перемикач «Увімкнути облік сировини», нижче в тому ж розділі — при увімкненні в меню з'являється «Склад».

Чек-лист перед реальним запуском

  1. Токен бота — вже бойовий (@BoberBBQ_bot).
  2. Пароль адмінки — вже змінено власником.
  3. Токен monobank — перевірте кнопкою «Перевірити» в Налаштуваннях: на момент останньої перевірки бойовий токен був недійсний/без доступу до еквайрингу. Перевипустіть у застосунку Monobank (Ще → Мій бізнес → Прийом платежів → Токени) і вставте новий.
  4. Переконайтесь, що тестовий режим оплати вимкнено перед стартом реальних продажів (в Налаштуваннях є явне попередження, коли він активний).
  5. Наповніть реальне меню (категорії/товари) через адмінку, якщо ще не зроблено.
  6. Додайте бота адміністратором у чати доставки/самовивозу, звірте їх chat_id в Налаштуваннях (Telegram інколи мігрує групу в супергрупу й міняє ID — якщо сповіщення раптом перестали приходити, це перша підозра).
  7. Підключіть зовнішній uptime-моніторинг до GET /health.
  8. (Опційно) Якщо потрібна фіскалізація — зареєструйте ПРРО в податковій і касу в Checkbox (кроки й посилання обговорювались окремо), вставте логін/пароль/ліцензійний ключ у Налаштування → Фіскалізація, перевірте підключення і тільки тоді вмикайте перемикач.

Додатково

  • Детальніше про перше розгортання з нуля — docs/DEPLOYMENT.md (описує загальний процес; конкретні шляхи/сервер вище в цьому файлі — джерело правди для поточного продакшену).
  • Пункти, узгоджені із замовником у процесі розробки — docs/OPEN_QUESTIONS.md.
  • Ідеї на майбутнє (нереалізовані, без дедлайну) — docs/TODO.md.