Заполнить коэффициент единицы измерения (MEASURE_RATIO) из свойства элемента

Просмотров: 9016

Задача: Каталог наполняется из 1С, но 1С не передает коэффициент единицы измерения (особенность конкретной 1С, но вообще она умеет). Вместо этого, коэффициенты забиваются в обычный, дополнительный реквизит и приходят на сайт как свойство. Нужно заполнить коэффициент из этого поля.

Для работы каталога и корзины (ввод количества товара по коэффициенту), дабы не городить огород и не переписывать, по отдельности шаблоны каталога (списка, топа, карточки) и корзины - просто скопируем коэффициенты из свойства в поле торгового каталога.

Заполнить коэффициент единицы измерения (MEASURE_RATIO) из свойства элемента

Скрипт для запуска в ручную, по крону или на событие в init.php:

Cmodule::IncludeModule('iblock');
Cmodule::IncludeModule('catalog');
$iblockId = 4;
$updateElements = CIBlockElement::GetList(
    array("ID" => "ASC"),
    array("IBLOCK_ID" => $iblockId),
    false,
    false,
    array(
        'ID',
        'PROPERTY_ATT_COEFFFICIENT'
    )
);
while ($arFields = $updateElements ->GetNext()) {
    $coeff = $arFields['PROPERTY_ATT_COEFFFICIENT_VALUE'];
    $curElementRatio = CCatalogMeasureRatio::getList(
        false,
        array(
            'IBLOCK_ID' => $iblockId,
            'PRODUCT_ID' => $arFields['ID']),
        false,
        false);
    while ($arRatio = $curElementRatio->GetNext()) {
        $ratioId = $arRatio['ID'];
    }

    CCatalogMeasureRatio::update($ratioId, array(
            'PRODUCT_ID' => $arFields['ID'],
            'RATIO' => $coeff
        )
    );
}

Пояснения:
C помощью CIBlockElement::GetLis - получили элементы инфоблока с ИД 4.
Нам нужны только ID элементов и значение свойства PROPERTY_ATT_COEFFFICIENT
Значение коэффициента загнали в переменную $coeff

Внутри цикла (каждого элемента), с помощью CCatalogMeasureRatio::getList получили ID коэффициента конкретного товара (элемента) и загнали в переменную $ratioId
С помощью CCatalogMeasureRatio::update перезаписали/установили коэффициенты для конкретного товара

PS: Если коэффициентов еще не было (пустые). Можно их создать, тут же в цикле, методом CCatalogMeasureRatio::add с любым значением. И тут же перезаписать. Или сразу добавить с нужным значением.

Заполнить коэффициент единицы измерения используя D7

Этот код использует D7-синтаксис для работы с таблицами и модулями в 1С-Битрикс. Обратите внимание, что в D7 нет необходимости использовать CModule::IncludeModule, так как в коде выше используется Loader::includeModule.

use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
use Bitrix\Catalog\MeasureRatioTable;
Loader::includeModule('iblock');
Loader::includeModule('catalog');

$iblockId = 4;
$updateElements = ElementTable::getList([
    'select' => ['ID'],
    'filter' => ['IBLOCK_ID' => $iblockId],
]);
while ($arFields = $updateElements->fetch()) {
    $propertyValue = CIBlockElement::GetProperty(
        $iblockId,
        $arFields['ID'],
        [],
        [
                'CODE' => 'KV_METROV_V_UPAKOVKE_CHIS'
        ]
    );

    if ($arProperty = $propertyValue->Fetch()) {
        $coeff = $arProperty['VALUE'];

        $curElementRatio = MeasureRatioTable::getList([
            'filter' => [
                '=PRODUCT_ID' => $arFields['ID'],
            ],
        ]);
        if ($arRatio = $curElementRatio->fetch()) {
            MeasureRatioTable::update($arRatio['ID'], [
                'RATIO' => $coeff,
            ]);
        }
    }
}

Обновлление коэффициента на событиях обновления или добавления элементов

Для того чтобы сделать код срабатывающим на событиях OnAfterIBlockElementAdd и OnAfterIBlockElementUpdate, вы можете зарегистрировать обработчик событий, используя следующий код в файле init.php:

use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
use Bitrix\Catalog\MeasureRatioTable;

Loader::includeModule('iblock');
Loader::includeModule('catalog');

function updateMeasureRatiosAfterElementChange(&$arFields) {
    if ($arFields['IBLOCK_ID'] == 4) {
        $propertyValue = CIBlockElement::GetProperty(
            $arFields['IBLOCK_ID'],
            $arFields['ID'],
            [],
            ['CODE' => 'KV_METROV_V_UPAKOVKE_CHIS']
        );

        if ($arProperty = $propertyValue->Fetch()) {
            $coeff = $arProperty['VALUE'];

            $curElementRatio = MeasureRatioTable::getList([
                'filter' => [
                    '=PRODUCT_ID' => $arFields['ID'],
                ],
            ]);

            if ($arRatio = $curElementRatio->fetch()) {
                MeasureRatioTable::update($arRatio['ID'], [
                    'RATIO' => $coeff,
                ]);
            }
        }
    }
}

// Регистрируем обработчик события OnAfterIBlockElementAdd
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->registerEventHandler('iblock', 'OnAfterIBlockElementAdd', 'main', '', 'updateMeasureRatiosAfterElementChange');

// Регистрируем обработчик события OnAfterIBlockElementUpdate
$eventManager->registerEventHandler('iblock', 'OnAfterIBlockElementUpdate', 'main', '', 'updateMeasureRatiosAfterElementChange');

Этот код регистрирует обработчик событий для событий OnAfterIBlockElementAdd и OnAfterIBlockElementUpdate, который вызывает функцию updateMeasureRatiosAfterElementChange при добавлении или обновлении элемента инфоблока. Функция в свою очередь выполняет вашу логику обновления коэффициентов.

