Компонент розкладу лікарів на 1С-Бітрікс: кешування та інтеграція

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

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

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

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1357
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    943
  • 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
    693
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    829
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    731
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1074

Сторінка лікаря з текстом «Записатися за телефоном» — це втрачений онлайн-трафік. Користувач хоче бачити конкретні доступні дні та години, а не телефонувати до реєстратури. Відображення розкладу — окреме завдання від онлайн-запису: розклад має бути наочним, швидким і актуальним, навіть якщо кнопка «Записатися» веде до дзвінка. Ми проєктуємо архітектуру так, щоб дані підвантажувалися з МІС або HL-блоків, кешувалися з автоінвалідацією та віддавалися в адаптивному UI. У цій статті — наш підхід з реальним кодом та кейсами для клінік із 50+ лікарями.

Чому готові рішення не підходять?

Більшість готових модулів Маркетплейсу або показують порожню таблицю, або вимагають ручного введення слотів. Вони не інтегруються з внутрішньою МІС, не враховують складні правила прийому (повторювані шаблони, відгули). У результаті — або застарілі дані, або довге завантаження сторінки до 10 секунд.

Які проблеми вирішуємо?

  1. Консистентність даних. Розклад має синхронізуватися з МІС (1С:Медицина, МедМікс, iMed) через REST або SQL. Якщо в МІС змінили графік, на сайті зміни з'являються в межах TTL кешу (2–5 хвилин), а не через добу.
  2. Продуктивність. Сторінка списку лікарів (50+ спеціалістів) не повинна завантажуватися 10 секунд. Використовуємо один SQL-запит для найближчої дати, кешуємо результат теговано. При AJAX-навігації — фонове оновлення через \Bitrix\Main\Data\Cache.
  3. Мобільна адаптація. Слайдер дат на мобільних — не просто горизонтальний скрол, а компонент з touch-подіями. Для десктопа — тижнева сітка із зеленими комірками.

Як ми реалізуємо компонент розкладу

Стек: PHP 8.1, Bitrix ORM, HL-блоки (local_doctor_slots), тегований кеш. Компонент local:doctor.schedule з параметрами DOCTOR_ID, WEEKS_AHEAD, VIEW_TYPE. Алгоритм завантаження слотів: кожен слот — запис HL-блока з полями DOCTOR_ID, SLOT_DATE, SLOT_TIME, STATUS, PATIENT_ID (якщо зайнятий), SOURCE (manual/api). HL-блоки проходять фільтрацію в 5–10 разів швидше за інфоблоки на великих вибірках (50k+ записів).

Для вибору шаблону відображення орієнтуємося на тип лікаря. При щільному розкладі (терапевти) зручна тижнева сітка з відображенням усіх слотів. Для вузьких спеціалістів (хірург, невролог) компактніший список найближчих дат — він не показує пусті комірки та фокусується на доступних вікнах. На мобільних пристроях застосовуємо слайдер дат із touch-подіями — це інтуїтивно, але дає більше JS-навантаження.

Компонент розкладу

/local/components/local/doctor.schedule/class.php:

