Разработка и DevOps / кейс 07
Chibbis: сервис заказа еды и кабинет ресторана
Единая продуктовая система для выбора ресторана, оформления и оплаты заказа, отслеживания доставки и работы партнеров. В нее входят web-интерфейс, mobile приложения и адаптеры ресторанных интеграций.
Один заказ в foodtech проходит не через один экран, а через цепочку участников. Гость выбирает блюда и оплачивает, ресторан подтверждает состав, оператор следит за исключениями, курьер получает данные для доставки. Если каждый интерфейс хранит свою версию происходящего, расхождение быстро становится бизнес-проблемой: в корзине остается недоступная позиция, цена меняется после выбора, повторное нажатие создает дубль, а сбой кассы одного ресторана выглядит как остановка всего сервиса.
В этом кейсе центральным результатом стала не новая витрина сама по себе. Главное, что единая история заказа связала действия гостя, ресторана, оператора и курьера, а интеграционные сбои получили локальные и проверяемые границы.
Контур проекта
- Задача: Объединить каталог ресторанов, заказ, оплату, статусы доставки и работу партнеров в одной продуктовой системе.
- Направление: Foodtech, web, mobile, backend, интеграции.
- Точная ответственность AIFlowPoint: Разработка web-каталога и корзины, кабинета ресторана, клиентского и курьерского приложений, сервисов заказа и кассовых адаптеров
- Продолжительность: 9 месяцев на web, mobile, backend и основные интеграции.
- Команда: Product manager, аналитик, UX/UI, 3 backend-разработчика, 2 web-разработчика, Android-разработчик, iOS-разработчик, 2 QA и DevOps. Всего 13 человек.
- Фокус: Foodtech, Web и mobile, Интеграции.
Ситуация клиента и цена рассинхронизации
Один заказ проходил через гостя, ресторан, оператора и курьера, но каждый участник видел его в своем интерфейсе. Рестораны использовали разные кассовые системы и по-разному передавали меню, стоп-листы и статусы, а сбой одного партнера не должен был останавливать весь сервис.
Покупательская задача здесь шире редизайна каталога. Нужно было сохранить согласованное состояние заказа от выбора ресторана до доставки, не позволить старым данным незаметно превратиться в оплату и изолировать нестабильность внешнего партнера. Для бизнеса это означает управляемый заказ даже тогда, когда меню, статусы и кассовые ответы приходят из систем с разным поведением.
Что именно связывала AIFlowPoint
В объем работ AIFlowPoint вошли web-каталог и корзина, кабинет ресторана, клиентское и курьерское приложения, сервисы заказа и кассовые адаптеры. Именно в этих границах описаны решения, проверки, метрики и передача результата. Разработка всей платформы Chibbis и всех интеграций компании в объем работ AIFlowPoint не входила.
Один заказ как источник правды
Работу начали с четырех решений, которые удерживают продукт вокруг одного заказа:
- Разделили сценарий между гостем, рестораном, оператором и курьером.
- Сохранили заказ единым объектом с общей историей для всех участников.
- Вынесли интеграции с разными кассовыми системами в отдельные адаптеры.
- Зафиксировали цену и состав заказа в момент подтверждения, а для внешних статусов ввели проверку допустимых переходов.
Такой подход отделяет внутреннее состояние заказа от особенностей конкретной кассы. Гость и сотрудники работают с одним объектом, а несовместимые форматы и временные ошибки партнеров остаются внутри адаптеров. Цена, состав и переходы статусов не принимаются как произвольные внешние сообщения, а проходят через бизнес-правила.
Четыре интерфейса вокруг одной истории
- Разработали новый web-интерфейс каталога, поиска, карточки ресторана и корзины.
- Синхронизировали меню, цены, модификаторы, график и недоступные позиции.
- Добавили онлайн-оплату, промокоды, бонусы и расчет итоговой суммы.
- Создали кабинет партнера и mobile приложения для клиента и курьера.
- Реализовали события заказа, push-уведомления и поддержку в контексте доставки.
- Добавили защиту от дублей, повторной оплаты и изменения цены после подтверждения.
- Настроили мониторинг интеграций, чтобы сбой одного ресторана не выглядел как общий сбой сервиса.
Это не набор независимых экранов. Каталог и корзина зависят от актуального меню, платеж зависит от зафиксированного состава, кабинет ресторана работает со своими заказами, приложения получают согласованные события, а поддержка видит контекст конкретной доставки. Мониторинг при этом должен отличать локальную деградацию кассового адаптера от общей недоступности продукта.
Как изолировали разные кассовые системы
React и server-side rendering дают быстрый индексируемый каталог. ASP.NET Core обслуживает заказы и бизнес-правила, Kotlin и Swift используются в нативных приложениях. Реляционные базы хранят заказ и расчеты, MongoDB используется для части гибких каталогов и событий, Redis ускоряет чтение и короткие блокировки, RabbitMQ доставляет изменения между сервисами. Prometheus, Grafana и ELK помогают отличить ошибку приложения от проблемы конкретной интеграции.
Цена и состав фиксируются в момент подтверждения. Старый экран не может отправить заказ с устаревшей стоимостью незаметно для пользователя. Любой внешний статус проходит проверку допустимого перехода.
Технологический контур проекта: React, TypeScript, Node.js, Server-side rendering, C#, ASP.NET Core, Kotlin, Swift, Microsoft SQL Server, MySQL, MongoDB, Redis, RabbitMQ, Docker, Docker Swarm, GitLab CI, Nginx, HAProxy, Prometheus, Grafana, ELK Stack, Playwright и xUnit. Каждая технология связана с конкретной частью заказа, интеграций, наблюдаемости или автоматической проверки.
Что происходит при старой цене, дубле или сбое кассы
Кейс раскрывает четыре критичных отказных сценария. Первый связан с устаревшими данными: позиция уже недоступна или цена изменилась, пока у гостя открыта старая вкладка. Второй связан с повтором действия: двойное нажатие или повторная попытка оплаты не должны создавать второй заказ или списание. Третий связан с кассовой системой ресторана: временная ошибка должна попасть в контролируемую очередь, не останавливая остальных партнеров. Четвертый связан с видимостью состояния: клиенту нужен понятный статус и способ обратиться в поддержку, даже когда внешний контур деградировал.
Как принимали контур заказа
Результат проверяется наблюдаемым поведением, а не фактом наличия экранов:
- Недоступную позицию нельзя оплатить из старой вкладки.
- Ресторан видит только свои заказы и настройки.
- Повторное нажатие не создает второй заказ.
- Сбой кассовой системы попадает в контролируемую очередь.
- При сбое кассовой системы клиент видит статус заказа и способ связаться с поддержкой.
- Ключевой путь проверяется в web, Android и iOS.
Что изменилось для гостя и операционной команды
Гость, ресторан, оператор и курьер работают с одной историей заказа вместо разрозненных состояний. Цена и состав фиксируются при подтверждении, старая вкладка не позволяет оплатить недоступную позицию, повторное действие не создает новый заказ, а сбой одной кассовой интеграции не останавливает остальные рестораны.
Измеримый результат: Медианное время оформления заказа сокращается на 20-35%; доля технических дублей заказов и оплат ниже 0,01%; не менее 95% временных сбоев партнерских интеграций восстанавливаются автоматически.
Эффект: Команда улучшила действующий продукт без остановки сервиса и сделала сбои отдельных ресторанов управляемыми.
Материалы, оставшиеся продуктовой команде
- Web и mobile приложения
- Сервисы заказа
- Кабинет ресторана
- Адаптеры кассовых интеграций
- Документация событий
- Дашборды и автотесты
- Порядок реагирования на инциденты
Такая передача позволяет продолжать развитие не только через исходный код. У команды остаются интерфейсы, сервисный контур, правила событий, наблюдаемость, автоматические проверки и порядок работы с инцидентами.
Как проверили отсутствие дублей и локализацию сбоев
Артефакты проекта: продуктовая аналитика до и после, журнал idempotency, dashboard кассовых адаптеров и разборы интеграционных инцидентов. Они связывают эффект с наблюдаемым изменением продукта и показывают, как контролировались дубли и локальные сбои.
Кейс релевантен foodtech-платформам, маркетплейсам и другим продуктам, где одна операция проходит через несколько ролей и внешних партнеров. Особенно близкая ситуация возникает, когда нельзя остановить действующий сервис ради большой перестройки, но нужно сделать критичный путь согласованным и восстанавливаемым.
Есть заказ или другая операция, которая расходится между клиентом, партнером и внутренней командой? Пришлите схему текущего пути. Разберем один принимаемый контур, его повторы, внешние сбои и критерии передачи результата.