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

Стандартный набор ограничений службы доставки

Из коробки 1С Битрикс «Управление сайтом» предоставляет следующий набор ограничений:

  • Исключить по местоположению
  • По весу
  • По группам пользователей
  • По категории товара
  • По товарам
  • По максимальному размеру
  • По максимальным размерам
  • По общей стоимости товаров
  • По платёжным системам
  • По публичной части
  • По типу плательщика

Ограничения служб доставки    

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

Собственный класс ограничений

Для реализации ограничения, вам необходимо унаследовать свой класс от базового класса Bitrix\Sale\Delivery\Restrictions\Base системы. Однако вы так же можете наследоваться от существующих классов ограничений из папки /bitrix/modules/sale/lib/delivery/restrictions/ . И так, минимальный набор методов класса ограничений выглядит так: 


namespace Lib\Restrictions;

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

/**
 * Ограничние по свойство товара
 */
class ProductPropertyXRestriction extends Base
{
    /**
     * Название ограничения
     * @return string
     */
    public static function getClassTitle()
    {
        return 'ограничение по свойству товара';
    }

    /**
     * Описание ограничения
     * @return string
     */
    public static function getClassDescription()
    {
        return 'Если у товара задано свойство «X», вы не можете использовать эту службу доставки';
    }


    /**
     * Метод получения необходимых для проверки ограничения данных
     * @param Bitrix\Sale\Shipment $shipment
     * @return null
     */
    protected static function extractParams(CollectableEntity $shipment)
    {
        return null;
    }

    /**
     * Массив параметров ограничения, на его основе строиться форма в админке
     * @param $deliveryId
     * @return array
     */
    public static function getParamsStructure($deliveryId = 0)
    {
        return [];
    }

    /**
     * Основная функция проверки наступления условия ограничения
     * @param $shipmentParams
     * @param array $restrictionParams
     * @param $deliveryId
     * @return bool
     */
    public static function check($shipmentParams, array $restrictionParams, $deliveryId = 0)
    {
        return true;
    }
}

В качестве примера, сделаем проверку на наличие у товара корзины, какого-нибудь свойства, например свойство типа "Хрупкий товар", допустим хрупкий товар можно возить только курьером компании.

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

Хрупкий товар

Свойство типа "Список" имеет одно значение "Да" с мнемоническим кодом "Y".

Хрупкий товар, настройки свойтсва

Запомним код свойства DELICATE_PRODUCT, оно потребуется для проверки товаров. Давайте сразу же проставим одному из товаров это свойство. Перейдём к торговым предложениям, выведем свойство в список, чтобы не пришлось проваливаться в каждое ТП отдельно.

Список торговых предложений товара

Жмём на шестерёнку в верхнем правом углу списка. Перейдём к настройкам, найдём наше свойство, переместим его в правую колонку и сохраним настройки списка.

Свойство хрупкий товар

Теперь свойство доступно в списке и можно отредактировать его прямо отсуюда.

Ставим свойство торговым предложениям

Подготовка выполнена, давайте займёмся классом ограничения.

Подключение и использование

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

Пример сткруты файлов и папок отвечающих за подключение собственных классов я приводил в этой статье раздел «Подготовка init.php и пространства имён». В целом можно воспользоваться такой же схемой. Т.е. собственные классы в папке /local/php_interface/lib/ с пространством имён lib , а так же файл init.php с подключением констант, файла автозагрузки классов и обработчика событий:


<?php

//Константы
require dirname(__FILE__) . '/constants.php';

//Автозагрузка классов
require dirname(__FILE__) . '/autoload.php';

//Обработка событий
require dirname(__FILE__) . '/event_handler.php';


/**
 * обёртка для print_r() и var_dump()
 * @param $val - значение
 * @param string $name - заголовок
 * @param bool $mode - использовать var_dump() или print_r()
 * @param bool $die - использовать die() после вывода
 */
function print_p($val, $name = 'Содержимое переменной', $mode = false, $die = false){
    global $USER;
    if($USER->IsAdmin()){
        echo '<pre>'.(!empty($name) ? $name.': ' : ''); if($mode) { var_dump($val); } else { print_r($val); } echo '</pre>';
        if($die) die;
    }
}

Функцию print_p() я часто использую для отладки, поэтому оставлю её тут по умолчанию.

Получаем такую структуру папки local:

Папка local

Файл constants.php

Тут пока путь к корню папки с пользовательскими классами


<?

//Папка с пользовательскими классами
define('APP_CLASS_FOLDER', '/local/Lib/');

Файл autoload.php

Тут битриксовая «автозагрузка» классов


<?

use Bitrix\Main\Loader;

//Автозагрузка наших классов
Loader::registerAutoLoadClasses(null, [
    'Lib\Restrictions\ProductPropertyXRestriction' => APP_CLASS_FOLDER . 'Restrictions/ProductPropertyXRestriction.php'
]);

Файл event_handler.php

Для подключения своего ограничения в событии onSaleDeliveryRestrictionsClassNamesBuildList нужно вызвать функцию которая вернёт объект \Bitrix\Main\EventResult

<?

use Bitrix\Main;
$eventManager = Main\EventManager::getInstance();

$eventManager->addEventHandler(
    'sale',
    'onSaleDeliveryRestrictionsClassNamesBuildList',
    'ProductPropertyXDeliveryRestriction'
);

function ProductPropertyXDeliveryRestriction()
{
    return new \Bitrix\Main\EventResult(
        \Bitrix\Main\EventResult::SUCCESS,
        [
            'Lib\Restrictions\ProductPropertyXRestriction' => APP_CLASS_FOLDER . 'Restrictions/ProductPropertyXRestriction.php',
        ]
    );
}
Если всё сделано верно и с путями нигде не напутали, то в настройках любой службы доставки появиться наше ограничение.

