«КортФлоу» — SaaS для операционного управления клубом с кортами

Обновлено:
CRM Системы3 месяцаNDA

Мы разработали вертикальный SaaS для клубов на 4–12 кортов: брони, занятия, участники, тренеры и деньги живут в одном окне вместо связки «бумажный журнал у стойки, Excel и мессенджер». Это back-office управляющего и администраторов, а не приложение для игрока: на первом экране видна выручка дня и загрузка кортов. Переключатель клуба в сайдбаре даёт мультиарендность — один аккаунт ведёт сеть площадок или франшизу. Проект выполнила команда полного цикла за 3 месяца.

«КортФлоу» — SaaS для операционного управления клубом с кортами

Задача

Клуб с кортами — это бизнес, который продаёт время. Корт-час либо продан, либо потерян навсегда: непроданный слот нельзя отложить на завтра. Поэтому операционка клуба сводится к двум вопросам — насколько плотно заполнено расписание и сколько денег принёс каждый час работы площадки.

На практике этот учёт до сих пор часто держится на связке «бумажный журнал у стойки + Excel + мессенджер». Журнал знает про брони, но не знает про оплату. Таблица знает про членство, но не знает, кто сегодня не пришёл. Переписка знает про переносы, но об этом не знает никто, кроме двух собеседников. Данные не сходятся, а сверка съедает время администратора в самые загруженные часы.

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

Расписание живёт отдельно от денег

Бронь фиксировалась в журнале, оплата — в кассе или переводом, а сопоставление шло вручную в конце дня. Ответ на вопрос «сколько мы заработали сегодня» появлялся к вечеру, а не в момент, когда на него можно повлиять.

Блокировки корта не доходят до продажи

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

Членство не влияет на правила автоматически

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

Загрузка кортов не измеряется

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

Что делает система

Дашборд

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

Расписание

Сетка «корты × время» — основной рабочий инструмент администратора. Переносы, повторяющиеся брони для регулярных игроков и блокировка кортов под ремонт или турнир. Заблокированный корт сразу исчезает из продажи, поэтому ситуация «продали слот, которого нет» технически невозможна.

Бронирования

Аренда корта и тренировка — две разные сущности со своими правилами, а не один тип записи. Онлайн-оплата, отмены, лист ожидания на занятые слоты и правила по неявкам. Лист ожидания превращает отказ в продажу: освободившийся слот уходит следующему в очереди, а не остаётся пустым.

Участники и членство

База участников с уровнями членства — Стандарт, Премиум, Участник. Уровень определяет цену и глубину окна бронирования, то есть за сколько дней можно занять корт. Здесь же история платежей, автопродление и задолженности: правила применяются системой одинаково ко всем, а не по памяти администратора.

Тренеры

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

Корты и динамический прайс

Карточка корта хранит покрытие, наличие света и признак крытого или открытого. На этих характеристиках строится динамический прайс по дню недели и часу: вечерний крытый корт в будний день и утренний открытый в понедельник — разный товар и разная цена.

Операции

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

Аналитика

Загрузка по слотам, выручка на корт-час, отток участников и воронка «пробное занятие → членство». Четыре среза отвечают на разные вопросы: где пустует расписание, какой час зарабатывает, кто уходит из клуба и насколько эффективно пробные занятия превращаются в постоянных участников.

Мультиарендность

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

Технологический стек

React + TypeScript

Сетка «корты × время» с переносами и блокировками — это сложное состояние, которое меняется от каждого действия администратора. Строгая типизация ловит рассинхрон структур данных на сборке, а не в час пик у стойки, когда цена ошибки — потерянная бронь.

Next.js

Серверный рендеринг даёт быстрый первый экран на слабых устройствах за стойкой, а роутинг и API-слой в одном приложении упрощают поддержку. Дашборд открывается сразу с данными, без ожидания клиентских запросов.

Node.js

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

PostgreSQL

Бронирование — это конкуренция за один и тот же ресурс: два администратора могут одновременно занимать один слот. Транзакции и ограничения на уровне базы гарантируют, что корт-час не будет продан дважды, а не полагаются на проверку в коде.

Аналитический слой

Загрузка по слотам и выручка на корт-час — агрегаты по большому количеству броней. Предрасчёт по срезам «период × площадка» держит дашборд быстрым: метрики дня открываются мгновенно, а не пересчитываются на каждый вход администратора.

ReactTypeScriptNext.jsNode.jsPostgreSQLAnalytics

Как шла разработка

День администратора за стойкой

Готово

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

Модель броней и правил

Готово

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

Расписание и защита от двойной продажи

Готово

Собрали сетку «корты × время» с переносами и повторяющимися бронями, а конкуренцию за слот закрыли на уровне базы данных. Одновременная попытка занять один корт-час двумя администраторами завершается предсказуемо, без ручного разбора постфактум.

Деньги и аналитика

Готово

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

Мультиарендность и запуск

Готово

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

Результаты

Клуб получил одно рабочее место вместо связки «журнал, таблица, мессенджер». Бронь, оплата, членство и блокировки живут в общем контуре, поэтому сверка данных в конце смены превратилась из ежедневной рутины в проверку готового отчёта.

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

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

3 месяца

от разбора смены администратора до запуска

4–12 кортов

рабочий размер клуба, под который спроектирована система

9 разделов

от расписания и броней до операций и аналитики

4 среза

аналитики: загрузка, выручка на корт-час, отток, воронка

Почему кейс без имени клиента

Название клуба и его финансовые показатели закрыты соглашением о неразглашении, поэтому в кейсе нет ни имени клиента, ни реальных цифр по выручке и загрузке. Всё описанное выше — наша работа: архитектура системы, состав модулей, интерфейсные решения и сроки разработки.

Данные на скриншотах интерфейса демонстрационные. Описание проблем в разделе «Задача» — типовая картина отрасли, с которой к нам приходят клубы с кортами, а не внутренняя кухня конкретной площадки.

Вопросы о проекте

Обсудим похожий проект?

Расскажите о задачах вашего бизнеса — предложим архитектуру и оценим сроки