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

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

Задача: Каталог наполняется из 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 затем вызывает ваш код обновления коэффициентов для каждого элемента инфоблока. Вы можете адаптировать этот код под свои требования.