Ограничение доставки

Пока оно бесполезно. Чтобы оно полноценно заработало, нужно доделать несколько методов.

Проверка основного условия

Для проверки нам потребуется создать вспомогательный метод getDelicateProductId() который вернёт массив идентификаторов всех торговых предложений, имеющих флаг "Хрупкий товар", он потребуется для проверки содержимого корзины. А так же дополним методы getParamsStructure()extractParams() и главный метод check().


<?php

namespace Lib\Restrictions;

use \Bitrix\Sale\Delivery\Restrictions\Base;
use \Bitrix\Sale\Internals\CollectableEntity;
use \Bitrix\Sale\Shipment;
/**
 * Ограничние по свойство товара
 */
class ProductPropertyXRestriction extends Base
{
    /**
     * Название ограничения
     * @return string
     */
    public static function getClassTitle()
    {
        return 'ограничение по свойству товара';
    }

    /**
     * Описание ограничения
     * @return string
     */
    public static function getClassDescription()
    {
        return 'Если у товара задано свойство «X», вы не можете использовать эту службу доставки';
    }


    /**
     * Метод получаения необходимых для проверкм ограничения данных
     * в данном случае мы получаем флаг, имеются ли в корзине товары с отмеченным флагом "Хрупкий товар"
     * @param Bitrix\Sale\Shipment $shipment
     * @return null
     */
    protected static function extractParams(CollectableEntity $entity)
    {

        if ($entity instanceof Shipment)
        {
            $basketHasDelicateProducts = false;
            $aeDelicateProductId = self::getDelicateProductId();

            $collection = $entity->getCollection();
            $order = $collection->getOrder();
            $basket = $order->getBasket();

            foreach ($basket as $basketItem) {
                if(in_array($basketItem->getProductId(), $aeDelicateProductId)){
                    $basketHasDelicateProducts = true;
                }
            }

            return $basketHasDelicateProducts;

        } else {
            return -1;
        }

        return 0;
    }

    /**
     * Массив параметров ограничения, на его основе строиться форма в админке
     * @param $deliveryId
     * @return array
     */
    public static function getParamsStructure($deliveryId = 0)
    {
        return [
            'HAS_DELICATE' => [
                'TYPE' => 'Y/N',
                'DEFAULT' => 'Y',
                'LABEL' => 'Запретить службу доставки для хрупких товаров'
            ],
        ];
    }

    /**
     * Основная функция проверки наступления условия ограничения
     * @param $shipmentParams - результат extractParams()
     * @param array $restrictionParams - значение параметра описанного в getParamsStructure()
     * @param $deliveryId
     * @return bool
     */
    public static function check($shipmentParams, array $restrictionParams, $deliveryId = 0)
    {
        $result = true;

        //Стоит флаг "Запретить службу доставки для хрупких товаров" и в корзине есть хрупкий товар (параметр $shipmentParams)
        if($restrictionParams['HAS_DELICATE']=='Y' && $shipmentParams == true){
            //Службу доставки использовать нельзя
            $result = false;
        }

        //Стоит флаг "Запретить службу доставки для хрупких товаров" и в корзине НЕТ хрупких товаров
        if($restrictionParams['HAS_DELICATE']=='Y' && $shipmentParams == false){
            //Службу доставки использовать можно
            $result = true;
        }

        return $result;
    }

    /**
     * Получим массив, всех торговых предложений относящихся к хрупким товарам
     * @return array
     */
    private static function getDelicateProductId()
    {
        $delicateProductId = [];
        $arFilter = ['IBLOCK_ID'=>IB_CATALOG_SKU, '!PROPERTY_DELICATE_PRODUCT'=>false];
        $res = \CIBlockElement::GetList(['ID'=>'ASC'], $arFilter, false, false, ['ID']);
        while($ob = $res->GetNextElement()){
            $arFields = $ob->GetFields();
            $delicateProductId[] = $arFields['ID'];
        }

        return $delicateProductId;
    }
}


Обратите внимание в методе getDelicateProductId() добавлена константа IB_CATALOG_SKU заранее заведённая в файле local/php_interface/constants.php . В getParamsStructure() возвращаем массив описывающий тип свойства и возможные значения параметра. Этот параметр будет доступен при редактировании ограничения в службе доставки.

Настройка ограничения


Далее проверив корзину и получив параметры ограничения, выполняем финальную проверку в методе check() . Я добавил комментарии в код, чтобы вам было проще сориентироваться. Я настроил ограничение для Почты России. Теперь при такой корзине (без хрупких товаров) нам доступны все методы доставки.

Корзина без хрупких товаров

Добавим в корзину товар, для которого мы проставили флаг "Хрупкий товар". Теперь нам доступен только курье и самовывоз.

Корзина с хрупким товаров

Наше ограничение работает! Через extractParams() и объект класса Shipment можно дотянуться до множества параметров корзины и заказа, а используя вспомогательные методы такие как getDelicateProductId() можно получить дополнительные данные не относящиеся напрямую к заказу, например узнать группу пользователя и т.д. Параметров кстати может быть множество, они описываются как элементы массива в getParamsStructure().

Создавайте свои ограничения доставки, улучшайте пользовательский опыт клиента и логистику сайта. Удачи!.





Полезная статья?
(Голосов: 3, Рейтинг: 3.56)
Netology
Вам также могут понравиться
Английский для программистов

Английский для программистов

Почему IT-специалисту необходимо освоить английский язык? Разбираем в статье.

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как правильно подключать стили и скрипты к шаблону 1С Битрикс.

Генерация оглавления статьи

Генерация оглавления статьи

В статье рассмотрен пример функции для генерации оглавления статьи блога или новости


Комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке