Для кофеен, пекарен и кафе на 1–5 точек

Продукты всегда в наличии

Склад, прогноз спроса и напоминания о заказе. Система сама считает, что и когда заказать, — и присылает сводку в Telegram.

Как это работает

Демо живёт 24 часа, регистрация не нужна.

2 критично 6 заказать 31 хватает 1 нет данных Молоко 3,2% 18 л заказать 2 кор. Стаканы 350 мл 40 шт критично 4 уп. Зерно Бразилия 6,4 кг хватает Почему такой статус Сейчас 18 л, в пути 0. До поставки в пн нужно 31 л + запас 4 л. Не хватает 17 л → заказать 2 кор. (24 л)

Знакомо?

Закончилось посреди смены

Молоко кончается в разгар утреннего потока. Бариста бежит в магазин по розничной цене, очередь стоит.

Выбросили просрочку

Заказали с запасом «чтобы точно хватило» — половина ушла в списание. Деньги сгорели дважды: при закупке и при выбросе.

Всё держится в голове владельца

Учётная система показывает остаток, но не отвечает на главный вопрос: когда заказывать. Отпуск — и всё рассыпается.

Как это работает

  1. 1

    Учёт

    Приход, расход, списания и пересчёт. Остаток никогда не правится руками — он равен сумме движений, и любую цифру можно объяснить по журналу.

  2. 2

    Прогноз

    Система считает расход на 14 дней вперёд по истории, с учётом дня недели, и показывает собственную точность. Не «магия ИИ», а честные числа, которые видно.

  3. 3

    Напоминание

    Зная срок поставки и дни доставки поставщика, система считает, хватит ли запаса до следующего заказа. Если нет — присылает сводку с готовым количеством.

Промотайте неделю за секунду

В демо есть кнопка «+7 дней». Система проживает неделю: списывает расход, принимает поставки, пересчитывает прогноз и шлёт сводки.

Рядом — переключатель «автопилот». С ним система заказывает сама, и через неделю почти всё зелёное. Без него позиции краснеют. Это и есть сравнение «с системой и без».

Так приходит сводка в Telegram
Кофейня «Демо» · среда, 23 сентября

Заказать сегодня (3)
Молочная ферма — до 16:00, поставка в чт
  • Молоко 3,2% — 2 кор. (24 л), сейчас хватит до пт
  • Сливки 33% — 1 кор. (6 л)
Кофе-Импорт — до 18:00, поставка в пт
  • Зерно Бразилия — 2 × 1 кг

Критично (1)
  • Стаканы 350 мл — хватит только до завтра,
    ближайшая поставка в пт

Открыть дашборд →

Точность видна, а не обещана

Каждую ночь система проверяет себя: строит прогноз на прошлые дни по данным, которые были тогда, и сравнивает с тем, что случилось на самом деле.

86% точность на демо-данных

В карточке позиции написано прямо: «86% за 28 дней, модель M2, завышает на 3%». Если модель ошибается — это видно, а не скрыто.

— факт - - прогноз

Как это устроено

Этот раздел — для тех, кто смотрит на проект как на код, а не как на продукт.

Стек

Go (chi, pgx + sqlc, без ORM) · PostgreSQL 16 · Redis + asynq · React + TypeScript + Vite · Tailwind · systemd + Nginx

Ключевые решения

  • Журнал движений. Таблица только дописывается: права на UPDATE и DELETE отозваны у роли приложения. Ошибка исправляется сторно, а не правкой.
  • Изоляция тенантов на четырёх уровнях. Row-level security в базе, роль без BYPASSRLS, составные внешние ключи. Забытый WHERE tenant_id перестаёт быть уязвимостью.
  • Transactional outbox. Уведомление пишется в одной транзакции с событием, отправкой занимается воркер. Telegram не влияет на время ответа API.
  • Абстракция часов. time.Now() запрещён — время берётся из интерфейса. На этом держится «промотка времени» в демо.

Что проверено тестами

  • 50 горутин одновременно списывают одну позицию: остаток не уходит в минус и сходится с журналом.
  • Повтор запроса с тем же ключом не создаёт второе движение, повторная приёмка — второй приход.
  • Чужой тенант получает 404 на любой ресурс; запросы без тенанта возвращают ноль строк.
  • Точность прогноза на сгенерированных данных: WAPE ≤ 20% с фиксированным seed.

Об авторе

Виталий Остапенко. Делаю бэкенд на Go и интерфейсы на React. Этот проект — учебный: я хотел пройти путь целиком, от требований и схемы данных до деплоя и мониторинга, и не срезать углы там, где обычно срезают.