[spoiler]
Ларчик открывается просто, достаточно схематично рассмотреть, как происходит сохранение элемента в форме редактирования.
Итак, Вы нажали кнопку "Сохранить" в форме. Данные отправились на сервер, выполняется проверка переданных данных, относящихся к элементу инфоблока, затем (если инфоблок является торговым каталогом) - проверка валидности цен и данных, относящихся к товару. Проверка прошла успешно, начинается сохранение (или обновление) данных:
- Вызывается CIBlockElement::Add или CIBlockElement::Update. Данные заносятся в базу, вызывается пользовательский обработчик событий, изменяет нужный тип цен.
- Вызывается CCatalogProduct::Add или CCatalogProduct::Update - сохранение свойств товара
- Сохраняются цены и удаляются те, которых не было в форме редактирования.
Какой же может быть выход? Если использование обработчика необходимо - его можно усложнить, встроив проверку адреса текущей страницы. Если это адрес формы редактирования - никаких действий не выполнять. А требуемый функционал в форме редактирования реализовать через функцию BXIBlockAfterSave. В настройках инфоблока есть поле "Файл для редактирования элемента, позволяющий модифицировать поля перед сохранением". Путь к файлу с функцией необходимо прописать в этом поле. Минус этого решения - в функцию передаются только поля и свойства элемента, но не цены. Выход - либо брать их из базы, либо работать с массивом $_POST.
UPD. Подобная же проблема может возникнуть в скриптах импорта (csv, 1C). В этом случае решение одно - использовать обработчики класса CPrice.
Решил задачу через жесткий костыль: OnAfterIBlockElementUpdate генерит файлик с id нужного элемента, после чего проверяем наличие данных в этом файле, и если есть то CPrice::SetBase... чистим файл.
Как-то так. Главное работает, как часы!
К примеру в Контент/Каталоги/Продукция/Товары/ товар -> Торговый каталог/Параметры поле "Доступное количество" изменяется поле "Количество товара" на вкладке Склады.
Нужно реализовать, чтобы также отрабатывало при импорте товаров. Тойсть я выгружаю CSV обновляется поле "Доступное количество", а дальше через функцию BXIBlockAfterSave обновляем значения поля "Количество товара".
Подскажите как это можно реализовать.
Как быть?
AddEventHandler("catalog", "OnProductUpdate", "FucOnProductUpdate");
function FucOnProductUpdate($ID, $arFields){
$arOrder = array("SORT"=>"ASC");
$arFilter = array("ID" => $ID);
$arGroupBy = false;
$arNavStartPs = false;
$arSelectFields = array("QUANTITY");
$arRes = CCatalogProduct::GetList($arOrder,$arFilter,$arGroupBy,$arNavStartPs,$arSelectFields)->fetch(); //текущие количество на складе
$arFieldsUpdate = Array("PRODUCT_ID" => $ID,"STORE_ID" => 1, "AMOUNT" => $arRes["QUANTITY");
$arOrderID = array("SORT"=>"ASC");
$arFilterID = array("PRODUCT_ID" => $ID, "STORE_ID" => 1);
$arGroupByID = false;
$arNStPsID = false;
$arSelectFieldsID = array("ID","PRODUCT_ID"); //ID - записи
$arResID = CCatalogStoreProduct::GetList($arOrderID,$arFilterID,$arGroupByID,$arNStPsID,$arSelectFieldsID)->fetch();
if($arResID == false){
$arFieldsADD = Array("PRODUCT_ID" => $ID, "STORE_ID" => 1, "AMOUNT" => $arRes["QUANTITY");
$ID_ADD = CCatalogStoreProduct::Add($arFieldsADD);
}else{
$arFieldsUpdate = Array("PRODUCT_ID" => $ID,"STORE_ID" => 1, "AMOUNT" => $arRes["QUANTITY");
$r = CCatalogStoreProduct::Update($arResID["ID"], $arFieldsUpdate);
}
}
Когда я изменяю поле "Доступное количество" у меня не обновляется поле "Количество товара" на вкладке Склад.
В чем может быть причина?
Вот мой файл BXIBlockAfterSave:
- работает отменно, цена обновляется после обновления страницы элемента товара!
А так выглядит мой обработчик событий init.php:
- обработчик не отрабатывает добавление цены.
Подскажите что надо исправить в init.php?
В Вашем коде для init.php нет обработчиков событий класса CPrice.
Выяснилось, что цена добавилась только у ~ 12 000 элементов.
Скорей всего на сервере не хватает памяти. Будем увеличивать.
Вопрос: Как с помощью скрипта добавить цену остальным элементам?
Если делать через:
$res = CIBlockElement:: GetList и
while ($ob = $res->GetNextElement()) { с проверкой наличия уже проставленной цены.
то не повешу ли я БД.
Как сделать добавление цены большому количеству элементов, при этом наблюдать процесс работы скрипта, чтобы знать работает он ещё или уже закончил работу, или завис??
Я сделал так: в init.php создал статическую переменную $dontDelete, сохраняю в нее ID цены, добавленной с помощью CPrice::Add() (это происходит в обработчике событий OnPriceUpdate/OnPriceAdd). В обработчике события OnBeforeProductPriceDelete проверяю эту переменную, если она не содержится в массиве $arr, то добавляю ее туда и все проходит успешно – новая цена не удаляется.