Yandex Metrika
sanches.free 1 просмотр

Ограничения служб доставки в интернет‑магазине Битрикс на D7

Зачем нужны ограничения доставки

При работе интернет‑магазина часто нужно исключить курьерку для тяжёлого тарифа, отключить ПВЗ за пределами обслуживаемой области или привязать способ отправки к выбранной оплате. В платформе на D7 эти условия оформляются как ограничения службы доставки: платформа последовательно запускает зарегистрированные проверки и отбрасывает вариант, который не прошёл правило.

В коробке уже есть ограничения по местоположению, весу, стоимости и ряду смежных сценариев. Если бизнесу нужно нестандартное условие, его добавляют отдельным PHP‑классом и включают в реестр обработчиков событием onSaleDeliveryRestrictionsClassNamesBuildList.

Регистрация класса ограничения

Событию передаётся карта «полное имя класса → путь к файлу от корня сайта». Путь должен реально существовать; удобно положить реализацию в /local/lib/... и подключать автозагрузкой Composer или через явный require_once до срабатывания цепочки ограничений.

use Bitrix\Main\EventManager;
use Bitrix\Main\EventResult;

EventManager::getInstance()->addEventHandler(
    'sale',
    'onSaleDeliveryRestrictionsClassNamesBuildList',
    static function (): EventResult {
        return new EventResult(
            EventResult::SUCCESS,
            [
                \Fulfillment\RouteGuard\SlotAvailabilityRule::class
                    => '/local/lib/Fulfillment/RouteGuard/SlotAvailabilityRule.php',
            ]
        );
    }
);

Минимальный каркас на Base

Точкой расширения служит абстрактный предок \Bitrix\Sale\Delivery\Restrictions\Base. Полезные ориентиры можно подсмотреть в каталоге /bitrix/modules/sale/lib/delivery/restrictions/, но для собственной логики достаточно переопределить перечисленные ниже статические методы.

  • getClassTitle и getClassDescription задают текст в интерфейсе администрирования.
  • extractParams готовит срез данных из активной отгрузки перед проверкой.
  • getParamsStructure описывает поля конфигурации ограничения в административной форме.
  • check сравнивает то, что вернул extractParams, с параметрами, сохранёнными для конкретной службы.
namespace Fulfillment\RouteGuard;

use Bitrix\Sale\Shipment;
use Bitrix\Sale\Delivery\Restrictions\Base;

final class SlotAvailabilityRule extends Base
{
    public static function getClassTitle(): string
    {
        return 'Отбор слота перед отгрузкой';
    }

    public static function getClassDescription(): string
    {
        return 'Сравнивает выбранные оплату и вес отправления с сохранёнными порогами.';
    }

    protected static function extractParams(Shipment $shipment)
    {
        return null;
    }

    public static function getParamsStructure($deliverySvcId = 0): array
    {
        return [];
    }

    public static function check($payload, array $ruleConfig, $deliverySvcId = 0)
    {
        return true;
    }
}

Извлекаем контекст из отгрузки

Методу extractParams передаётся \Bitrix\Sale\Shipment участвующего в расчёте экземпляра. По коллекции позиций отгрузки можно пройти товары корзины, подняться к заказу и прочитать оплаты, свойства получателя или произвольные данные складской интеграции. Если проверке ничего не нужно из заказа, допустимо вернуть null или скаляр. Подробнее об объектах см. заметки о корзине и о заказе на D7.

protected static function extractParams(Shipment $shipment)
{
    $payload = [
        'paySystemHandles' => [],
    ];

    foreach ($shipment->getShipmentItemCollection() as $line) {
        $basketRow = $line->getBasketItem();
        if ($basketRow && $basketRow->getProductId() > 0) {
            $payload['sampleProductId'] = (int)$basketRow->getProductId();
        }
    }

    $order = $shipment->getCollection()->getOrder();
    foreach ($order->getPaymentCollection() as $payment) {
        $payload['paySystemHandles'][] = (int)$payment->getPaymentSystemId();
    }

    return $payload;
}

Настройки в админке и проверка

getParamsStructure возвращает массив описаний полей. Типы вроде Y/N, ENUM и NUMBER превращаются в переключатели, списки и числовые вводы. Пустой массив означает «ограничение без ручных параметров».

В check первый аргумент — результат extractParams, второй — сохранённые значения из формы, третий — идентификатор службы доставки. Возвращайте true, если способ разрешён. Для не тестовых сценариев полезно явно игнорировать служебные вызовы с некорректным $deliverySvcId.

public static function getParamsStructure($deliverySvcId = 0): array
{
    return [
        'RQ_SLOT_ACK' => [
            'TYPE' => 'Y/N',
            'VALUE' => 'Y',
            'LABEL' => 'Требовать подтверждённое окно доставки',
        ],
        'RQ_PAY_SYSTEM_UID' => [
            'TYPE' => 'NUMBER',
            'DEFAULT' => '0',
            'MIN' => 0,
            'LABEL' => 'ID платёжной системы-спутника',
        ],
        'RQ_HUB_TAGS' => [
            'TYPE' => 'ENUM',
            'MULTIPLE' => 'Y',
            'OPTIONS' => [11 => 'Север', 19 => 'Юг'],
            'LABEL' => 'Разрешённые узлы распределения',
        ],
    ];
}

public static function check($payload, array $ruleConfig, $deliverySvcId = 0)
{
    if ((int)$deliverySvcId <= 0) {
        return true;
    }

    $wantedPay = (int)($ruleConfig['RQ_PAY_SYSTEM_UID'] ?? 0);
    if ($wantedPay > 0) {
        $handles = is_array($payload['paySystemHandles'] ?? null) ? $payload['paySystemHandles'] : [];
        if (!in_array($wantedPay, $handles, true)) {
            return false;
        }
    }

    return ($ruleConfig['RQ_SLOT_ACK'] ?? 'N') === 'Y';
}

Порядок проверки и хранилище параметров

Статическое свойство $easeSort задаёт очередность: чем значение выше, тем позже выполняется правило (по умолчанию 100). Практичная градация: 100 для лёгких сравнений полей без БД, 200 там, где нужны простые запросы, и 300+ для тяжёлых расчётов.

Если стандартного хранилища параметров недостаточно, переопределяют prepareParamsValues, save и delete — именно этим механизмом платформа совмещает новое ограничение по местоположениям со старыми таблицами совместимости.

Сценарий «все регионы, кроме списка»

Для узких зон исключений иногда нужна инверсия стандартного правила локаций: связь между службой и деревом регионов уже учитывает выбранные узлы через DeliveryLocationTable, а бизнесу достаточно разрешить доставку везде, кроме перечисленных кодов. Реализуется это дополнением к extractParams, которое читает символьный код местоположения из свойства заказа доставки, и проверкой, инвертирующей результат DeliveryLocationTable::checkConnectionExists. После сохранения настройки обычно синхронизируют методом prepareParamsForSaving, а при удалении очищают собственную таблицу или вызывают resetMultipleForOwner, если данные живут во встроенном контуре связей службы.

Итого

  • Кастомные ограничения подключаются событием onSaleDeliveryRestrictionsClassNamesBuildList.
  • Класс наследует Base: отделяйте сбор фактов заказа (extractParams) от бизнес‑условия (check).
  • Используйте $easeSort, чтобы дорогие проверки выполнялись после дешёвых.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии