Розробка сайту фітнес-клубу на 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Розробка сайту фітнес-клубу на 1С-Бітрікс
Складна
від 1 тижня до 3 місяців
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Розробка сайту фітнес-клубу на 1С-Бітрікс

Сайт фітнес-клубу — це не вітрина з фотографіями залів. Це робочий інструмент, через який клієнт записується на тренування, купує абонемент, стежить за залишком занять і взаємодіє з тренером. Все це має працювати без ручного втручання адміністратора, синхронізуватися з внутрішніми системами клубу і витримувати пікові навантаження в понеділок вечором, коли половина міста вирішує почати нове життя.

Розберемо, як це реалізується на 1С-Бітрікс — від структури даних до логіки бронювання місць.

Розклад занять: Highload-блоки та фільтрація

Розклад — центральний елемент сайту. Клієнт приходить сюди найчастіше, і якщо розклад гальмує або незручно фільтрується — він йде в Telegram-бот конкурента.

Чому Highload-блок, а не звичайний інфоблок. Звичайний інфоблок (b_iblock_element) зберігає дані в EAV-моделі: кожна властивість — окремий рядок в b_iblock_element_property. При 300 заняттях на тиждень, 15 залах і 40 тренерах таблиця властивостей розростається на десятки тисяч рядків. Фільтрація по комбінації «зал + день + тренер + напрямок» перетворюється на серію JOIN-ів, які на боєвому сервері дають 800-1200 мс.

Highload-блок (b_hlblock_entity) — це плоска таблиця в MySQL/PostgreSQL. Один рядок = одне заняття, усі поля — колонки. Фільтрація працює через звичайні індекси.

Структура Highload-блока FitnessSchedule:

