Статус партнерства с 1С-Битрикс: Бизнес партнер
  • Маркетплейс
  • Документация
  • Блог
  • Новости
  • Софт
  • Профиль
  • Программная смена местоположения в компоненте bitrix:sale.order.ajax

    30.05.2018

    Периодически на проектах встречается задача внедрить не стандартную логику определения местоположения в компоненте оформления заказа.

    Большинство решений предлагают, по сути, эмулировать смену уже на отображенной странице с последующей перегрузкой при помощи JavaScrip. Вот еще один вариант, но без лишних перегрузок. Решение работает на основе обработчика события компонента bitrix:sale.order.ajax OnSaleComponentOrderProperties.

    В первую очередь выносим идентификаторы свойств, которые нам понадобятся в доступные переменные

    class ProjectConfig
    {
        /**
         * ИД свойства заказа Почтовый индекс
         */
        const PROPERTY_ZIP_ID = 4;
        /**
         * ИД свойства заказа Местоположение
         */
        const PROPERTY_LOCATION_ID = 6;
    }
    

    Далее добавляем метод обработчика события. Для примера "нестандартной" логики я взял хранение местоположение в свойстве UF_LOCATION пользователя сайта. Компонент оперирует кодом местоположения из-за этого первым делом по значению UF_LOCATION получаем код нужного местоположения. Следующим шагом, необходимо проверить почтовый индекс на соответствие местоположению. Полученные значения местоположения и индекса заносим в соответствующие переменные массива $arUserResult['ORDER_PROP'].

    class SaleHandlers
    {
    	private static $cacheZipTimout = 300000000;
    
        /**
         * Проверяем почтовый индекс по местоположению. Если не входит в список - возвращаем первый из списка
         * @param $locationId int ИД местоположения
         * @param $zip int индекс
         */
        public static function checkZip ($locationId,$zip){
            $arResult = array();
            $cache = Bitrix\Main\Data\Cache::createInstance();
            if ($cache->initCache(self::$cacheZipTimout, 'location_index_'.$locationId, 'zip_locations'))
            {
                $arResult = $cache->getVars();
            }
            elseif ($cache->startDataCache())
            {
                $rsZip = CSaleLocation::GetLocationZIP($locationId);
                while ($arZip = $rsZip->fetch()) {
                    $arResult[$arZip['ZIP']] = true;
                }
                $cache->endDataCache($arResult);
            }
            reset($arResult);
            return (array_key_exists($zip,$arResult)) ? $zip : key($arResult);
        }
    
        public static function OnSaleComponentOrderProperties(&$arUserResult, $request, &$arParams, &$arResult)
        {
            global $USER;
            if ($USER->IsAuthorized()) {
                $arUser= Main\UserTable::getList([
                    'filter' => ['ID' => $USER->GetID()],
                    'select' => [
                        'UF_LOCATION',
                        'LOCATION_CODE'=>'LOCATION.CODE'
                    ],
                    'runtime' => [
                        new Main\Entity\ReferenceField(
                            'LOCATION',
                            '\Bitrix\Sale\Location\LocationTable',
                            [
                                'this.UF_LOCATION' => 'ref.ID'
                            ]
    
                        )
                    ]
                ])->fetch();
                $arUserResult['ORDER_PROP'][Opt::PROPERTY_LOCATION_ID] = $arUser['LOCATION_CODE'];
                $arUserResult['ORDER_PROP'][Opt::PROPERTY_ZIP_ID] = self::checkZip(
    				$arUser['UF_LOCATION'],
    				$arUserResult['ORDER_PROP'][Opt::PROPERTY_ZIP_ID]
    			);
            }
        }
    }
    

    Следующий шаг зарегистрировать классы и обработчик в init.php

    use Bitrix\Main\EventManager;
    
    Bitrix\Main\Loader::registerAutoLoadClasses(null, array(
    	'ProjectConfig' => '/local/php_interface/classes/projectconfig.php',
    	'SaleHandlers' => '/local/php_interface/handlers/salehandlers.php',
    ));
    
    $eventManager = EventManager::getInstance();
    $eventManager->addEventHandler(
    	"sale", 
    	'OnSaleComponentOrderProperties', 
    	array("SaleHandlers", "OnSaleComponentOrderProperties")
    );
    

    Следующая задача изменить страницу оформления заказа. Стандартный компонент оформления заказа выполнен практически полностью на JavaScript. Нам необходимо запретить редактирование местоположения. Для этого необходимо переопределить метод объекта BX.Sale.OrderAjaxComponent сохраняем метод editActiveRegionBlock. И создаем альтернативный, в котором сначала проверяем необходимость отображения блока. Если вывод полей редактирование то просто выходим, иначе вызываем родительский editActiveRegionBlock.

    Для этого в каталоге с шаблоном компонента создаем скрипт (например order_ajax_ext.js) содержащий следующий код:

    (function () {
    	'use strict';
    
    	BX.namespace('BX.Sale.OrderAjaxComponentExt');
    
    	BX.Sale.OrderAjaxComponentExt = BX.Sale.OrderAjaxComponent;
    	BX.Sale.OrderAjaxComponentExt.parentEditActiveRegionBlock = BX.Sale.OrderAjaxComponent.editActiveRegionBlock;
    	BX.Sale.OrderAjaxComponentExt.editActiveRegionBlock =function (activeNodeMode) {
    		if (this.initialized.region) {
    			return;
    		}
    		BX.Sale.OrderAjaxComponent.parentEditActiveRegionBlock(activeNodeMode);
    	};
    })();
    
    И подключаем его в template.php после подключения штатного order_ajax.js командой
    $this->addExternalJs($templateFolder.'/order_ajax_ext.js');
    

    Обратите внимание: предотвращается редактирование всей информации блока "Регион доставки", т.е. если вам необходимо дать доступ на редактирование части полей этого блока - надо более детально разобрать и исправить метод BX.Sale.OrderAjaxComponent.editActiveRegionBlock. Для этого скопировать его код в новый метод из примера выше, и внести необходимые правки. В этом случае возможно родительский метод вызывать нет необходимости (зависит от внесенных правок)

    Все записи

    © 2001-2024 Воробьев Александр