Обновление коэффициэнта из свойства при обмене с 1С

Вариант кода для init.php который будет срабатывать только при импорте товаров из 1С-Предприятие.

use Bitrix\Main\EventManager;
use Bitrix\Iblock\ElementTable;
use Bitrix\Catalog\MeasureRatioTable;

// Регистрируем обработчик события OnBeforeIBlockElementUpdate
EventManager::getInstance()->addEventHandler(
    'iblock',
    'OnBeforeIBlockElementUpdate',
    'DoUpdateElement'
);

// Регистрируем обработчик события OnBeforeIBlockElementAdd
EventManager::getInstance()->addEventHandler(
    'iblock',
    'OnBeforeIBlockElementAdd',
    'DoAddElement'
);

function DoUpdateElement(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') {
        // Ваша логика по обработке данных перед обновлением элемента

        // Пример обновления коэффициентов
        updateMeasureRatios($arFields);
    }
}

function DoAddElement(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') {
        // Ваша логика по обработке данных перед добавлением элемента

        // Пример обновления коэффициентов
        updateMeasureRatios($arFields);
    }
}

function updateMeasureRatios(&$arFields)
{
    // Проверяем, что существует свойство с нужным кодом
    if (isset($arFields['PROPERTY_VALUES']['KV_METROV_V_UPAKOVKE_CHIS'])) {
        $coeff = $arFields['PROPERTY_VALUES']['KV_METROV_V_UPAKOVKE_CHIS']['n0']['VALUE'];

        // Проверяем, что у элемента есть связь с коэффициентом
        $curElementRatio = MeasureRatioTable::getList([
            'filter' => [
                '=PRODUCT_ID' => $arFields['ID'],
            ],
        ]);

        if ($arRatio = $curElementRatio->fetch()) {
            MeasureRatioTable::update($arRatio['ID'], [
                'RATIO' => $coeff,
            ]);
        }
    }
}

Этот код предполагает, что коэффициент хранится в свойстве с кодом KV_METROV_V_UPAKOVKE_CHIS. Обработчики событий OnBeforeIBlockElementUpdate и OnBeforeIBlockElementAdd регистрируются для выполнения необходимых операций перед обновлением или добавлением элемента. Функция updateMeasureRatios обновляет коэффициент, если он присутствует.

Михаил Базаров 16.01.2024
Не проверенный вариант
Попробовать обновление коэффициентов по событию завершения импорта каждого xml файла
Код
use Bitrix\Main\EventManager;

// Регистрируем обработчик события OnSuccessCatalogImport1C
EventManager::getInstance()->addEventHandler(
    'catalog',
    'OnSuccessCatalogImport1C',
    'OnSuccessCatalogImport1CHandler'
);

function OnSuccessCatalogImport1CHandler(&$arFields)
{
    if (isset($arFields['IBLOCK_ID'])) {
        // Добавьте ваш код обработки данных после успешного импорта 1С
        // ...

        // Пример обновления коэффициентов
        updateMeasureRatiosAfterImport($arFields['IBLOCK_ID']);
    }
}

function updateMeasureRatiosAfterImport($iblockId)
{
    // Получаем элементы инфоблока
    $updateElements = \Bitrix\Iblock\ElementTable::getList([
        'select' => ['ID'],
        'filter' => ['IBLOCK_ID' => $iblockId],
    ]);

    while ($arFields = $updateElements->fetch()) {
        // Ваш код обновления коэффициентов
        updateMeasureRatios($arFields);
    }
}

function updateMeasureRatios(&$arFields)
{
    // Ваш код обновления коэффициентов
    // ...
}

В данном примере, при событии "OnSuccessCatalogImport1C" будет вызван обработчик OnSuccessCatalogImport1CHandler, который выполнит ваш код. Функция updateMeasureRatiosAfterImport затем вызывает ваш код обновления коэффициентов для каждого элемента инфоблока. Вы можете адаптировать этот код под свои требования.

Блог-note: заметки разработчика

Проверка на наличие элементов, текущего пользователя, в заданном инфоблоке.

Если стоит задача, определить наличие элементов созданных пользователем на сайте. Можно воспользоваться API: CUser и CIB...

Композитный сайт на 1С-Битрикс

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

Удалить все картинки элементов инфоблока: анонс, детальную и дополнительные картинки (MORE_PHOTO)

Задача: В инфоблоке 10 000 элементов, нужно удалить картинки анонса, детальные и дополнительные картинки из свойства MOR...

Вывести список всех пользователей с необходимой информацией

Если нужно, на какой-либо странице сайта, вывести всех пользователей из группы "Зарегистирированные пользователи", прост...

Установка поиска Sphinx на Ubuntu 22.04 для 1С-Битрикс

Задача: установить и сконфигурировать поиск Sphinx под управлением Ubuntu 22.04 и панели управления HestiaCP для использ...

Сортировать товары по названию, цене и свойствам в каталоге 1С-Битрикс

Задача: реализовать возможность сортировки товаров в разделах каталога. Сортировка должна работать с использованием AJAX...

Быстрая отписка от всех рассылок модуля "E-mail маркетинг", в кабинете пользователя

Задача: дать пользователям возможность отписаться от всех рассылок "E-mail маркетинга", не только по ссылке из...

Создание агента в 1С-Битрикс, на реальном примере

Задача: Каждый час нужно обновлять свойство элементов/товаров с типом строка "В наличии", вписывать в него либ...

Добавить все свойства инфоблока в умный фильтр одним разом

Если у вас достаточно много свойств, в инфоблоке с товарами, например: больше 1000-чи, после интеграции с 1С или импорта...