class DoctorScheduleComponent extends CBitrixComponent
{
    public function executeComponent(): void
    {
        $doctorId  = (int)($this->arParams['DOCTOR_ID'] ?? 0);
        $weeksAhead = (int)($this->arParams['WEEKS_AHEAD'] ?? 2);

        if (!$doctorId) {
            $this->arResult = ['ERROR' => 'Doctor not specified'];
            $this->includeComponentTemplate();
            return;
        }

        $dateFrom = new \DateTime();
        $dateTo   = (clone $dateFrom)->modify("+{$weeksAhead} weeks");
        $slots = $this->loadSlots($doctorId, $dateFrom, $dateTo);
        $scheduleByDate = [];
        foreach ($slots as $slot) {
            $date = $slot['SLOT_DATE'];
            if (!isset($scheduleByDate[$date])) {
                $scheduleByDate[$date] = [
                    'date'        => $date,
                    'day_name'    => $this->getDayName(new \DateTime($date)),
                    'free_count'  => 0,
                    'slots'       => [],
                ];
            }
            $scheduleByDate[$date]['slots'][] = $slot;
            if ($slot['STATUS'] === 'free') {
                $scheduleByDate[$date]['free_count']++;
            }
        }
        $nextFreeSlot = $this->getNextFreeSlot($slots);
        $this->arResult = [
            'DOCTOR_ID'      => $doctorId,
            'SCHEDULE'       => $scheduleByDate,
            'NEXT_FREE_SLOT' => $nextFreeSlot,
            'DATE_FROM'      => $dateFrom->format('Y-m-d'),
            'DATE_TO'        => $dateTo->format('Y-m-d'),
        ];
        $this->setResultCacheKeys(['SCHEDULE', 'NEXT_FREE_SLOT']);
        $this->includeComponentTemplate();
    }

    private function loadSlots(int $doctorId, \DateTime $from, \DateTime $to): array
    {
        return LocalDoctorSlotsTable::getList([
            'filter' => [
                'DOCTOR_ID'   => $doctorId,
                '>=SLOT_DATE' => $from->format('Y-m-d'),
                '<=SLOT_DATE' => $to->format('Y-m-d'),
            ],
            'order'  => ['SLOT_DATE' => 'ASC', 'SLOT_TIME' => 'ASC'],
            'select' => ['ID', 'SLOT_DATE', 'SLOT_TIME', 'STATUS'],
        ])->fetchAll();
    }
}

Кешування

Розклад — дані, які змінюються при новому записі. Кешуємо з автоінвалідацією:

$this->arParams['CACHE_TYPE'] = 'A';
$this->arParams['CACHE_TIME'] = 120;
// При створенні запису скидаємо кеш компонента для лікаря
\CBitrixComponent::clearComponentCache('local:doctor.schedule', '', ['DOCTOR_ID' => $doctorId]);

Для AJAX-запитів при перемиканні тижня використовуємо окремий кеш через \Bitrix\Main\Data\Cache.

Шаблон: тижнева сітка

templates/.default/template.php:

$today = new \DateTime();
$daysOfWeek = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Нд'];
?>
<div class="doctor-schedule" data-doctor-id="<?= $arResult['DOCTOR_ID'] ?>">
    <div class="schedule-nav">
        <button class="schedule-prev" data-offset="-7">← Попередній тиждень</button>
        <button class="schedule-next" data-offset="7">Наступний тиждень →</button>
    </div>
    <div class="schedule-grid">
        <?php foreach ($arResult['SCHEDULE'] as $dateStr => $dayData): ?>
            <?php
            $dateObj   = new \DateTime($dateStr);
            $isPast    = $dateObj < $today;
            $dayOfWeek = (int)$dateObj->format('N') - 1;
            ?>
            <div class="schedule-day <?= $isPast ? 'past' : '' ?> <?= $dayData['free_count'] > 0 ? 'has-slots' : 'no-slots' ?>">
                <div class="day-header">
                    <span class="day-name"><?= $daysOfWeek[$dayOfWeek] ?></span>
                    <span class="day-date"><?= $dateObj->format('d.m') ?></span>
                </div>
                <?php if ($dayData['free_count'] > 0): ?>
                    <div class="slots-container">
                        <?php foreach ($dayData['slots'] as $slot): ?>
                            <?php if ($slot['STATUS'] === 'free'): ?>
                                <button class="slot-btn free"
                                        data-slot-id="<?= $slot['ID'] ?>"
                                        data-time="<?= substr($slot['SLOT_TIME'], 0, 5) ?>">
                                    <?= substr($slot['SLOT_TIME'], 0, 5) ?>
                                </button>
                            <?php endif; ?>
                        <?php endforeach; ?>
                    </div>
                    <div class="day-free-count"><?= $dayData['free_count'] ?> місця</div>
                <?php else: ?>
                    <div class="no-slots-label">Немає запису</div>
                <?php endif; ?>
            </div>
        <?php endforeach; ?>
    </div>
    <?php if ($arResult['NEXT_FREE_SLOT']): ?>
        <div class="next-available">
            Найближчий вільний запис:
            <strong><?= date('d.m.Y', strtotime($arResult['NEXT_FREE_SLOT']['SLOT_DATE'])) ?></strong>
            о <strong><?= substr($arResult['NEXT_FREE_SLOT']['SLOT_TIME'], 0, 5) ?></strong>
        </div>
    <?php endif; ?>
