История о том, как желание автоматизировать хаос на кухне привело к созданию готовой системы для доставки еды с открытым исходным кодом (ну, почти). Технические детали, грабли и выводы.

Лирическое отступление

Привет. Я программист (со скидкой на самоучку), который в 2021 году решил, что открыть две шаурмичные — хорошая идея. Спойлер: идея была так себе. Но из этого вышла полезная CRM, которой сейчас пользуются 15+ заведений. Расскажу, как я её писал, на чём сломался и почему мой код до сих пор не идеален.

Если вам нужна только техническая часть — листайте к разделу «Архитектура». Если интересна драма с бумажками и комиссиями — читайте по порядку.


Предыстория: почему я вообще влез в ресторанный бизнес

Я всегда любил готовить. А ещё мне казалось, что управлять точкой общепита несложно: нанял поваров, подключил агрегаторы, настроил учёт — и сиди получай деньги.

В 2021 году открыл первую шаурмичную в спальном районе. 45 квадратов. Работа с 11 до 23. В пик — до 30 заказов в день, в обычные дни 15–20. Средний чек около 500 ₽. Выручка в хороший месяц 400–500 тыс. ₽. Аренда, продукты, зарплаты съедали почти всё, оставалось 50–100 тыс. «чистыми» при идеальном раскладе.

Через полгода открыл вторую точку (30 квадратов). Это была ошибка. Вместо того чтобы отладить процессы на первой, я решил масштабироваться. В итоге обе работали в режиме «пожар».

Что меня бесило больше всего:

  1. Заказы из трёх источников: телефон (звонки), WhatsApp, агрегаторы (Яндекс Еда, Delivery Club). Всё перемешивалось. Повара записывали заказы на бумажки, теряли их, путали адреса.

  2. Комиссии агрегаторов — 25–30% с заказа. В месяц выходило 30–40 тыс. ₽ с двух точек. Деньги, которые уходили в воздух.

  3. Отсутствие контроля. Я не понимал реальных остатков, не вёл управленческий учёт, не видел динамики продаж. Каждый вечер я вручную сводил заказы из трёх каналов — уходило 2–3 часа.

  4. Повара не хотели учиться. Я попробовал купить готовую CRM за 5 тыс. ₽/мес. Повар посмотрел и сказал: «Сложно, я лучше на бумажке». Система оказалась бесполезной.

Я понял, что либо автоматизируюсь, либо закрою точки. Денег на разработку от студии (500–800 тыс. ₽) не было. Поэтому я сел и написал свою CRM.


Архитектура: что внутри

Я не профессиональный бэкенд-разработчик. Знаю PHP на уровне «починить WordPress и написать простой CRUD». Поэтому архитектура максимально простая, без изысков.

Стек:

  • Backend: чистый PHP 7.4 (без фреймворков). Почему без фреймворка? Потому что я хотел контролировать каждый запрос и не тащить лишние зависимости. Да, это велосипед. Но работает.

  • База данных: MySQL 5.7 (InnoDB). Всего 12 таблиц: заказы, товары, категории, промокоды, пользователи, настройки и т.д.

  • Frontend: HTML5, CSS3 (адаптив через медиа-запросы), vanilla JS (без React/Vue — чтобы не усложнять).

  • Сервер: обычный хостинг за 350 ₽/мес (Apache, PHP, MySQL).

Основные модули (как есть в коде):

  1. Клиентская витрина (frontend)

    • Адаптивная вёрстка под телефон и планшет.

    • Категории товаров, корзина с динамическим пересчётом (JS).

    • Промокоды (проверка через AJAX).

    • Выбор времени доставки / самовывоза.

    • Статус заказа в реальном времени (обновляется по кнопке, без веб-сокетов — просто через setInterval).

  2. Админ-панель

    • CRUD для товаров, категорий, промокодов.

    • Загрузка изображений через медиа-менеджер (без FTP — всё через веб-интерфейс).

    • Настройки доставки (стоимость, бесплатно от суммы, интервалы).

    • Просмотр списка заказов с фильтрами по статусу и дате.

    • Ручное создание заказа (для оператора по телефону).

    • Статистика: выручка за период, графики (Google Charts), экспорт в CSV.

  3. Кухонный монитор (отдельный вход для повара)

    • Минималистичный интерфейс — только крупные кнопки.

    • Автоматическое обновление каждые 10 секунд (polling).

    • При новом заказе воспроизводится звук (через HTML5 Audio). Я записал свой голос: «Новый заказ!» (можно заменить на MP3 через медиа-менеджер).

    • Статусы: «Новый» → «Готовится» → «Готов».

    • Кнопка «Печать чека» — вызывает window.print() с кастомными стилями для чека (логотип, адрес, телефон, состав заказа).

    • Группировка заказов по дням (сегодня / вчера / раньше).

  4. Полуавтоматическая оплата

    • После оформления заказа клиент видит QR-код (через библиотеку phpqrcode) и ссылку на оплату (например, на СБП или карту).

    • Администратор вручную подтверждает оплату в админке (кнопка «Оплачен»).

    • Я отказался от полноценного эквайринга из-за сложности интеграции и юридических нюансов. Это упрощение, но оно устраивает 90% моих клиентов (самозанятые и ИП без кассы).

  5. Безопасность

    • Пароли хешируются через password_hash() (bcrypt).

    • CSRF-защита для форм (токены).

    • Экранирование вывода через htmlspecialchars().

    • Подготовленные запросы (PDO) для защиты от SQL-инъекций.

    • Отдельные сессии для админа, оператора и повара.

