Цитата |
---|
Олег Брага написал: Приветствую. Подскажите пожалуйста, можно ли в событии onBeforeProcessDocument как-то добраться до списка Products полей? И модифицировать его, а то насколько я вижу методы getFields и setValues работают только с обычными не списковыми (не ArrayDataProvider) полями?
Ну или возможны какие-то другие способы, как выводить в документ не все позиции из сделки? Самый простой пример из жизни: в сделке Есть товар и услуга (доставка например), нужно сгенерить документы закрывающие, на товар нужно генерить накладную, куда доставка попасть не должна. Каким образом лучше это сделать? Насколько японимаю никаких условных операторов в шаблонах нет пока, думал получится через событие, но там смог модифицировать только обычные поля, а до списков пока не понял как добраться. |
Здравствуйте.
Интересный вопрос, но, я думаю, есть потребность в решении данной задачи.
Вот я набросал код, который вырезает из документа товары по признаку.
Код рабочий. Перепишите функцию isSkipProduct и всё должно работать.
Код |
---|
<?php
\Bitrix\Main\Loader::includeModule('crm');
\Bitrix\Main\Loader::includeModule('documentgenerator');
/**
* Returns true if this product should not be added to the document
*
* @param \Bitrix\Crm\Integration\DocumentGenerator\DataProvider\Product $product
* @return bool
*/
function isSkipProduct(\Bitrix\Crm\Integration\DocumentGenerator\DataProvider\Product $product)
{
$typePropertyId = 500;
$restrictedType = 100;
return $product->getValue('PROPERTY_'.$typePropertyId) === $restrictedType;
}
$templateId = 242;
// deal id
$value = 29;
$template = \Bitrix\DocumentGenerator\Template::loadById($templateId);
if(!$template)
{
die('template not found');
}
$template->setSourceType(\Bitrix\Crm\Integration\DocumentGenerator\DataProvider\Deal::class);
$document = \Bitrix\DocumentGenerator\Document::createByTemplate($template, $value);
if(!$document)
{
die('could not create document');
}
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
\Bitrix\DocumentGenerator\Driver::MODULE_ID,
'onBeforeProcessDocument',
function(\Bitrix\Main\Event $event)
{
$productsPlaceholder = 'PRODUCTS';
/** @var \Bitrix\DocumentGenerator\Document $document */
$document = $event->getParameter('document');
$provider = $document->getProvider();
$productsProvider = \Bitrix\DocumentGenerator\DataProviderManager::getInstance()->getDataProviderValue($provider, $productsPlaceholder);
if($productsProvider instanceof \Bitrix\DocumentGenerator\DataProvider\ArrayDataProvider)
{
$products = [];
foreach($productsProvider as $product)
{
if(!isSkipProduct($product))
{
$products[] = $product;
}
}
$productsFieldDescription = $provider->getFields()[$productsPlaceholder];
$productsProvider = \Bitrix\DocumentGenerator\DataProviderManager::getInstance()->createDataProvider($productsFieldDescription, $products, $provider, $productsPlaceholder);
$document->setValues([$productsPlaceholder => $productsProvider]);
$document->setFields([$productsPlaceholder => $productsFieldDescription]);
}
}
);
$document->getFile();
|
Небольшие пояснения, как это работает.
Получаем значение из по ключу 'PRODUCTS' из провайдера документа (в данном примере это сделка).
Если значение - это список товаров, то проходимся по нему, фильтруем лишнее, получаем новый массив товаров.
Дальше мы создаем новый объект ArrayDataProvider, полностью аналогичный существующему (на основе описания поля), но с другим массивом товаров.
Переопределяем значение в документе по ключу PRODUCTS
И обязательно переопределяем описание поля для этого ключа. Без этого не будет работать.
Будут вопросы - пишите.