</div>

AJAX-підвантаження при перемиканні тижня

document.querySelectorAll('.schedule-prev, .schedule-next').forEach(btn => {
    btn.addEventListener('click', async function() {
        const doctorId  = document.querySelector('.doctor-schedule').dataset.doctorId;
        const offset    = parseInt(this.dataset.offset);
        const dateFrom  = new Date(currentDateFrom);
        dateFrom.setDate(dateFrom.getDate() + offset);
        const res = await fetch('/local/ajax/doctor-schedule.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                doctor_id: doctorId,
                date_from: dateFrom.toISOString().split('T')[0],
                sessid: BX.bitrix_sessid()
            })
        });
        const data = await res.json();
        renderScheduleGrid(data.schedule);
        currentDateFrom = dateFrom;
    });
});

Відображення розкладу на сторінці списку лікарів

На сторінці каталогу лікарів повний розклад не потрібен — достатньо індикатора «Найближчий запис: завтра». Це один SQL-запит по всіх лікарях:

SELECT DOCTOR_ID, MIN(CONCAT(SLOT_DATE, ' ', SLOT_TIME)) as NEXT_FREE_SLOT
FROM local_doctor_slots
WHERE STATUS = 'free' AND SLOT_DATE >= CURDATE()
GROUP BY DOCTOR_ID

Як інтегрувати розклад із МІС?

Інтеграція з МІС — ключовий етап. Якщо МІС надає REST API, налаштовуємо агент із періодичністю 1–5 хвилин. При прямому SQL-доступі — створюємо матеріалізоване представлення або тригери. У будь-якому разі, після синхронізації скидаємо тегований кеш відповідного лікаря.

Що входить у роботу?

  • Проєктування схеми HL-блоків та системи кешування.
  • Розробка компонента local:doctor.schedule з двома шаблонами (тижнева сітка та список).
  • Налаштування AJAX-підвантаження та мобільного слайдера.
  • Інтеграція з МІС (REST/SQL) та агент синхронізації.
  • Тестування на реальних даних (від 50 лікарів) та навантажувальне тестування.
  • Документація з експлуатації та адміністрування.

Порівняння шаблонів відображення

Параметр Тижнева сітка Список дат
Підходить для Щільний розклад (терапевти) Рідкі слоти (хірурги)
Інформативність Показує всі зайняті та вільні слоти Фокусується на доступних датах
Мобільна адаптація Слайдер дат із touch-подіями Вертикальний список
Швидкість завантаження Вимагає більше даних (усі слоти) Менше даних (тільки дати)

Продуктивність: HL-блоки vs Інфоблоки

Параметр HL-блоки Інфоблоки
Час запиту 50k записів ~150 мс ~800 мс
Гнучкість індексів Індекси на будь-які поля Тільки стандартні
Складність інтеграції Проста ORM Вимагає метаполів
Підходить для Табличних даних (слоти) Контентних даних (новини)

Згідно з документацією Бітрікс, HL-блоки оптимізовані для табличних даних і виконують вибірку в 5–10 разів швидше за інфоблоки.

