При разработке обработок массового ввода документов разработчики часто сталкиваются с задачей создания подчиненных документов (например, накладных реализации на основании счетов или заказов покупателей). Нередко возникает вопрос: как правильно перенести данные и гарантировать, что созданный документ появится в дереве структуры подчиненности (связанных документах)? Разберем этот процесс подробно.
Распространенным заблуждением является представление о том, что при создании документа на основании платформа выполняет некую специальную регистрацию и физически «включает» документ в подчиненность. В действительности этот механизм устроен иначе:
КритерийОтбора (обычно с именем СтруктураПодчиненности или СвязанныеДокументы).Сделка, ДокументОснование, СчетНаОплату) или в реквизитах табличных частей (например, колонка ЗаказПокупателя в табличной части Товары).Таким образом, чтобы документ появился в структуре подчиненности, достаточно, чтобы в его реквизитах было корректно сохранено значение ссылки на документ-основание.
Рассмотрим типовой пример ручного переноса полей, который часто пишут начинающие разработчики:
// Ручное заполнение реквизитов шапки и табличных частей
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Организация = Основание.Организация;
НовыйДокумент.Контрагент = Основание.Контрагент;
НовыйДокумент.ДоговорКонтрагента = Основание.ДоговорКонтрагента;
НовыйДокумент.Склад = Основание.Склад;
Для Каждого ТекСтрока Из Основание.Товары Цикл
НоваяСтрока = НовыйДокумент.Товары.Добавить();
НоваяСтрока.Номенклатура = ТекСтрока.Номенклатура;
НоваяСтрока.Количество = ТекСтрока.Количество;
НоваяСтрока.Цена = ТекСтрока.Цена;
НоваяСтрока.Сумма = ТекСтрока.Сумма;
КонецЦикла;
Такой подход имеет существенные недостатки:
В платформе 1С:Предприятие предусмотрен стандартный механизм заполнения одного объекта на основании другого. Вызов метода Заполнить() автоматически запускает обработчик события ОбработкаЗаполнения в модуле объекта создаваемого документа.
Посмотрим на пример правильной реализации:
// Программное создание и инициализация по основанию
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Заполнить(Основание);
// При необходимости можно скорректировать отдельные поля
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Комментарий = "Создано автоматически по обработке";
// Запись и проведение документа
Попытка
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
Исключение
Сообщить("Ошибка проведения документа: " + ОписаниеОшибки());
КонецПопытки;
Преимущества метода Заполнить():
ОбработкаЗаполнения уже заложено заполнение всех реквизитов оснований, благодаря чему документ гарантированно попадет в структуру подчиненности.Если вам требуется обработать массив документов (например, более 100 заказов), учтите следующие практические моменты:
Попытка ... Исключение. Это предотвратит прерывание всей пакетной обработки из-за ошибки в одном документе.РежимПроведенияДокумента.Неоперативный, чтобы избежать блокировок и ошибок контроля оперативного времени.Заполнить() копирует строки документа-основания целиком. Если по заказу уже были частичные отгрузки, перед созданием документа может потребоваться программно откорректировать количество в табличной части с учетом фактических остатков к отгрузке.