Перейти к содержимому

События оформления заказа - свои проверки, запрет и допданные

Вмешиваемся в оформление заказа: добавляем свои проверки, дописываем данные и разбираемся, почему обработчик иногда срабатывает не тогда, когда ожидалось.

Решение

Подключаем обработчик события заказа:

use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler('sale', 'OnSaleOrderBeforeSaved',
['\\Vendor\\OrderRules', 'beforeSaved']);
// событие поднимается и при оформлении, и при правке заказа в админке

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

Запрещаем заказ с понятным сообщением:

public static function beforeSaved(\Bitrix\Main\Event $event): \Bitrix\Main\EventResult
{
$order = $event->getParameter('ENTITY');
if ($order->getPrice() < 1000 && $order->getField('DELIVERY_ID') == 3) {
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::ERROR, [
'ERROR' => new \Bitrix\Main\Error('Курьером доставляем от 1000 рублей'),
]);
}
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS);
}

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

Дописываем свои данные до сохранения:

$props = $order->getPropertyCollection();
foreach ($props as $prop) {
if ($prop->getField('CODE') === 'SOURCE') {
$prop->setValue($_COOKIE['utm_source'] ?? 'direct'); // источник заказа
}
}

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

Уносим тяжёлое из оформления:

// в обработчике только пометка, работа - отдельным заданием
CAgent::AddAgent('\\Vendor\\Crm::pushNewOrders();', 'main', 'N', 60);
// вызов внешней системы прямо здесь задержит покупателя на её таймаут
// агент с периодом в минуту разбирает накопленное и переживает отказы сети

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

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

Событие после сохранения годится для уведомлений, а до сохранения - для проверок и правок. Перепутанный порядок даёт знакомую картину: письмо ушло, а заказ не сохранился.

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

Типичные проблемы

Менеджер не может сохранить заказ в админке.

Проверка, написанная для витрины, срабатывает и при правке из административной части. Событие поднимается при любом сохранении заказа, а не только при оформлении.

Покупатель видит пустую страницу вместо сообщения.

В обработчике брошено исключение вместо возврата ошибки. Текст ошибки доходит до формы оформления только через результат события.

Оформление стало долгим.

В обработчике идёт обращение к внешней системе. Оно выполняется в том же запросе и добавляет к ожиданию своё время.

Письмо уходит, а заказа нет.

Уведомление отправляется в событии до сохранения заказа. Для уведомлений берут событие после успешного сохранения.

Позиция добавляется в заказ дважды.

Обработчик не проверяет, сделал ли он это раньше. Заказ пересохраняется при оплате и отгрузке, и код срабатывает заново.

Частые вопросы

Как отличить оформление от правки менеджером?

По признаку нового заказа и по контексту запроса. Проверку для витрины ограничивают публичной частью.

Где регистрировать обработчик?

В файле с обработчиками своего решения. Регистрация в шаблоне страницы работает только на этой странице.

Можно ли поменять сумму заказа в обработчике?

Да, но осторожно: расчёт к этому моменту уже сделан. Надёжнее менять цену позиции правилом корзины.

Что делать, если внешняя система обязательна?

Ставить заказ в очередь и подтверждать позже. Синхронная зависимость от чужой доступности стоит потерянных заказов.

Смежное

Первоисточник