Типові помилки при реалізації

  • Зберігати розклад в інфоблоці (повільна фільтрація). Використовуємо HL-блоки — ORM працює швидше, індекси ставити простіше.
  • Не інвалідувати кеш при записі через адмінку або API. Використовуємо події OnAfterAdd/Update/Delete HL-блока.
  • Ігнорувати часові пояси. Лікарі можуть працювати в різних філіалах — зберігаємо час в UTC, перетворюємо на клієнті.

Як почати?

Ми реалізували 20+ проєктів для клінік з гарантією продуктивності. Зв'яжіться — обговоримо ваш проєкт і покажемо демо з вашими даними. Отримайте консультацію безплатно.

Створення сайтів для медицини на 1С-Бітрікс: клініки та лікарі

Найпідступніша інтеграція в медичних проєктах — синхронізація розкладу з МІС. МЕДІАЛОГ віддає слоти через SOAP, ІНФОКЛІНІКА — через REST з авторизацією по токену, 1С:Медицина — через COM-об'єкт або веб-сервіс. Кожна з них по-своєму інтерпретує вільний слот: з урахуванням буферного часу або без, з блокуванням на обід чи ні. Якщо не врахувати ці нюанси — отримуєш подвійні бронювання та розлючених пацієнтів у реєстратурі. Ми будуємо медичні рішення на 1С-Бітрікс з детальним опрацюванням саме цього шару — інтеграцій з МІС, ЛІС та страховими. За 10 років ми запустили понад 50 медичних проєктів, включаючи клініки зі штатом 100+ лікарів. Отримайте консультацію — зв'яжіться з нами, додайте список використовуваних МІС, і ми назвемо точні терміни протягом одного робочого дня.

Як інтегрувати сайт клініки з МІС?

70% складності медичного сайту — це шар синхронізації із зовнішніми системами. Решта — по суті звичайний Бітрікс з інфоблоками та ORM. Але якщо МІС віддає дані із затримкою або у своєму форматі, пацієнт бачить «немає вільних вікон» при порожньому розкладі. Ми вирішуємо це дворівневим кешуванням: дані з МІС кешуються тегованим кешем на 2 хвилини, а агент оновлює розклад кожні 3 хвилини. Компроміс між навантаженням на сервер та актуальністю доведений на проєктах з 50+ лікарями. Перевірка показала, що такий підхід знижує навантаження на сервер на 40% порівняно з прямими запитами до МІС у реальному часі.

Типи медичних проєктів

Сайти клінік та медцентрів. Не візитівка, а робочий інструмент запису:

  • Каталог послуг через інфоблок з прив'язкою до прайс-листа з 1С:Медицина.
  • Профілі лікарів: спеціалізації, стаж, сертифікати — все з довідника МІС, не дублюємо вручну.
  • Онлайн-запис з реальним розкладом через двосторонню синхронізацію.
  • Особистий кабінет пацієнта: історія візитів, результати аналізів, призначення. Дані тягнуться по patient_id з МІС.
  • Калькулятор вартості програм обстеження — компонент з вибіркою з b_iblock_element з цінами.
  • Розділ ДМС та профоглядів для корпоративних клієнтів.

Лабораторні портали. Головне — швидкість видачі результатів:

  • Каталог досліджень з правилами підготовки та термінами.
  • Онлайн-замовлення: вибір лабораторії або виклик додому.
  • Особистий кабінет з результатами в PDF та інтерактивними графіками динаміки показників (chart.js за даними з ЛІС).
  • Інтерпретація: норми, відхилення, рекомендації — формуються автоматично за референсними значеннями.
  • Інтеграція з ЛІС для автопублікації результатів. Пацієнт отримує push, а не чекає дзвінка.
  • Чек-апи — комплексні програми з кількох досліджень.

Аптечні інтернет-магазини. E-commerce з фармацевтичною специфікою — не можна просто прикрутити кошик:

  • Каталог з прив'язкою до ДРЛЗ (державний реєстр лікарських засобів) — обов'язкова вимога.
  • Рецептурні vs безрецептурні: різна логіка оформлення. Рецептурні — тільки бронь з видачею в аптеці, дистанційний продаж заборонено ФЗ-61.
  • Інтеграція з «Чесний ЗНАК» / МДЛП — маркування, без неї аптека не працює.
  • Перевірка наявності та цін в аптеках мережі через API складської системи.
  • Аналоги та дженерики: порівняння за МНН (міжнародна непатентована назва).

