Обсудить проект

Кейс · коммерческий продукт

Reho24 — продуктовая экосистема краткосрочной аренды

Поиск и бронирование жилья, мобильное приложение, операционные инструменты хоста, отчётность для собственников и внешние интеграции. Всё это работает поверх одного API и одного источника данных. Здесь разобрано, как это устроено и что в такой системе действительно сложно.

  • Django · Vue 3 · Flutter
  • PostgreSQL · PostGIS · Redis
  • несколько клиентов · один API
  • техническое руководство

02Контекст

Что за продукт и в чём сложность

Краткосрочная аренда — это не только витрина с объектами. Есть гости, которые ищут и бронируют; хосты и собственники, которые управляют объектами и смотрят на деньги; операционная команда, которая заселяет, согласует и разбирает проблемные случаи. Вокруг этого календари доступности, платежи, каналы бронирования и сообщения.

Сложность не в каком-то одном экране. Она в том, что одно и то же состояние — бронь, платёж, календарь — видят и меняют много разных клиентов: сайт, мобильное приложение, внутренние кабинеты, внешние системы. Если у каждого своя версия правды, расхождения неизбежны. Поэтому вся архитектура собрана вокруг единого серверного ядра.

Моя роль в проекте — техническое руководство: архитектура, код-ревью и процесс релизов.

03Архитектура

Один API, много клиентов, один источник правды

Обобщённая схема экосистемы без привязки к конкретным внешним системам.

Центр системы — Django-ядро с REST API на django-ninja и WebSocket-каналами на Django Channels. Веб, мобильное приложение и внутренние кабинеты обращаются к нему по одному контракту, а не к отдельным бэкендам.

Такая схема даёт одну точку, где живут правила: что считается доступным слотом, как считается цена, кто что может видеть. Новый клиент не переизобретает бизнес-логику, он вызывает её.

Всё долгое, ненадёжное и периодическое вынесено из запроса: Celery с Redis берёт на себя фоновые задачи и расписания, а общение с внешними системами идёт через отдельный слой интеграций.

Схема: Web, Mobile, Внутренние, Django API, PostgreSQL, Celery, ИнтеграцииWebVue 3 · TypeScriptMobileFlutter · DartВнутренниеReact · ExpressDjango APIninja · ChannelsPostgreSQLPostGIS · данныеCeleryRedis · расписанияИнтеграцииPMS · платежи · push
fig. Все клиенты работают через один REST-контракт. Состояние живёт в PostgreSQL, всё фоновое и внешнее — за пределами запроса.

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

  • Python
  • Django
  • django-ninja
  • Django Channels
  • Celery

Данные

  • PostgreSQL
  • PostGIS
  • Redis

Web

  • Vue 3
  • TypeScript
  • Vite
  • Pinia

Mobile

  • Flutter
  • Dart
  • BLoC
  • dio

Внутренние

  • React
  • Express
  • Vite
  • Node.js

Эксплуатация

  • Docker
  • OpenTelemetry
  • Prometheus
  • GitHub Actions

Нужен похожий продуктовый контур?

Расскажите, какие клиенты и интеграции у вас есть и где сейчас расходится состояние. Разберём архитектуру и скажем, что реалистично.

Обсудить проект

13Контакт

Расскажите, что
должно работать.

Опишите задачу, текущую систему и ограничения. Если проект подходит по профилю — предложим следующий шаг: обычно это короткий созвон с вопросами о данных, интеграциях и сроках.

brief.form4 поля · 2 минуты

Бюджет необязательно