Разработка и DevOps / кейс 03

TravelLine: Платформа онлайн-бронирования для гостиничного бизнеса

Единая платформа для управления бронированием, тарифами, доступностью, оплатой и каналами продаж. Состояние брони и правила повторной обработки защищают систему от дублей и овербукинга.

  • SaaS
  • Бронирование
  • Платежи
Экран выбора номера в модуле онлайн-бронирования TravelLine

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

Паспорт продукта

  • Направление: SaaS, backend, frontend, платежи, интеграции.
  • Задача: Объединить бронирование, тарифы, доступность, оплату и каналы продаж в одном кабинете, исключить внутреннюю двойную продажу и снизить риск овербукинга между каналами.
  • Продолжительность: 9 месяцев с поэтапным выпуском модулей.
  • Команда: Product manager, аналитик, tech lead, 4 backend-разработчика, 3 frontend-разработчика, 2 mobile-разработчика, 2 QA, UX и DevOps. Всего 16 человек.
  • Роль AIFlowPoint: Разработка модуля бронирования, кабинета отеля, логики резервов, платежных сценариев и синхронизации каналов продаж.

Бизнес-ситуация: одна бронь, несколько источников состояния

Отель управлял тарифами, квотами и доступностью, а внешние каналы продаж присылали заявки и обновления с задержками и повторами. Последний свободный номер мог одновременно выглядеть доступным в нескольких каналах, поэтому особенно важной была согласованность состояний.

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

Объем работ ограничили модулем бронирования и связанным с ним операционным контуром. В него вошли кабинет отеля, web и mobile сценарии, управление доступностью, платежи, синхронизация с каналами и инструменты разбора расхождений. Задача не формулировалась как обещание полностью устранить внешние задержки. Целью было исключить внутреннюю двойную продажу и сделать межканальные расхождения наблюдаемыми и восстанавливаемыми.

Модель владения и ключевые решения

Перед разработкой зафиксировали владельца каждого вида данных между отелем, каналами продаж, платежной системой и платформой. Единое состояние брони сохранили внутри платформы. Заранее определили обработку задержек, повторных уведомлений и расхождений по доступности. Операции с доступностью сделали транзакционными, а внешние заявки идентифицируемыми.

Это дало системе явные правила. Параллельные клиенты не могли внутри платформы купить последний доступный номер. Внешнее сообщение со стабильным идентификатором можно было безопасно принять повторно. Задержка одного канала не блокировала весь кабинет. Если уведомление терялось, состояние восстанавливалось повторной синхронизацией, а сотрудник мог увидеть историю изменения цены, квоты или статуса.

Что реализовали для гостя и отеля

Пользовательский и операционный пути собрали в одном контуре:

  1. Разработали бронирование по датам, гостям, номеру, тарифу и дополнительным услугам.
  2. Создали кабинет отеля для управления ценами, квотами, ограничениями и закрытыми датами.
  3. Добавили временный резерв номера и автоматическое освобождение просроченного резерва.
  4. Подключили менеджер каналов и обмен доступностью с внешними площадками.
  5. Реализовали оплату, возврат, частичную отмену и подтверждающие документы.
  6. Добавили правила срока проживания, раннего заезда, позднего выезда и пакетных предложений.
  7. Подготовили журнал изменений цены и доступности с причиной каждого изменения.
  8. Разработали mobile сценарий кабинета для быстрых действий администратора.

Для гостя путь начинался с выбора дат, состава гостей, номера и тарифа. На время оплаты система удерживала ограниченный резерв, а после подтверждения фиксировала финансово значимое состояние. Для сотрудника отеля кабинет объединял цены, квоты, ограничения, закрытые даты и журнал изменений. Mobile клиент позволял выполнять быстрые административные действия без отдельного рабочего места.

Технический контур

.NET обслуживает бизнес-правила бронирования и интеграции. Vue.js отвечает за web-кабинет, Flutter дает единый mobile клиент. SQL Server хранит брони и финансово значимые состояния, Redis используется для коротких резервов, RabbitMQ доставляет изменения внешним каналам, а ClickHouse собирает продуктовую аналитику. OpenAPI фиксирует контракт интеграций, k6 проверяет периоды резкого роста спроса.

Операции с доступностью выполняются транзакционно. У каждой внешней заявки есть стабильный идентификатор. Повторное сообщение не создает новую бронь, а задержка одного канала не блокирует работу всего кабинета.

Состояния брони и интеграционные контракты стали частью передаваемой системы, а не скрытой логикой отдельных обработчиков. Нагрузочная проверка охватывала критические сценарии, где спрос и число параллельных резервов растут. Журнал и traces внешних каналов помогали отделить внутреннюю ошибку от задержки или повтора на стороне интеграции.

Технологический контур проекта: C#, .NET, ASP.NET Core, Vue.js, TypeScript, Flutter, Microsoft SQL Server, Redis, RabbitMQ, ClickHouse, REST API, OpenAPI, Jenkins, Docker, ELK Stack, Playwright, xUnit и k6. Его роль в кейсе состоит в объяснении состояний брони, интеграций, аналитики и проверок, а не в длине списка технологий.

Результат и измеримый эффект

Операционная команда получила способ отделять внутренний конфликт бронирования от задержки внешнего канала и восстанавливать обмен без ручного исправления состояния.

Измеримый результат: Ноль внутренних двойных продаж последнего номера; не менее 95% обновлений доступности доставляются каналам за две минуты; количество ручных разборов расхождений снижается на 30-50%.

Эффект: Отель получил единое состояние брони и стал значительно реже вручную разбирать конфликты между каналами продаж.

Приемка, отказные ветки и проверка результата

Критерии проверки были привязаны к наблюдаемому поведению:

  • Два параллельных клиента внутри платформы не могут купить последний доступный номер.
  • Изменение тарифа не переписывает цену уже подтвержденной брони.
  • Повторный платежный callback не создает вторую оплату.
  • Потерянное уведомление восстанавливается повторной синхронизацией.
  • Сотрудник видит, кто и когда изменил цену, квоту или статус.
  • Критические сценарии проходят нагрузочную и browser-проверку.

Результат фиксируют схема состояний брони, нагрузочный отчет, dashboard синхронизации, traces внешних каналов и журнал инцидентов до и после. Материалы связывают исходную частоту ручных разборов с периодом после внедрения и отдельно показывают доставку обновлений в пределах целевого времени.

Что передали

  • Web-кабинет и mobile клиент.
  • Backend, схему данных и миграции.
  • Интеграционные контракты.
  • Схему состояний брони.
  • Набор автотестов.
  • Инструкции поддержки.
  • Runbook для расхождений между каналами.

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

Кому релевантно

Кейс подходит платформам, где одна коммерческая сущность изменяется через несколько внешних каналов, а задержки, повторы и частичные отказы неизбежны. Это может быть бронирование, резервирование ограниченного ресурса или другой процесс, где важны единый владелец состояния, идемпотентность и журнал изменений.

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