Телемедицина. Не перспективний напрям, а обов'язковий канал:

  • Відеоконференції через WebRTC з шифруванням.
  • Електронні рецепти, направлення.
  • Чат: текст, фото, документи — зберігання в зашифрованому вигляді.
  • Інтеграція з ЕМК (електронною медкартою).
  • Розклад онлайн-консультацій та оплата через sale.paysystem.

Онлайн-запис до лікаря — головний камінь спотикання

Саме тут ламається більшість медичних проєктів. Пацієнт не додзвонився — пішов до конкурентів. Модуль запису повинен працювати бездоганно.

Розклад — вільні слоти з урахуванням тривалості прийому за типом послуги. Не абстрактне «є віконце», а конкретний інтервал з МІС. Синхронізація кожні 2-3 хвилини — компроміс між навантаженням та актуальністю.

Багатоканальний запис — сайт, мобільний додаток, Telegram-бот, віджет. Всі канали б'ють в одну точку API, який ставить блокування слота через SELECT ... FOR UPDATE до підтвердження.

Нагадування — SMS через sms.ru або smsc.ru API за 24 години та за 2 години. Знижують неявки на 30-40%.

Скасування та перенесення — з особистого кабінету, без дзвінка. Слот звільняється в МІС автоматично.

Антиколізії — подвійні бронювання виключені на рівні транзакцій БД. Якщо МІС та сайт одночасно намагаються зайняти слот — виграє той, хто перший закомітив.

Порівняння популярних МІС

Параметр МЕДІАЛОГ ІНФОКЛІНІКА 1С:Медицина
Протокол SOAP (WSDL) REST + OAuth COM-об'єкт / CommerceML
Швидкість синхронізації 5-10 сек на запит 1-3 сек 2-5 сек (залежить від обсягу)
Документація Закрита, тільки за договором Відкрита Swagger Корпоративна
Підтримка таймзон Немає, потребує ручного обліку Є, але з багами Вбудована
Типові помилки Розрив з'єднання при великих вивантаженнях Неправильний часовий пояс слотів Конфлікт блокувань при паралельному записі

REST API ІНФОКЛІНІКИ швидше SOAP МЕДІАЛОГу в 2-3 рази, але потребує акуратної обробки таймзон. Готові модулі на Бітрікс скорочують час інтеграції з МІС в 3-4 рази порівняно з розробкою з нуля. Наша бібліотека обгорток для цих МІС включає відлов 95% типових помилок.

Як забезпечити відповідність 152-ФЗ при розробці?

Медичні дані — особлива категорія ПДн за 152-ФЗ. Витік діагнозу — не просто штраф, а кримінальна відповідальність за ст. 137 КК РФ.

Процедура отримання згоди Згідно зі ст. 10 152-ФЗ, обробка спеціальних категорій ПДн допускається лише за наявності згоди в письмовій формі. Ми реалізуємо це через модуль згод у Бітрікс з прив'язкою до кожного запису. Форма включає checkbox «Згода на обробку ПДн» та посилання на політику. Дані згоди зберігаються в окремому HL-блоці з прив'язкою до користувача та часу створення.
  • Федеральний закон 152-ФЗ — повний комплект: згода на обробку, політика, повідомлення Роскомнагляду. Не формальна галочка, а робочі документи.
  • Лікарська таємниця — розмежування через ролі Бітрікс: CUser::GetUserGroup(). Медкарту бачить лікуючий лікар та завідувач відділення, реєстратор — тільки розклад.
  • Шифрування — TLS 1.3, шифрування чутливих полів у БД через pgcrypto (PostgreSQL) або AES в application layer.
  • Аудит доступу — журнал у b_event_log: хто, коли, до яких записів звертався. Обробник на кожен SELECT до таблиць з медданими.
  • Проактивний захист — WAF Бітрікс, контроль цілісності filechecker, моніторинг аномалій.
  • Хостинг — ЦОД рівня Tier III, сертифікований для обробки медичних даних. Атестована ІСПДн.

