Как программно создать два или более документов на основании одного

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки в системе 1С:Предприятие часто возникает задача автоматизации, когда на основании одного документа-источника (например, «Заявка») требуется сформировать не один, а сразу пакет документов. Стандартный механизм «Ввод на основании» ориентирован на создание ровно одного экземпляра объекта, что вызывает определенные трудности у начинающих разработчиков. Разберем подробно, почему стандартная процедура ОбработкаЗаполнения не подходит для создания нескольких документов и как реализовать эту задачу правильно.

Почему стандартная ОбработкаЗаполнения имеет ограничения

Процедура ОбработкаЗаполнения, расположенная в модуле объекта, вызывается в момент инициализации конкретного экземпляра документа. Ее основная задача — заполнить реквизиты текущего объекта данными из переданного основания. Попытка программно создать и записать второй документ внутри этой процедуры является грубой архитектурной ошибкой по нескольким причинам:

  1. Нарушение транзакционности: Если пользователь решит закрыть форму первого (создаваемого стандартно) документа без сохранения, то второй документ, созданный программно методом Записать() внутри процедуры, уже останется в базе данных. Это приведет к появлению «мусорных» данных.
  2. Интерактивность: Стандартный механизм ожидает открытия формы одного объекта. Попытка открыть вторую форму из модуля объекта технически невозможна на стороне сервера.

Проанализируем правильные способы решения этой задачи, которые позволяют сохранить чистоту кода и удобство для пользователя.

Решение 1: Использование пользовательской команды (Рекомендуемый способ)

Вместо того чтобы полагаться на стандартную кнопку «Создать на основании», мы создадим собственную команду. Это может быть Команда объекта (расположенная непосредственно в документе) или Общая команда. Такой подход позволяет нам полностью контролировать процесс создания любого количества документов. При необходимости роботизировать этот процесс без изменения кода конфигурации применяют программное формирование документов по сценарию.

Рассмотрим алгоритм реализации. Сначала создадим команду и пропишем в ее модуле клиентский обработчик. Нам необходимо вызвать серверный метод, который сформирует объекты, а затем открыть их формы пользователю.

Пример кода в модуле команды:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    // ПараметрКоманды — это ссылка на наш документ-основание
    ДанныеДокументов = СформироватьПакетДокументовНаСервере(ПараметрКоманды);
    
    // Перебираем массив структур с параметрами заполнения и открываем формы
    Для Каждого ДанныеЗаполнения Из ДанныеДокументов Цикл
        ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ДанныеЗаполнения);
        ОткрытьФорму("Документ.ТребованиеНакладная.ФормаОбъекта", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, Истина);
    КонецЦикла;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция СформироватьПакетДокументовНаСервере(СсылкаОснование)
    
    Результат = Новый Массив;
    
    // Подготавливаем данные для первого документа (склад ТМЦ)
    ПараметрыТМЦ = Новый Структура;
    ПараметрыТМЦ.Вставить("Основание", СсылкаОснование);
    ПараметрыТМЦ.Вставить("ТипСклада", "ТМЦ");
    Результат.Добавить(ПараметрыТМЦ);
    
    // Подготавливаем данные для второго документа (склад ГП)
    ПараметрыГП = Новый Структура;
    ПараметрыГП.Вставить("Основание", СсылкаОснование);
    ПараметрыГП.Вставить("ТипСклада", "ГП");
    Результат.Добавить(ПараметрыГП);
    
    Возврат Результат;
    
КонецФункции

В этом примере мы не записываем документы сразу, а передаем структуру параметров в форму нового документа. Чтобы это заработало, необходимо в целевом документе (Требование-накладная) в процедуре ОбработкаЗаполнения проанализировать входящую структуру.

Решение 2: Тонкая настройка ОбработкиЗаполнения

