При работе с электронным документооборотом (ЭДО) часто возникает задача автоматического заполнения реквизитов, которые не входят в стандартный пакет обмена. Типичный пример — перенос текстового комментария из исходного документа Заказ поставщику (на стороне отправителя) в создаваемый Заказ покупателя (на стороне получателя). В этой статье мы подробно разберем, как реализовать этот механизм, где именно писать код и как правильно идентифицировать документы в базе данных.
Рассмотрим стандартную ошибку начинающих разработчиков: попытку написать логику заполнения в процедуре ПриСозданииНаСервере формы документа. Разберем, почему это решение не является оптимальным. Во-первых, при обмене через ЭДО документы часто создаются и записываются программно в фоновом режиме, без открытия интерактивной формы. В этом случае код в форме просто не выполнится. Во-вторых, форма должна отвечать за визуальное отображение, а бизнес-логика заполнения должна находиться в модуле объекта.
Проанализируем альтернативные варианты. Наиболее правильным местом для реализации логики заполнения является процедура ОбработкаЗаполнения в модуле объекта документа ЗаказПокупателя. Также в типовых конфигурациях, использующих Библиотеку электронных документов (БЭД), можно использовать переопределяемые модули интеграции ЭДО, такие как ИнтеграцияЭДОПереопределяемый. Это позволит перехватить данные в момент их загрузки из XML-файла.
Прежде чем получить комментарий, нам нужно найти в базе данных тот самый Заказ поставщику, который послужил основанием. Искать по тексту самого комментария, как предлагалось в начале обсуждения на форуме, — крайне ненадежный метод. Мы рискуем найти множество документов с пустыми или похожими комментариями.
Выясним, какие данные приходят из ЭДО. Как правило, в электронном документе содержится номер и дата заказа. Рассмотрим пример запроса, который позволяет найти ссылку на документ по его номеру:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказПоставщику.Ссылка КАК Ссылка,
| ЗаказПоставщику.Комментарий КАК Комментарий
|ИЗ
| Документ.ЗаказПоставщику КАК ЗаказПоставщику
|ГДЕ
| ЗаказПоставщику.Номер = &Номер
| И ЗаказПоставщику.Проведен";
Запрос.УстановитьПараметр("Номер", НомерИзДанныхЭДО);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Теперь у нас есть и ссылка, и комментарий
Объект.Комментарий = Выборка.Комментарий;
КонецЕсли;
Нужно учитывать, что стандартные форматы ФНС (например, УПД) не всегда содержат поле Комментарий в явном виде. В системе ЭДО текстовая информация часто передается через так называемые "Информационные поля" (ИнфПоля) в XML-файле. Посмотрим на ситуацию со стороны отправителя: чтобы комментарий вообще дошел до получателя, он должен быть включен в файл обмена.
Если вы используете расширение, вы можете программно добавить текст комментария в дополнительные сведения электронного документа при отправке. На стороне получателя этот текст можно будет извлечь из структуры данных ДанныеЗаполнения, которая передается в ОбработкаЗаполнения.
Рассмотрим пример реализации логики в модуле объекта ЗаказПокупателя. Мы будем использовать поиск по номеру документа-основания, который передается в структуре данных:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") И ДанныеЗаполнения.Свойство("НомерОснования") Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказПоставщику.Комментарий КАК Комментарий
|ИЗ
| Документ.ЗаказПоставщику КАК ЗаказПоставщику
|ГДЕ
| ЗаказПоставщику.Номер ПОДОБНО &Номер";
// Используем ПОДОБНО, так как номера могут иметь разные префиксы у отправителя и получателя
Запрос.УстановитьПараметр("Номер", "%" + ДанныеЗаполнения.НомерОснования);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
ЭтотОбъект.Комментарий = Выборка.Комментарий;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Иногда возникают ситуации, когда один Заказ покупателя формируется на основании нескольких документов или когда в процессе участвует сложная цепочка документов. Если нам нужно собрать комментарии из нескольких источников, проанализируем следующий подход с использованием массива и функции СтрСоединить:
Предположим, у нас есть массив ссылок на заказы. Нам нужно объединить их уникальные комментарии в одну строку, разделяя их переносом строки.
МассивКомментариев = Новый Массив;
// Допустим, СсылкиОснований - это массив найденных документов
Для Каждого СсылкаОснование Из СсылкиОснований Цикл
Если ЗначениеЗаполнено(СсылкаОснование.Комментарий) Тогда
// Проверяем на дубли, чтобы не повторять одинаковые фразы
Если МассивКомментариев.Найти(СсылкаОснование.Комментарий) = Неопределено Тогда
МассивКомментариев.Добавить(СсылкаОснование.Комментарий);
КонецЕсли;
КонецЕсли;
КонецЦикла;
ЭтотОбъект.Комментарий = СтрСоединить(МассивКомментариев, Символы.ПС);
Для того чтобы данные передавались корректно без сложного программирования, рекомендуем обратить внимание на следующие возможности 1С:УНФ:
Администрирование — Электронные документы появились Настройки заполнения входящих документов. Проверьте, возможно ли настроить маппинг полей через этот интерфейс без изменения кода.СопоставлениеОбъектовЭДО. Это исключает ошибки, связанные с дублированием номеров документов у разных поставщиков.Подведем итог: Перенос комментария — это задача поиска правильного документа-источника. Основное внимание стоит уделить надежности идентификации (лучше использовать GUID или связку Номер+Дата) и правильному выбору места размещения кода (Модуль объекта, ОбработкаЗаполнения). Использование запросов в формах является устаревшим подходом, который не гарантирует работу в автоматизированных процессах ЭДО.