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