Цитата |
---|
Олег Брага написал: Приветствую. Подскажите пожалуйста, можно ли в событии 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
И обязательно переопределяем описание поля для этого ключа. Без этого не будет работать.
Будут вопросы - пишите.