Выясним, как должен выглядеть код в модуле объекта целевого документа, чтобы он умел различать, какой именно документ из пакета сейчас создается. Выясним это, проанализировав использование параметра ДанныеЗаполнения.


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
        // Обработка логики при программном создании пакета
        Основание = ДанныеЗаполнения.Основание;
        ТипСклада = ДанныеЗаполнения.ТипСклада;
        
        ЗаполнитьОбщиеРеквизиты(Основание);
        
        Если ТипСклада = "ТМЦ" Тогда
            // Заполняем только строки, относящиеся к ТМЦ
            ЗаполнитьСтрокиПоСкладуТМЦ(Основание);
        ИначеЕсли ТипСклада = "ГП" Тогда
            // Заполняем только строки, относящиеся к ГП
            ЗаполнитьСтрокиПоСкладуГП(Основание);
        КонецЕсли;
        
    ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.Заявка") Тогда
        // Стандартный ввод на основании (если нужен)
        ЗаполнитьПоСтандарту(ДанныеЗаполнения);
    КонецЕсли;
    
КонецПроцедуры

Решение 3: Использование формы-помощника (Транзитная обработка)

Если бизнес-процесс предполагает, что пользователь должен иметь возможность выбрать, какие именно документы создавать, или уточнить данные перед созданием, лучше всего использовать Обработку-помощник. Разберем этот сценарий подробнее.

Вместо непосредственного создания документов, кнопка «Создать на основании» открывает форму обработки. В этой форме мы можем отобразить пользователю таблицу с будущими документами. Это дает ряд преимуществ:

После нажатия кнопки «Сформировать» в обработке, запускается цикл создания документов. Здесь мы также можем использовать метод ОткрытьФорму() для каждого объекта, чтобы пользователь мог их проверить и нажать «Провести» вручную.

Интеграция с Библиотекой стандартных подсистем (БСП)

В современных конфигурациях (таких как ERP 2.5, УТ 11, БП 3.0) механизм ввода на основании управляется через подсистему «Подключаемые команды». Чтобы внедрить создание двух документов по одной кнопке в общую систему, нам потребуется внести изменения в модуль менеджера документа-источника. В БП 3.0 для подобных задач внедряют автоматическое создание счета и договора на основании писем.

Проанализируем процедуру ПриОпределенииКомандПодключенныхКОбъекту. Здесь мы можем зарегистрировать свою команду, указав для нее параметр Использование = "ВызовСерверногоМетода". Это позволит системе выполнить наш код на сервере без лишних переключений контекста, что значительно ускоряет работу программы при создании больших пакетов документов. Практический пример такой реализации представлен в обработке для пакетного создания документов на основании исходного.

Важные нюансы при работе с транзакциями

Проанализируем ситуацию, когда документы должны быть созданы и записаны автоматически без участия пользователя (в фоновом режиме). В этом случае критически важно использовать транзакции. Рассмотрим пример кода:


НачатьТранзакцию();
Попытка
    Док1 = Документы.ТребованиеНакладная.СоздатьДокумент();
    // Логика заполнения Док1
    Док1.Записать(РежимЗаписиДокумента.Запись);
    
    Док2 = Документы.ТребованиеНакладная.СоздатьДокумент();
    // Логика заполнения Док2
    Док2.Записать(РежимЗаписиДокумента.Запись);
    
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ЗаписьЖурналаРегистрации("Ошибка создания пакета документов", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
    ВызватьИсключение "Не удалось создать пакет документов. Обратитесь к администратору.";
КонецПопытки;

Важно: Помните, что внутри транзакции нельзя открывать формы документов пользователю. Транзакция используется только тогда, когда весь процесс автоматизирован полностью.

Заключение

Мы рассмотрели несколько способов решения задачи. Подведем итог: для большинства интерактивных задач оптимальным является использование пользовательской команды, которая подготавливает параметры и открывает несколько форм новых документов. Если же требуется сложная настройка перед созданием — выбирайте форму-помощник. Использование ОбработкаЗаполнения для создания сторонних объектов — это путь к ошибкам и нестабильной работе базы данных, которого следует избегать.

← На главную