Поле Тип Призначення
UF_DATE date Дата заняття
UF_TIME_START string Початок (формат HH:MM)
UF_TIME_END string Закінчення
UF_HALL_ID integer ID залу (зв'язок з HL FitnessHalls)
UF_TRAINER_ID integer ID тренера (зв'язок з інфоблоком тренерів)
UF_DIRECTION_ID integer Напрямок: йога, кросфіт, басейн...
UF_CAPACITY integer Максимум учасників
UF_BOOKED integer Поточна кількість записаних
UF_STATUS enumeration active / cancelled / full
UF_IS_RECURRING boolean Повторюване за шаблоном
UF_TEMPLATE_ID integer Посилання на шаблон розкладу

Для повторюваних занять створюється окремий Highload-блок ScheduleTemplate з полями дня тижня та часу. Cron-завдання (Bitrix agents або системний cron) раз на тиждень генерує конкретні заняття на наступний тиждень за шаблонами. Це дозволяє тренеру скасувати конкретне заняття 15 березня, не ломаючи весь розклад.

Фільтрація на фронту. Використовуємо Bitrix\Highloadblock\HighloadBlockTable::compileEntity() для отримання ORM-сутності, далі стандартний DataManager::getList() з фільтром:

$result = $entityClass::getList([
    'filter' => [
        'UF_DATE' => $selectedDate,
        'UF_HALL_ID' => $hallId,
        'UF_STATUS' => 'active',
    ],
    'order' => ['UF_TIME_START' => 'ASC'],
]);

На фронті розклад рендирується як сітка: по горизонталі — зали, по вертикалі — часові слоти. Клієнт перемикає день, фільтрує за напрямком або тренером. AJAX-запити через компонент bitrix:highloadblock.list або кастомний REST-ендпоінт.

Онлайн-запис з лімітом місць і waitlist

Запис на заняття — це не просто «натиснув кнопку, потрапив у список». Це транзаційна операція з перевіркою ліміту, конкурентним доступом і механізмом очікування.

Основний сценарій:

  1. Клієнт натискає «Записатися» на конкретному занятті
  2. Система перевіряє: UF_BOOKED < UF_CAPACITY
  3. Якщо так — створює запис у Highload-блоці FitnessBooking, інкрементує UF_BOOKED
  4. Якщо ні — пропонує встати в лист очікування

Проблема конкурентного доступу. Два клієнти одночасно натискають «Записатися» на заняття, де залишилось одне місце. Без блокування обидва отримають підтвердження, а на тренуванні опиниться зайвий чоловік.

Рішення — використання \Bitrix\Main\Application::getConnection() з транзакцією та блокуванням рядка:

$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();

$row = $entityClass::getList([
    'filter' => ['ID' => $scheduleId],
    'select' => ['UF_BOOKED', 'UF_CAPACITY'],
    'runtime' => [/* FOR UPDATE через raw SQL */],
])->fetch();

if ($row['UF_BOOKED'] < $row['UF_CAPACITY']) {
    // створюємо бронювання, інкрементуємо UF_BOOKED
    $connection->commitTransaction();
} else {
    $connection->rollbackTransaction();
    // пропонуємо waitlist
}

На практиці чистий ORM Bitrix не підтримує SELECT ... FOR UPDATE, тому критичну секцію обертаємо в raw SQL через $connection->query().

Лист очікування (waitlist). Окремий Highload-блок FitnessWaitlist з полями: UF_SCHEDULE_ID, UF_USER_ID, UF_POSITION, UF_CREATED_AT. Коли хтось скасує запис, агент Bitrix перевіряє waitlist і автоматично переносить першого в черзі в основний список, відправляючи SMS/push через модуль messageservice.

Скасування запису. Клуб зазвичай дозволяє скасування за 2-4 години до початку. Логіка перевірки часу — в обробнику події, який порівнює UF_TIME_START з поточним часом і блокує скасування, якщо ліміт пройшов.

Продаж абонементів через модуль sale

Абонементи фітнес-клубу — це не товари з каталогу. У них своя логіка: термін дії, кількість відвідувань, заморозка.

Типи абонементів реалізуються як елементи інфоблока «Абонементи» з властивостями:

  • DURATION_DAYS — термін дії в днях
  • VISIT_LIMIT — ліміт відвідувань (0 = безліміт)
  • TYPE — разовий / місячний / річний
  • FREEZE_ALLOWED — можна ли заморожувати
  • FREEZE_MAX_DAYS — максимальний термін заморозки

При покупці через \Bitrix\Sale\Order::create() абонемент додається в кошик як звичайний товар, але після оплати спрацьовує обробник події OnSaleOrderPaid. Він створює запис у Highload-блоці UserSubscription з полями: UF_USER_ID, UF_START_DATE, UF_END_DATE, UF_VISITS_LEFT, UF_IS_FROZEN, UF_FREEZE_START.

Заморозка абонемента. Клієнт у особистому кабінеті натискає «Заморозити». Система перевіряє FREEZE_ALLOWED і FREEZE_MAX_DAYS, встановлює UF_IS_FROZEN = true, зберігає UF_FREEZE_START. При розморожуванні — перераховує UF_END_DATE, додаючи кількість замороженого часу.

Інтеграція з CRM-системами клубу

Фітнес-клуби рідко працюють тільки через сайт. Основні системи обліку — 1С:Фітнес клуб та Mobifitness.

1С:Фітнес клуб. Обмін через стандартний протокол CommerceML або через REST API самого 1С (HTTP-сервіси). Синхронізуються: довідник послуг, розклад, клієнтська база, продажі абонементів. Обмін запускається по cron кожні 15-30 хвилин.

Mobifitness API. REST API з авторизацією по токену. Основні ендпоінти: /api/v1/schedule, /api/v1/bookings, /api/v1/clients. Bitrix виступає фронтендом, Mobifitness — мастер-системою розкладу. В цьому випадку Highload-блок FitnessSchedule заповнюється не вручну, а через синхронізацію з API.

Вибір архітектури залежить від того, яка система є мастер-системою даних. Якщо клуб уже працює в Mobifitness — сайт підтягує розклад звідти. Якщо клуб переходить на цифру з нуля — Bitrix може бути основною системою.

Особистий кабінет клієнта

Особистий кабінет будується на стандартному модулі main (авторизація, профіль) з розширеннями:

  • Історія відвідувань — вибірка з FitnessBooking по UF_USER_ID з JOIN на розклад
  • Залишок занять — поле UF_VISITS_LEFT з UserSubscription
  • Продовження абонемента — кнопка, яка створює замовлення в sale з прив'язкою до поточної підписки
  • Заморозка/розморозка — інтерфейс керування статусом підписки

Авторизація — через телефон з SMS-кодом (модуль messageservice + кастомний компонент). Фітнес-аудиторія не любить паролі.

Профілі тренерів

Тренери — окремий інфоблок з прив'язкою до напрямків через множинну властивість типу «Прив'язка до елементів». Кожен тренер має: фото, сертифікати (файлові властивості), досвід, опис, посилання на розклад (фільтр по UF_TRAINER_ID).

На детальній сторінці тренера його розклад на поточний тиждень автоматично виводиться — один AJAX-запит до FitnessSchedule з фільтром за тренером.

Терміни реалізації

Масштаб проекту Склад Термін
Невеликий клуб (1 зал, 5-7 напрямків) Розклад, запис, абонементи, особистий кабінет 8-10 тижнів
Мережа з 3-5 клубів + мультисайтовість, єдина база, інтеграція з Mobifitness 14-18 тижнів
Велика мережа (10+ клубів) + B2B-портал для корпклієнтів, мобільне додаток через REST API Bitrix, складна тарифікація 20-28 тижнів

На що звернути увагу

Перед розробкою потрібно визначити мастер-систему розкладу: чи буде розклад ведатися в Bitrix або в сторонній CRM. Це визначає напрямок синхронізації та архітектуру Highload-блоків. Друге питання — платіжний шлюз: для абонементів з автоспісанням потрібен еквайринг з підтримкою рекурентних платежів, а це окрема інтеграція через sale.paysystem.