Кейс · коммерческий продукт
Reho24 — продуктовая экосистема краткосрочной аренды
Поиск и бронирование жилья, мобильное приложение, операционные инструменты хоста, отчётность для собственников и внешние интеграции. Всё это работает поверх одного API и одного источника данных. Здесь разобрано, как это устроено и что в такой системе действительно сложно.
02Контекст
Что за продукт и в чём сложность
Краткосрочная аренда — это не только витрина с объектами. Есть гости, которые ищут и бронируют; хосты и собственники, которые управляют объектами и смотрят на деньги; операционная команда, которая заселяет, согласует и разбирает проблемные случаи. Вокруг этого календари доступности, платежи, каналы бронирования и сообщения.
Сложность не в каком-то одном экране. Она в том, что одно и то же состояние — бронь, платёж, календарь — видят и меняют много разных клиентов: сайт, мобильное приложение, внутренние кабинеты, внешние системы. Если у каждого своя версия правды, расхождения неизбежны. Поэтому вся архитектура собрана вокруг единого серверного ядра.
Моя роль в проекте — техническое руководство: архитектура, код-ревью и процесс релизов.
03Архитектура
Один API, много клиентов, один источник правды
Обобщённая схема экосистемы без привязки к конкретным внешним системам.
Центр системы — Django-ядро с REST API на django-ninja и WebSocket-каналами на Django Channels. Веб, мобильное приложение и внутренние кабинеты обращаются к нему по одному контракту, а не к отдельным бэкендам.
Такая схема даёт одну точку, где живут правила: что считается доступным слотом, как считается цена, кто что может видеть. Новый клиент не переизобретает бизнес-логику, он вызывает её.
Всё долгое, ненадёжное и периодическое вынесено из запроса: Celery с Redis берёт на себя фоновые задачи и расписания, а общение с внешними системами идёт через отдельный слой интеграций.
04Backend
Серверная часть
Ядро разбито на предметные домены, а не на один большой набор моделей.
Доменные модули
Бронирования, платежи, объекты, календари, пользователи и другие области разделены по модулям со своими границами. Таких модулей десятки, и это одна из причин держать в проекте дисциплину сотен версионированных миграций.
Единый REST-контракт
Веб, мобильное приложение и внутренние инструменты используют один и тот же API. Изменение контракта проходит через ревью с учётом всех клиентов.
Realtime по WebSocket
Сообщения и обновления состояния доставляются клиентам по каналам Django Channels, без постоянного опроса сервера.
Фоновые задачи и расписания
Большой контур фоновых и периодических задач в Celery: синхронизации, напоминания, пересчёты, отчёты. Повторы и расписания описаны в коде, а не в чьей-то памяти.
Геопоиск
Поиск объектов по карте и расстоянию построен на PostGIS, поэтому география решается в базе, а не фильтрацией в приложении.
Идемпотентная обработка внешних событий
Колбэки платёжных и booking-систем приходят повторно и не по порядку. Обработчики пишутся так, чтобы повтор не создавал второй платёж или вторую бронь.
05Web
Веб-клиент на Vue 3
Публичный клиент написан на Vue 3 и TypeScript, сборка на Vite, состояние в Pinia. Это поиск объектов, карточки, процесс бронирования и личный кабинет: те сценарии, которые гость проходит от выбора жилья до подтверждённой брони.
Для хостов и организаций есть отдельные кабинеты в том же приложении. Самое важное решение здесь — не дублировать на клиенте серверные правила: клиент показывает состояние и отправляет намерения, а допустимость операции определяет API. Поэтому веб и мобильное приложение ведут себя согласованно.
06Mobile
Мобильное приложение на Flutter
iOS и Android собираются из одной кодовой базы на Flutter и Dart. Состояние организовано через BLoC, сетевой слой на dio.
Поиск и карта
Выбор объектов на карте и в списке, фильтры, переход к карточке и бронированию. Карты — Яндекс.
Бронирования и поездки
Гостю доступны его брони, детали заселения и состояние оплаты, а хосту — управление объектами.
Сообщения и push-уведомления
Сообщения приходят в реальном времени, а важные события — через push, даже когда приложение закрыто.
Безопасный вход
Биометрическая авторизация на устройстве и Sign in with Apple. Без отдельной нативной реализации под каждую платформу.
Deep links
Ссылки открывают конкретный объект или бронь прямо в приложении, поэтому переходы из сообщений и писем не обрываются на главном экране.
Один код, два магазина
Единая кодовая база снижает расхождения между платформами и упрощает релизы.
07Внутренние
Внутренние инструменты
Работа команды и отчётность для собственников вынесены из публичных клиентов в отдельные приложения на React, Express и Vite.
Операционный кабинет хоста
Инструмент для повседневной работы с гостями и объектами: у него свои сценарии, плотные таблицы и действия, которым нечего делать в публичном интерфейсе.
Отчётность для собственников
Отдельное приложение финансовой отчётности: что и когда было получено, какие начисления, что подлежит выплате. Данные берутся из того же ядра.
Почему отдельные приложения
У внутренних пользователей другие права, другой темп изменений и другие риски. Отдельная сборка и деплой позволяют менять их, не трогая публичный клиент, при этом оба работают с общим API.
08Интеграции
Внешние системы
Каждая внешняя система ненадёжна по-своему, поэтому интеграции изолированы адаптерами и не смешаны с доменной логикой.
PMS и каналы бронирования
Синхронизация доступности, цен и броней с внешними системами управления размещением.
Платежи и эквайринг
Приём оплат через платёжных провайдеров, обработка их уведомлений и сверка статусов.
Мессенджеры и почта
Уведомления гостям и хостам по тем каналам, где их быстрее заметят.
Push-уведомления
Доставка событий в мобильное приложение.
Отчёты и хранилище
Выгрузки, например в Google Sheets, и файловое хранилище для документов и изображений.
Карты и геокодирование
Преобразование адресов в координаты и отображение объектов на карте.
09Надёжность
Надёжность и процесс
Трассировка
OpenTelemetry показывает путь запроса через API, базу и фоновые задачи, так что медленное место находят по следу, а не наугад.
Метрики
Prometheus собирает показатели сервисов и очередей, а по ним строятся оповещения.
Повторы фоновых задач
Сбой внешней системы не должен терять работу: задачи повторяются с паузами, а неудавшиеся остаются видимыми.
Код-ревью и релизы
Изменения проходят ревью, а выпуск идёт по описанному процессу, а не по настроению того, кто сегодня нажимает кнопку.
Дисциплина миграций
Схема данных меняется на живой системе, поэтому миграции версионируются и проверяются на совместимость с работающим кодом.
10Владение
Почему важен один инженерный владелец
Когда веб, мобильное приложение, внутренние кабинеты и бэкенд ведут разные люди без общего владельца, контракты расходятся: поле называется по-разному, ошибка обрабатывается по-своему, а правило дублируется трижды. Каждое такое расхождение рано или поздно становится багом.
Единая техническая ответственность позволяет менять API с пониманием того, что изменится в каждом клиенте, и держать ревью и релизы в одном процессе. Это не героизм одного человека, а способ уменьшить число мест, где система может разойтись сама с собой.
Итог — коммерческая продуктовая система в эксплуатации, а не демонстрационный проект.
11Стек
Технологии проекта
Backend
Данные
Web
Mobile
Внутренние
Эксплуатация
Нужен похожий продуктовый контур?
Расскажите, какие клиенты и интеграции у вас есть и где сейчас расходится состояние. Разберём архитектуру и скажем, что реалистично.
Обсудить проект13Контакт
Расскажите, что
должно работать.
Опишите задачу, текущую систему и ограничения. Если проект подходит по профилю — предложим следующий шаг: обычно это короткий созвон с вопросами о данных, интеграциях и сроках.
- Telegram@missuk2003
- Emailceo@closeflow.ru
- GitHubHusqvarnalox