Вячеслав, хм... идея интересная. У меня получилось нечто среднее.
Не было времени тщательно протестировать, но прямой кейс:
1) Создаем множественное свойство типа число
2) Создаем простые счета, называет их "Дочерний 1", "Дочерний 2" и "Родительский". Дочерние счета с товарами
3) Редактируем "Родительский" указываем в свойстве счета "Дочерний 1", "Дочерний 2"
4) Редактируем любой дочерний счет, изменяя состав.
Как результат: при изменении товарного состава (через кнопку редактировать) изменяется состав родительского счета
Код |
---|
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandlerCompatible('crm', 'OnBeforeCrmInvoiceUpdate', ['\\InvoiceHandler','updateInvoice']);
class InvoiceHandler
{
/**
* @var string Название свойства где храним ID дочерних счетов
*/
protected static $fieldCode = 'UF_CRM_1525862024';
public static function updateInvoice(&$arFields)
{
global $APPLICATION;
/**
* Если передается непустое свойство с дочерними счетами
* значит это родительский счет, который не нужно проверять
* так как [ 0 => "" ] не пустой массив нужно использовать
* array_filter для получение пустого массива
*
* Полагаем, что вложенность счетов не больше 1 уровня,
* а значит, если передано не пустое свойство, то это родительский
* элемент который не нужно обрабатывать.
* @var array Значение "Дочерние элементы"
*/
$arRealChildInvoices = ( !array_key_exists(static::$fieldCode, $arFields) )
? array_filter($arFields[static::$fieldCode])
: [];
if ( !empty($arRealChildInvoices) )
{
return true;
}
/**
* Нас интересуют только счета у которых есть товары, если это дочерний
* счет без товаров, то и учитывать его не нужно
*/
if ( empty($arFields['PRODUCT_ROWS']) )
{
return true;
}
/**
* Получим родительский счет и необходимые параметры
* для обновления товарного каталога.
* Если родитель не найден, значит это простой счет и делать ничего не нужно
*/
$arParentInvoice = \Bitrix\Crm\InvoiceTable::getRow([
'select' => ['ID', static::$fieldCode, 'ORDER_TOPIC', 'PAY_SYSTEM_ID' ,'PERSON_TYPE_ID'],
'filter' => [
static::$fieldCode => $arFields['ID'],
]
]);
if ( !$arParentInvoice )
{
return true;
}
$arProductRows = $arFields['PRODUCT_ROWS'];
/**
* Получим единый массив из товаров для всех счетов.
* @todo Лучше передать без запроса в цикле, так как
* счет это ничто иное как заказ в БД, можно просто
* достать товары всех заказов за 1 запрос
*/
foreach ($arParentInvoice[static::$fieldCode] as $invoiceId)
{
if ( $invoiceId == $arFields['ID'] || empty($invoiceId) )
{
continue;
}
$arProducts = \CCrmInvoice::GetProductRows($invoiceId);
if ( empty($arProducts) )
{
continue;
}
$arProductRows = array_merge($arProductRows,$arProducts);
}
unset($arProducts);
/**
* Особое внимание на значение [ "" ] в INVOICE_PROPERTIES
* без него обработки счета не будет, но в последней версии
* он почему-то unset'ится
* @var array Обновляемая информация родительского счета
*/
$arParentUpdateFields = [
'ORDER_TOPIC' => $arParentInvoice['ORDER_TOPIC'],
'PAY_SYSTEM_ID' => $arParentInvoice['PAY_SYSTEM_ID'],
'PERSON_TYPE_ID' => $arParentInvoice['PERSON_TYPE_ID'],
'INVOICE_PROPERTIES' => [ "" ],
'PRODUCT_ROWS' => $arProductRows
];
/**
* @var CCrmInvoice Объект счета с выключенной проверкой прав
*/
$invoice = new \CCrmInvoice(false);
$bResult = $invoice->Update($arParentInvoice['ID'], $arParentUpdateFields);
if ( !$bResult )
{
// логгируем ошибку
}
return true;
}
} |