Если вы работаете с шаблонами Аспро, то наверняка знаете, как легко добавлять простые текстовые поля в форму быстрого заказа через настройки модуля (например, ФИО или Адрес). Но что делать, если нужно добавить свойство заказа с типом «Дата/Время»?
Стандартный интерфейс настроек Аспро такие поля просто «не видит». В этой статье мы шаг за шагом разберем, как вывести красивый нативный календарь в форму «Заказ в 1 клик», как заблокировать выбор прошедших дат (и отсекать сегодняшний день после 18:30), а затем корректно сохранить эти данные в заказ и отправить в письме.
Что нам понадобится
- Доступ к файлам сайта (желательно через FTP/SFTP).
- Кастомное свойство заказа Битрикса (в нашем случае это
DATE_DELIVERY).
- Базовое понимание структуры компонентов Битрикс.
Шаг 1. Выводим поле в форму (HTML + JS)
Для начала нам нужно кастомизировать визуальный шаблон всплывающей формы.
Важно: Всегда старайтесь работать в папке /local/, чтобы при обновлении ядра Аспро ваши изменения не затерлись.
Файл для редактирования: /local/components/aspro/oneclickbuy.premier/templates/.default/template.php (Если у вас нет папки local, то путь будет начинаться с /bitrix/components/...)
Находим цикл, который выводит стандартные поля (ищем строку <?endforeach;?> примерно на 106-й строке), и сразу после него вставляем наш блок:
<div class="row" data-sid="DATE_DELIVERY">
<div class="col-md-12">
<div class="form-group fill-animate">
<label class="font_13" for="one_click_buy_id_DATE_DELIVERY">
<span>Время доставки</span>
</label>
<div class="input">
<input
type="datetime-local"
name="ONE_CLICK_BUY[DATE_DELIVERY]"
value=""
class="form-control inputtext"
id="one_click_buy_id_DATE_DELIVERY"
required
/>
</div>
</div>
</div>
</div>
<script type="text/javascript">
// Ограничение выбора даты доставки
(function() {
var dateInput = document.getElementById('one_click_buy_id_DATE_DELIVERY');
if (!dateInput) return;
var now = new Date();
var hours = now.getHours();
var minutes = now.getMinutes();
// Определяем минимально доступную дату
var minDate = new Date(now);
// Если время вышло (> 18:30), блокируем сегодня, переносим мин. дату на завтра
var isAfterCutoff = (hours > 18) || (hours === 18 && minutes >= 30);
if (isAfterCutoff) {
minDate.setDate(minDate.getDate() + 1);
}
// Форматируем для атрибута min="YYYY-MM-DDThh:mm"
var yyyy = minDate.getFullYear();
var mm = String(minDate.getMonth() + 1).padStart(2, '0');
var dd = String(minDate.getDate()).padStart(2, '0');
// Ставим 00:00, чтобы в разрешенный день можно было выбрать любое время
dateInput.setAttribute('min', yyyy + '-' + mm + '-' + dd + 'T00:00');
// Обработчик, если пользователь попытается ввести дату с клавиатуры в обход календаря
dateInput.addEventListener('change', function() {
if (!this.value) return;
var selectedDate = new Date(this.value);
selectedDate.setHours(0, 0, 0, 0); // Сравниваем только дни
var checkMinDate = new Date(minDate);
checkMinDate.setHours(0, 0, 0, 0);
// Если выбранная дата меньше минимально разрешенной
if (selectedDate.getTime() < checkMinDate.getTime()) {
var today = new Date(now);
today.setHours(0, 0, 0, 0);
if (selectedDate.getTime() === today.getTime() && isAfterCutoff) {
alert('Доставка на сегодня больше не доступна (заказы принимаются до 18:30). Пожалуйста, выберите другую дату.');
} else {
alert('Эта дата недоступна. Пожалуйста, выберите другое число.');
}
this.value = ''; // Принудительно очищаем поле
}
});
})();
</script>
Почему datetime-local? Использование нативного HTML5-поля гарантирует, что на смартфонах у клиента откроется удобный системный «барабан» выбора даты и времени (в iOS или Android), что значительно повышает конверсию по сравнению с мелкими скриптовыми календариками.
Шаг 2. Обработка и сохранение данных (PHP)
Браузер отдает дату в формате YYYY-MM-DDThh:mm (например, 2026-03-20T15:25). Битрикс этот формат не понимает и ждет классический DD.MM.YYYY HH:MI. Значит, нам нужно конвертировать дату «на лету» и сохранить её в свойства заказа.
Файл для редактирования: /local/components/aspro/oneclickbuy.premier/script.php
Открываем этот файл и ищем место, где перебираются и сохраняются свойства заказа (обычно это ближе к концу файла, цикл while($prop = $res->Fetch())).
Сразу ПОСЛЕ этого цикла вставляем следующий код:
// --- ПРЕОБРАЗОВАНИЕ ФОРМАТА ДАТЫ ---
if(!empty($_POST['ONE_CLICK_BUY']['DATE_DELIVERY'])){
// 1. Убираем букву T, заменяя ее на обычный пробел
$cleanDate = str_replace('T', ' ', $_POST['ONE_CLICK_BUY']['DATE_DELIVERY']);
// 2. Превращаем 2026-03-20 15:25 в красивый русский формат 20.03.2026 15:25
$timestamp = strtotime($cleanDate);
if($timestamp){
$_POST['ONE_CLICK_BUY']['DATE_DELIVERY'] = date('d.m.Y H:i', $timestamp);
} else {
// Если strtotime вдруг не отработал, сохраняем просто без буквы T
$_POST['ONE_CLICK_BUY']['DATE_DELIVERY'] = $cleanDate;
}
}
// -----------------------------------
// Принудительно сохраняем кастомное поле DATE_DELIVERY в свойства заказа
if(!empty($_POST['ONE_CLICK_BUY']['DATE_DELIVERY'])){
$dbProp = CSaleOrderProps::GetList(array(), array('CODE' => 'DATE_DELIVERY', 'PERSON_TYPE_ID' => $personType));
if($prop = $dbProp->Fetch()){
$dbP = CSaleOrderPropsValue::GetList(Array(),array('ORDER_ID' => $orderID, 'ORDER_PROPS_ID' => $prop['ID']));
if($arP = $dbP->Fetch()){
CSaleOrderPropsValue::Update($arP['ID'], array( 'VALUE' => htmlspecialcharsbx($_POST['ONE_CLICK_BUY']['DATE_DELIVERY'])));
}else{
CSaleOrderPropsValue::Add(array('ORDER_ID' => $orderID, 'NAME' => $prop['NAME'], 'ORDER_PROPS_ID' => $prop['ID'], 'CODE' => $prop['CODE'], 'VALUE' => htmlspecialcharsbx($_POST['ONE_CLICK_BUY']['DATE_DELIVERY'])));
}
}
}
// Конец принудительно сохраняем кастомное поле DATE_DELIVERY в свойства заказа
Шаг 3. Отправка даты в почтовом уведомлении
Последний штрих — нужно передать отформатированную дату в шаблон письма, которое отправляется администратору и клиенту.
В этом же файле script.php спускаемся чуть ниже до формирования массива $arMessageFields. Добавляем туда нашу новую переменную:
Нет комментариев