Разработка мобильного приложения для доставки еды
Доставка еды технически похожа на такси: геолокация, реальный трекинг, платёжный шлюз. Но есть существенные отличия — каталог блюд с вариантами и модификаторами, логика ресторана с расписанием и стопами, время приготовления как отдельная переменная в расчёте доставки, и зоны доставки с разной ценой в зависимости от расстояния.
Три типа систем
Агрегатор (по модели Delivery Club) — много ресторанов, общий пул курьеров, клиент выбирает из нескольких заведений. Сложная диспетчеризация, API для подключения ресторанов, собственный парк курьеров или аутсорсинг.
Собственная доставка ресторана — один ресторан или сеть, свои курьеры. Проще архитектурно, но нужна панель управления для администратора ресторана.
White-label платформа — та же архитектура, что у агрегатора, но для конкретного ресторана или небольшой сети. Промежуточный вариант.
Для большинства стартапов на старте — второй или третий тип. Агрегатор требует отдельного продукта для подключения партнёров, это удваивает объём работы.
Каталог и корзина
Меню ресторана — не просто список блюд. Категории, подкатегории, блюда с вариантами (размер пиццы, степень прожарки, добавки). Структура данных должна поддерживать модификаторы: «добавить сыр +80₽», «выбрать соус» (обязательный одиночный выбор), «убрать лук» (опциональный).
{
"id": 42,
"name": "Пицца Маргарита",
"base_price": 590,
"modifier_groups": [
{
"id": 1,
"name": "Размер",
"required": true,
"min_select": 1,
"max_select": 1,
"options": [
{"id": 11, "name": "25 см", "price_delta": 0},
{"id": 12, "name": "35 см", "price_delta": 150}
]
},
{
"id": 2,
"name": "Дополнительно",
"required": false,
"max_select": 3,
"options": [
{"id": 21, "name": "Двойной сыр", "price_delta": 80},
{"id": 22, "name": "Острый перец", "price_delta": 0}
]
}
]
}
Логика корзины на клиенте: каждая позиция хранит базовый product_id + выбранные modifier_ids. Цена считается на клиенте для отображения, на сервере — для финального заказа. Корзина сохраняется локально при закрытии приложения.
Зоны доставки и минимальная сумма
Ресторан доставляет не везде и с разной ценой. Зоны задаются полигонами — не простыми окружностями. При вводе адреса доставки проверяем попадание в полигон: клиентская проверка (через Google Maps containsLocation(point, polygon) или библиотеку turf.js в виде port на Dart/Swift/Kotlin) как быстрый UX, серверная проверка как финальный арбитр при создании заказа.
PostGIS на сервере: ST_Contains(zone.polygon, ST_MakePoint(:lon, :lat)) — надёжно и точно.
Каждая зона — отдельная строка в таблице со своей стоимостью доставки и минимальным заказом. Если адрес не попадает ни в одну зону — показываем сообщение «К сожалению, в ваш район мы пока не доставляем».
Время приготовления и доставки
Пользователь хочет знать: «когда будет готово и когда привезут». Время приготовления — параметр ресторана, может меняться в зависимости от загрузки. Администратор устанавливает текущее время в панели управления. Время доставки — расчётное на основе расстояния и скорости курьера.
Итоговое отображение: "~45 минут" (готовка 25 + доставка 20). Не обещать точное время, если нет интеграции с реальным диспетчером.
Статусы заказа и трекинг
Для доставки еды статусы сложнее, чем у такси:
placed → confirmed → preparing → ready_for_pickup → courier_assigned → courier_picked_up → delivering → delivered
Клиент видит упрощённую схему: «Принят» → «Готовится» → «В пути» → «Доставлен». Между «В пути» и «Доставлен» — трекинг курьера на карте (тот же WebSocket + анимированный маркер из курьерского трекинга).
Push-уведомления на каждый переход статуса. Firebase Cloud Messaging, data-уведомления для фоновой обработки, notification для отображения. На iOS — UNNotificationContent с категорией ORDER_UPDATE, на Android — выделенный NotificationChannel.
Оплата
Онлайн-оплата (CloudPayments / YooKassa / Tinkoff Acquiring) + оплата наличными при получении + Apple Pay / Google Pay. Предавторизация (холд) — стандартная практика для доставки: сумма холдируется при создании заказа, списывается при подтверждении. Если ресторан не принял заказ — холд снимается автоматически.
Промокоды и бонусная система — отдельный модуль. Применяются на этапе подтверждения заказа, скидка считается на сервере.
Приложение администратора ресторана
Без него система не работает в продакшне. Минимальный набор экранов:
- Текущие заказы (список с таймерами, статусами)
- Управление стопами (кнопка «блюдо закончилось»)
- Текущее время приготовления (поле ввода, применяется сразу)
- Расписание работы
Может быть веб-панелью, не обязательно мобильным приложением для первого этапа.
Стек
| Компонент | Технологии |
|---|---|
| iOS клиент | Swift, UIKit/SwiftUI, GoogleMaps SDK, CloudPayments |
| Android клиент | Kotlin, Jetpack Compose, Google Maps SDK |
| Flutter | Dart, flutter_bloc, google_maps_flutter |
| Бэкенд | Node.js / Laravel / Django, WebSocket, PostgreSQL + PostGIS, Redis |
| Уведомления | Firebase Cloud Messaging |
Сроки
MVP (одна платформа, один ресторан, базовый трекинг): восемь-двенадцать недель.
Полная платформа (iOS + Android, панель ресторана, агрегатор нескольких заведений, аналитика): пять-восемь месяцев.
Стоимость рассчитывается индивидуально после анализа требований и декомпозиции на задачи.







