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