Налаштування інформації про режим роботи магазинів 1С-Bitrix
Користувач бачить кнопку «Самовивіз» та переходить до списку точок. Біля кожної адреси — нічого про години роботи, або ще гірше: статичний текст «Пн-Пт 9:00-18:00», який актуальний рівно до першої зміни, але ніхто не знає, в якому файлі його міняти. Завдання — зберігати режим роботи у структурованому вигляді та показувати актуальний статус «відкрито/закрито» в реальному часі.
Структура зберігання розпису
Стандартна таблиця b_sale_store містить поле SCHEDULE типу TEXT — довільна строка без структури. Для машинної обробки це не підходить.
Правильний підхід: зберігати розпис у JSON. Або додати користувацьке поле до торгової точки (через CUserTypeEntity з ENTITY_ID = 'SALE_STORE'), або створити окрему таблицю:
CREATE TABLE bl_store_schedule (
id SERIAL PRIMARY KEY,
store_id INT NOT NULL REFERENCES b_sale_store(ID) ON DELETE CASCADE,
day_of_week SMALLINT NOT NULL, -- 1=Пн, 7=Вс
open_time TIME, -- NULL = закрито в цей день
close_time TIME,
is_closed BOOLEAN DEFAULT FALSE,
UNIQUE (store_id, day_of_week)
);
Така структура дозволяє зберігати різний розпис на кожен день тижня та явно помічати вихідні дні через is_closed = TRUE.
Виключення: святи та тимчасові зміни
Крім стандартного розпису потрібна таблиця виключень:
CREATE TABLE bl_store_schedule_exception (
id SERIAL PRIMARY KEY,
store_id INT NOT NULL,
date DATE NOT NULL,
open_time TIME,
close_time TIME,
is_closed BOOLEAN DEFAULT FALSE,
note VARCHAR(255),
UNIQUE (store_id, date)
);
При розрахунку статусу «відкрито/закрито» спершу перевіряємо bl_store_schedule_exception на поточну дату, і тільки при відсутності виключення беремо дані з bl_store_schedule за номером дня тижня.
Розрахунок поточного статусу
function getStoreStatus(int $storeId): array
{
$connection = \Bitrix\Main\Application::getConnection();
$now = new \DateTime('now', new \DateTimeZone('Europe/Minsk'));
$date = $now->format('Y-m-d');
$time = $now->format('H:i:s');
$dow = (int)$now->format('N'); // 1=Пн, 7=Вс
// Спершу перевіряємо виключення на сьогодні
$exception = $connection->query(
"SELECT * FROM bl_store_schedule_exception
WHERE store_id = {$storeId} AND date = '{$date}'"
)->fetch();
$schedule = $exception ?: $connection->query(
"SELECT * FROM bl_store_schedule
WHERE store_id = {$storeId} AND day_of_week = {$dow}"
)->fetch();
if (!$schedule || $schedule['is_closed']) {
return ['status' => 'closed', 'label' => 'Закрито'];
}
$isOpen = $time >= $schedule['open_time'] && $time < $schedule['close_time'];
return [
'status' => $isOpen ? 'open' : 'closed',
'label' => $isOpen
? 'Відкрито до ' . substr($schedule['close_time'], 0, 5)
: 'Відкриється в ' . substr($schedule['open_time'], 0, 5),
'open' => $schedule['open_time'],
'close' => $schedule['close_time'],
];
}
Часові пояси при мережі магазинів
Якщо мережа охоплює кілька часових поясів — додаємо поле timezone в b_sale_store (користувацьке поле або розширення). При розрахунку статусу створюємо DateTime з правильним DateTimeZone для кожного магазину. Зберігати розпис у UTC та конвертувати при відображенні — поширена помилка, яка ломається при переході на літнє/зимове час.
Відображення в компоненті та кешування
Компонент торгових точок bitrix:sale.store.list розширюється через result_modifier.php. В ньому викликаємо getStoreStatus() для кожної точки та додаємо дані в $arResult. Кешування: статус «відкрито/закрито» змінюється двічі на день (відкриття та закриття), тому TTL кеша — не більше 30 хвилин. Можна використовувати теговий кеш з тегом store_{$storeId}_schedule та інвалідувати його при оновленні розпису в адміністративній частині.
Що ми налаштовуємо
- Таблиці
bl_store_scheduleтаbl_store_schedule_exception - Адміністративний інтерфейс для редагування розпису (агент оновлення або форма в адміністративному розділі)
- Функцію розрахунку статусу з підтримкою часових поясів
- Розширення компонента
bitrix:sale.store.listчерезresult_modifier.php - Кешування з TTL 30 хвилин та інвалідацією при зміні розпису







