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