← Все проекты

Android + веб · расписание, абонементы, справки

Бассейн: приложение и кабинет

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

Kotlin Jetpack Compose NestJS PostgreSQL FCM Material 3

Презентация для владельца бизнеса

PDF, 1,3 МБ · обновлена 22.08.2026 · скачать PPTX

Смотреть презентацию

Отладочная сборка для Android

Версия 0.14.11 · 17 МБ · от 19.09.2026

Войти и скачать

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

Сборка отладочная и подписана отладочным ключом: Android спросит разрешение на установку из неизвестного источника. В магазины такая сборка не выкладывается.

Зачем это нужно

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

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

Одно приложение, четыре роли

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

01

Клиент

родитель или взрослый пловец

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

02

Тренер

на бортике, с телефоном

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

03

Администратор и владелец

за стойкой и над ней

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

Правило вместо разговора

Спор о восстановлении занятий — самая частая причина, по которой владельца отвлекают. Здесь он решается предъявлением фактов: каждое возвращённое занятие — отдельная строка в базе, у которой есть источник и срок.

вернули занятие от 16 августа (группа «Волна»),
использовать до 4 октября

Видно, какое занятие пропущено, по какой справке возвращено и куда потрачено. Одно занятие возвращается один раз: повторная загрузка справки за тот же период баланс не удваивает.

Отмена работает так же прозрачно: предупредил заранее — занятие вернулось, предупредил за полчаса — сгорело, и приложение прямо пишет почему. Порог задаётся владельцем, а не зашит в код.

Что видит владелец

Два веб-экрана. Рабочий кабинет — светлый, для ежедневной работы. Аналитическая панель — тёмная, для решений: её смотрят вечером и на большом экране.

Загрузка чаши

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

Деньги

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

Люди

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

Качество

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

Решения внутри

Отметка — единственный первичный факт

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

Занятия материализуются заранее

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

Уведомления не задваиваются

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

Пуши без SDK

Отправка идёт через FCM HTTP v1 напрямую: сервисный аккаунт подписывает JWT, тот меняется на токен доступа, дальше обычный HTTP-запрос. Официальный SDK тянет gRPC и полтора десятка зависимостей ради двух запросов. Без ключей Firebase сервер работает и пишет уведомления в лог — на машине разработчика ключей нет, и падать из-за этого нельзя.

Тональность отзывов считается на сервере

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

Роль решает токен, а не сборка

Сначала приложений было три — по флейвору на роль. На Android это работало, но не проходит в App Store: правило 4.3 отклоняет приложения одного разработчика, различающиеся только ролью. Свели в одно, и заодно исчезла ошибка, которую нельзя было исправить изнутри: тренер, скачавший клиентскую сборку, упирался в отказ на входе с советом поставить другое приложение.

Границы

Это первая версия, и часть работы сознательно оставлена на следующий этап — не потому, что её сложно написать, а потому, что она упирается не в код.

  • Онлайн-оплата и чеки по 54-ФЗ. Абонемент выдаёт администратор, платёж фиксируется в базе. Эквайринг требует договора с банком и кассы, а не кода вслепую.
  • Интеграции с кассой и CRM. В настройках есть переключатели и место под реквизиты, самих интеграций нет: они зависят от того, какой ОФД и какая CRM у конкретного бассейна.
  • Хранилище файлов справок. Клиент передаёт ссылку на фото. Где физически лежат персональные данные — решение владельца, а не разработчика.
  • Лист ожидания и догрузка пустых слотов. Свободные места уже считаются, логика предложения места — отдельная работа.

Сборка ниже подключена к демонстрационному серверу pool.dolganov-soft.ru. Вход — по номеру телефона и паролю, их выдаёт администратор бассейна; SMS-шлюза на стенде нет и не обещается. Кабинет администратора и владельца открывается в браузере: кабинет и аналитика.

Нужно похожее?

Опишите задачу в двух строках — отвечу в течение рабочего дня. Исходный код этого проекта и демо покажу по запросу.

Обсудить задачу Другие проекты