Интересные технические решения (или костыли, называйте как хотите):

  • Звуковое оповещение на кухне:
    При загрузке кухонного монитора я проверяю localStorage на наличие флага «звук включён». По умолчанию — включён. Когда приходит новый заказ (при очередном polling), я вызываю new Audio(url).play(). Но браузеры блокируют автовоспроизведение, поэтому пришлось повесить первый звук на клик по экрану (инструкция для повара: «нажмите в любом месте, чтобы включить звук»). Костыль, но работает.

  • Печать чека:
    Использую CSS media print. Скрываю всё лишнее, оставляю только блок с логотипом, составом заказа и итогом. Вызываю window.print(). Пользователь (повар) нажимает Ctrl+P или соглашается. Не элегантно, но для кухни — идеально.

  • Обновление статусов без веб-сокетов:
    Простой polling с интервалом 10 секунд. Нагрузка на сервер минимальная (при 30 заказах в день — смешно). Веб-сокеты излишни.

  • Загрузка изображений:
    Пишем в папку /uploads/ с уникальным именем (uniqid). Проверка MIME-типа (getimagesize), ограничение размера (2 МБ). В админке можно удалить картинку — файл стирается с диска.

  • Миграции БД:
    Написал простой install.php, который проверяет наличие таблиц и создаёт их с начальными данными (админ, тестовые товары). Для обновлений — отдельный скрипт update.php, который выполняет ALTER TABLE при необходимости. Не LevelDB, но для моего масштаба хватает.


Что пошло не так (технические грабли)

  1. Сначала не было мобильной версии кухонного монитора.
    На планшете 10 дюймов всё было красиво. Но один клиент поставил систему на старый телефон 5 дюймов — интерфейс развалился. Пришлось переписывать вёрстку под любой экран, использовать flex-wrap и относительные размеры.

  2. Звук на iOS не работал.
    На iPhone кухонный монитор не воспроизводил звук автоматически из-за политики Apple. Решение: добавить большую кнопку «Разрешить звук» при первом заходе, которая запускает пустой аудиоплеер по клику. Повара привыкли, но минус один балл к UX.

  3. Не предусмотрел ручное создание заказа.
    Первые дни клиенты звонили и говорили: «Я не могу оформить на сайте». Пришлось срочно дописывать форму в админке, где оператор выбирает товары, вводит адрес и телефон. Заказ сохраняется в ту же таблицу orders с флагом is_manual = 1. На кухне он появляется так же, как и обычный.

  4. Проблема с кодировкой.
    На старом хостинге MySQL был в latin1. Комментарии клиентов («без лука», «позвоните в домофон») превращались в кракозябры. Перевёл базу в utf8mb4, добавил SET NAMES utf8 в подключении. Больше не повторял.

  5. Отсутствие логов.
    Первые недели я не логировал ошибки. Когда упал сервер (из-за нехватки памяти), я потратил час, чтобы понять причину. Добавил простой логгер: error_log(print_r($data, true), 3, '/logs/error.log'). Хватило.


Цифры (сколько потерял и сэкономил)

Потерял:

  • На открытии второй точки — около 700 тыс. ₽ (ремонт, оборудование, аренда).

  • Время — 1,5 года жизни, которые мог бы потратить на развитие как программист.

  • Нервы — не поддаются оценке.

Сэкономил после внедрения системы на первой точке:

  • Время на сверку заказов: с 2–3 часов в день до 20 минут.

  • Ошибки поваров упали на 90%.

  • Экономия на комиссиях агрегаторов: 10–15 тыс. ₽ в месяц (часть заказов перешла на мой сайт).

Итог: за год система сэкономила около 150–200 тыс. ₽ на первой точке. Этого хватило, чтобы покрыть убытки от второй и закрыться без долгов.

Сейчас я продаю систему за 9 900 ₽. За год продано около 15 лицензий (установки на разные заведения). Это не стартап-миллионы, но пассивный доход, который растёт.


Кому это может пригодиться (как разработчику)

Если вы начинающий PHP-программист и хотите сделать свой pet-проект, который реально востребован — берите идею. Вот что вы можете вынести из моего опыта:

  • Начните с решения своей проблемы. Не пытайтесь сразу сделать универсальную CRM для всех. Сделайте для себя, потом доработаете.

  • Не бойтесь велосипедов. Чистый PHP без фреймворков — это быстро, понятно и контролируемо. Для небольших проектов это ок.

  • Тестируйте на реальных пользователях. Повар — лучший тестировщик. Если он говорит «сложно» — переделывайте.

  • Думайте о мобильной вёрстке с первого дня. Даже если кажется, что все будут использовать планшеты — кто-то обязательно возьмёт телефон.

  • Готовьте документацию. Без неё вашу систему никто не сможет установить, кроме вас. Я написал инструкцию по установке за 2 часа — и это сэкономило десятки часов поддержки.

Исходный код я не открываю (продаю), но готов поделиться структурой БД и основными принципами в комментариях, если интересно.


Вопрос к сообществу

  1. Как вы считаете, правильно ли я отказался от фреймворка (Laravel/Symfony) в пользу чистого PHP? В плюсах — скорость и контроль. В минусах — безопасность и масштабируемость.

  2. Полуавтоматическая оплата (вручную подтверждать) — это нормальное упрощение для малого бизнеса или костыль, который надо выпиливать?

  3. Как бы вы организовали звуковое оповещение без костыля с кликом по экрану? Веб-сокеты + разрешение на уведомления?

Я в комментариях отвечу на любой вопрос по коду, архитектуре или ресторанному опыту. Даже на критику — главное, без хамства.


P.S. Систему я продаю, но ссылку на демо не прикладываю, потому что правила Хабра запрещают прямую рекламу в статьях. Если хотите посмотреть, как работает кухонный монитор со звуком и печатью — найдите меня в Telegram (NailWeb4).