Генератор документов - феррари на которой можно ездить только вокруг дома, Новый модуль получился хорошим но не предназначен для использования разработчиками.
Александр Медведев написал: Олег Брага , попробуйте событие onBeforeProcessDocument и подмените значения на лету
Приветствую, ну ручками тянуть все значения реквизитов и заменять их по кодам, как-то печально, так как по идее должно быть достаточно подменить привязку к компании, а все остальное должно уже автоматом подтянуться. Проблем только с тем, что бы сделать это в правильный момент или иметь возможность каким-то образом перезапустить процесс подтягивания этих данных после замены в поле MY_COMPANY
Олег Брага написал: Вообще конечно мне не понятно почему нет изначально поля моя компания в Сделке, которое бы влияло на выбор потом при печати правильных реквизитов, в случае когда компаний несколько.
Кажется, в сделку планировали внедрить селектор выбора реквизитов, по аналогии со счетами. Когда это будет сделано - не скажу.
Вам надо в обработчике события вызвать $document->setValues(['MY_COMPANY' => 1]); Вычисление конкретных значений полей происходит позже, после этого события. Там будут учтены переданные вами данные
Антон Горбылев написал: По поводу события onBeforeProcessDocument Александр Медведев вам правильно рассказал. Вам надо в обработчике события вызвать $document->setValues(['MY_COMPANY' => 1]);
в моем случае вот такой код внутри обработчика события onBeforeProcessDocument:
код точно выполняется и в $newMyCompanyId точно лежит правильный ID одной из моих компаний. Но все равно в файле печатается название той у которой идентификатор меньше.
А вот такой код меняет наименование организации в конечном документе:
Приветствую, Александр Медведев, Наименование вставляется из реквизитов, показано на скриншоте screen_1 а насчет логов вы правы, там этот блок встречается дважды поскольку я забыл отключить обработчик события onCreateDocument, где обновляю привязку к моей компании непосредственно в данных документа. сейчас проведу еще раз более чистый эксперимент.
Уберите вызов \Bitrix\DocumentGenerator\Document::getFields() до того, как вы вызываете setValues()
Важно, чтобы ид моей компании был указан до того, как документ произведет инициализацию цепочки провайдеров и вычислит значения их полей. А в getFields() как раз идёт вычисление значений. После этого менять значение провайдера бесполезно, там будет работать только смена конечных значений.
Понятно, спасибо, сейчас попробую. Правда у меня на этом была основана проверка, нужно ли вообще обновлять это поле, не прописано ли оно уже правильное. Ну ладно пусть каждый раз обновляет.
Олег Брага, не надо ничего проверять. setValues() только добавляет данные во внутреннее хранилище переопределенных значений, внутри там нет никаких вычислений и можете дергать метод сколько хотите (он не перезаписывает, а всегда дополняет данные).
Антон Горбылев, спасибо, все получилось. В конечно итоге я сделал в обработчике onBeforeProcessDocument переопределение для печати, как вы писали, а в onCreateDocument изменение данных самого объекта документа, без запуска генерации (update со вторым параметром false), что бы при открытии данных тоже правильная компания привязанная отображалась.
Олег Брага написал: в onCreateDocument изменение данных самого объекта документа, без запуска генерации (update со вторым параметром false), что бы при открытии данных тоже правильная компания привязанная отображалась.
а без этого в редактировании отображается неверная компания? Мне кажется, этот шаг лишний. У вас может возникнуть ситуация, когда в docx файле одни данные, а в pdf - другие. Должно работать и без onCreateDocument.
Да, Антон Горбылев, вы правы, можно и без обработки на создание. Я просто подумал сначала, что то событие только на данные в рантайме перед генерацией документа влияет, а в базу не сохранит.
Бегло посмотрел код и насколько понял, вся работа с трансформером идёт через генератор документов. Хочу возможность подменить трансформер (реализовать интерфейс), так как давно для конвертации использую другой сервис, размещённый в локалке и отлично работающий, без всяких облаков и отсылки документов "куда-то". Однако, пока же модуль подключается жёстко и такой возможности вроде нет
nukemonk, я думаю, что можно использовать и своё решение. Тут вариантов два. Первый - это переписать сам модуль transformer. Он не очень сложный, кода там немного. Обновления для модуля выходят редко, можно держать его под системой контроля версий для возможности отката. 1. Указать свой адрес обработчика (смотрите код \Bitrix\Transformer\Http::__construct()) - в этом случае команда будет уходить по вашему адресу. 2. Сделать свою обработку результатов конвертации. Если другой хост, то надо подшаманить метод \Bitrix\Transformer\Http::getBackUrl() 3. Если данные у вас конвертируются локально, то можно писать сразу в базу 4. Сохранить файлы (таблица b_transformer_command - указать STATUS=400, сохранить файлы в b_documentgenerator_file, можете посмотреть \Bitrix\DocumentGenerator\Integration\TransformerManager::call())
Второй вариант - конвертировать самостоятельно через события генератора документов 1. Отключаете модуль transformer (если он нужен в другом месте, то можете дергать \Bitrix\Main\ModuleManager::unRegisterModule() и \Bitrix\Main\ModuleManager::registerModule() в рантайме, но это не очень) 2. Перехватываете события onCreateDocument и onUpdateDocument 3. В обработчике события конвертируете самостоятельно и сохраняете, куда нужно. Опять же сохранение можно посмотреть тут \Bitrix\DocumentGenerator\Integration\TransformerManager::call()
Сейчас связь жесткая, но развязывать, мне кажется, надо на уровне модуля transformer. Если есть потребность - пишите в техподдержку.
Так вот именно хотелось бы обойтись без того, чтобы калечить ядро Это итак понятно, что можно. Как написал, подумал, что есть вариант установить controller_transformer_url на свой и просто организовать скрипт-прослойку. Тогда в битриксе вообще ничего не надо будет трогать, но пока не хватило времени посмотреть, как именно идёт обмен
Воспроизвести полный цикл загрузки результатов обработки на клиент будет сложно (с учетом того, что надо полностью воспроизвести структуру запросов). Там сначала идёт запрос информации, куда загружать, потом файлы бьются на части и по частям загружаются на клиент, в конце склеиваются.
Лучше сделать отправку себе и загрузить себе самостоятельно.
Антон Горбылев написал: Там сначала идёт запрос информации, куда загружать, потом файлы бьются на части и по частям загружаются на клиент, в конце склеиваются.
Не понял, если честно. Сервер (контроллер) загружает сам файл на клиента?
Антон Горбылев написал: Там сначала идёт запрос информации, куда загружать, потом файлы бьются на части и по частям загружаются на клиент, в конце склеиваются.
Не понял, если честно. Сервер (контроллер) загружает сам файл на клиента?
да. Конвертация - операция асинхронная. На контроллере очередь. Клиент отдает задание на конвертацию, но не знает, когда она завершится. Сервер после окончания конвертации сам загружает результаты на клиент (если клиент всё ещё их ожидает)
То, что асинхронная - это само собой, но как-то слишком сложно, имхо. Почему на клиент (коллбэк) просто не отдавать данные по загрузке сконвертированного файла (урл на файл)? И загрузку реализовывать на клиенте? Единственный плюс такого подхода вижу - разве что для некоторого повышения безопасности. Больше плюсов навскидку не нахожу )
nukemonk написал: Почему на клиент (коллбэк) просто не отдавать данные по загрузке сконвертированного файла (урл на файл)? И загрузку реализовывать на клиенте?
Потому что сервер не хранит файлы. Из соображений экономии места, защиты приватности и содержимого файлов. После конвертации файл сразу загружается на клиент. Независимо от результата загрузки (успешно / неуспешно) файлы удаляются сразу.
Печалька. Как раз временное хранение файла и отдача только урла на него позволили бы без проблем организовывать прослойку (шину). У нас сейчас так работает, надеялся, что тут будет такой же подход. И не мог понять, что там за методы сохранения частей.