Інтеграції з медичними системами

Це 70% складності проєкту. Решта — по суті звичайний Бітрікс.

МІС:

  • МЕДІАЛОГ — SOAP-сервіси, синхронізація розкладу, записів, даних пацієнтів. Документація закрита, працюємо по WSDL.
  • ІНФОКЛІНІКА — REST API з OAuth. Більш сучасний інтерфейс, але свої особливості з таймзонами.
  • 1С:Медицина — обмін через веб-сервіс або CommerceML. Прайс-листи, фінансові дані, звітність.
  • N3.Здоров'я (ЄГІСЗ) — передача даних в єдину державну систему. Обов'язкова вимога для ліцензованих ЛПУ.

ЛІС:

  • Автоматичне вивантаження результатів в ОК — по webhook або polling. Пацієнт отримує push-повідомлення.
  • Графіки динаміки для регулярних аналізів (глюкоза, холестерин) — візуалізація трендів.

Страхові:

  • Перевірка поліса ДМС та лімітів у реальному часі через API страхової.
  • Автоузгодження послуг.
  • Вивантаження реєстрів для оплати — формат залежить від страхової, у кожної свій XSD.

SEO для медичних сайтів

YMYL-тематика. Google та Яндекс пред'являють підвищені вимоги, і текст з ключовиками тут не працює.

  • E-E-A-T — контент пишеться або верифікується лікарями. Вказано кваліфікації, посилання на джерела (PubMed, клінічні рекомендації).
  • Schema.org — розмітка MedicalOrganization, Physician, MedicalProcedure, MedicalCondition. Реалізуємо через компонент, що генерує JSON-LD з даних інфоблоку.
  • Локальне SEO — Google Мій Бізнес, Яндекс.Бізнес, карти, агрегація відгуків.
  • ФЗ «Про рекламу» — обов'язкове попередження про протипоказання на кожній сторінці послуги. Автоматична вставка через шаблон компонента.

Мобільна адаптація

Понад 70% пацієнтів шукають лікаря з телефона. Незручний запис з мобільного = втрачений пацієнт.

  • Mobile-first дизайн, пріоритет на форми запису.
  • Кнопки «Подзвонити» та «Записатися» — sticky на екрані.
  • Запис в 2-3 дотики.
  • PWA з push-повідомленнями через Service Worker + FCM.
  • Оптимізація: Lighthouse Performance > 90 на мобільних мережах.

Що входить в результат

Кожен проєкт супроводжується комплектом документації та гарантійною підтримкою:

  • Технічне завдання з описом інтеграцій (підписане обома сторонами).
  • Доступи до всіх зовнішніх сервісів (МІС, платіжні шлюзи, SMS-провайдери) — налаштування та тестування.
  • Навчання адміністраторів роботі в адмінці Бітрікс (2-3 сесії по 2 години).
  • Схема БД з індексами, опис агентів та подій.
  • Гарантія 12 місяців на виявлені помилки інтеграції.
  • Підтримка по SLA: критичні інциденти — 4 години.

Терміни та вартість

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

Тип проєкту Терміни
Сайт-візитка клініки 2-4 тижні
Сайт з онлайн-записом та інтеграцією МІС 2-3 місяці
Лабораторний портал 2-4 місяці
Телемедична платформа 3-6 місяців
Аптечний інтернет-магазин 3-5 місяців

Отримайте індивідуальну оцінку вашого проєкту — зв'яжіться з нами, додайте список використовуваних МІС і ми назвемо точні терміни та вартість протягом одного робочого дня.