При разработке обработок загрузки данных (например, из XML или Excel) программисты часто сталкиваются с проблемой: при ручном создании документа в интерфейсе 1С:Бухгалтерия 3.0 система автоматически подставляет договор, счета учета, ставки НДС и цены, но при программном создании объекта ДокументОбъект эти поля остаются пустыми. Это происходит потому, что значительная часть логики «автозаполнения» привязана к событиям формы ПриИзменении.
В этой статье мы разберем, как правильно имитировать поведение управляемой формы в коде, чтобы документ заполнялся максимально корректно и автоматически.
Первое, что нам необходимо понять: в управляемом приложении 1С код формы и код программного объекта разделены. Когда пользователь меняет Контрагента на форме, срабатывает серверный обработчик, который обращается к общим модулям. Наша задача при программном создании — не пытаться открыть форму (это невозможно в фоновом задании или серверном коде), а вызвать те же самые процедуры из общих модулей, которые использует форма.
Рассмотрим стандартный механизм инициализации документа. У каждого документа есть процедура ОбработкаЗаполнения в модуле объекта. Прежде чем вручную назначать реквизиты, следует вызвать метод Заполнить(). Это позволит системе установить значения по умолчанию (организацию, склад, валюту), которые определены в настройках пользователя или учетной политике.
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
// Инициализация стандартных реквизитов (дата, организация и т.д.)
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Заполнить(Неопределено);
Проанализируем ситуацию, когда нам нужно установить контрагента. В типовой конфигурации «Бухгалтерия предприятия» простого присвоения НовыйДокумент.Контрагент = СсылкаНаКонтрагента недостаточно. Нам нужно, чтобы заполнился основной договор и банковский счет.
Для этого в типовых решениях используются экспортные процедуры из общих модулей. Посмотрим на пример заполнения договора, который обычно вызывается в форме, но может быть вызван и программно:
НовыйДокумент.Контрагент = СсылкаНаКонтрагента;
// В БП 3.0 для подстановки договора часто используется логика из модуля ЗаполнениеДокументовБП
ПараметрыЗаполнения = Новый Структура();
ПараметрыЗаполнения.Вставить("ДокументОбъект", НовыйДокумент);
ЗаполнениеДокументовБП.ЗаполнитьДоговор(НовыйДокумент, "Контрагент");
Важный момент: если вы не знаете название конкретного модуля, откройте форму документа РеализацияТоваровУслуг в конфигураторе, найдите событие КонтрагентПриИзменении и посмотрите, какая серверная процедура там вызывается. Чаще всего она ведет в общий модуль с названием вроде ЗаполнениеДокументовБПСервер.
Это самая трудоемкая часть. При добавлении номенклатуры вручную система подтягивает счета учета (например, 41.01), счета доходов (90.01.1), счета расходов и ставку НДС. Чтобы сделать это программно, проанализируем следующие механизмы:
СчетаУчетаНоменклатуры. Чтобы не писать запросы вручную, используем типовую функцию.Номенклатура.Рассмотрим пример кода для заполнения строки табличной части:
НоваяСтрока = НовыйДокумент.Товары.Добавить();
НоваяСтрока.Номенклатура = СсылкаНаНоменклатуру;
НоваяСтрока.Количество = 10;
// Вызываем типовой механизм заполнения счетов учета
// В БП 3.0 это часто делается через модуль МенеджерСчетовУчета
ПараметрыСчетов = СчетаУчетаНоменклатуры.ПолучитьСчетаУчета(НовыйДокумент.Организация, НоваяСтрока.Номенклатура, НовыйДокумент.Склад);
ЗаполнитьЗначенияСвойств(НоваяСтрока, ПараметрыСчетов);
// Заполнение цен и пересчет сумм
// Используем специализированные модули пересчета, чтобы не считать НДС вручную
СтруктураПересчета = Новый Структура("ПересчитатьЦену, ПересчитатьСумму", Истина, Истина);
ОбработкаТабличныхЧастей.ПриИзмененииНоменклатурыТабЧасти(НоваяСтрока, НовыйДокумент, СтруктураПересчета);
Как справедливо замечено в обсуждении на форуме, отличным источником «правильного» кода заполнения являются модули обмена. В конфигурации Бухгалтерия предприятия есть модуль МенеджерОбменаЧерезУниверсальныйФормат. В нем 1С уже реализовала логику создания документов на основе входящих данных.
Проанализируем процедуры в этом модуле:
ПКО_Документ_РеализацияТоваровУслуг_ПередЗаписьюПолученныхДанныхОтложеннаяОбработка_РТиУВ этих процедурах можно подсмотреть, какие именно вспомогательные функции вызывает сама система при загрузке данных из других баз (например, из Управление торговлей). Там вы найдете готовые вызовы для заполнения аналитики, счетов и налоговых параметров.
После того как все строки добавлены, необходимо убедиться, что итоги по документу (Всего, НДС) рассчитаны правильно. Даже если вы заполняли суммы в каждой строке, рекомендуется вызвать общий метод пересчета. В современных типовых конфигурациях за это отвечают модули вроде БухгалтерскийУчетПересчет или УчетНДС.
Выясним причину, почему это важно: при программном заполнении легко пропустить расчет суммы НДС «в том числе» или «сверху», что приведет к ошибкам при проведении документа. Всегда ищите метод РассчитатьИтоги() или его аналог в модуле объекта документа.
// Пример финального пересчета перед записью
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
// Если нужно сразу провести
Если НовыйДокумент.ПроверитьЗаполнение() Тогда
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
КонецЕсли;
Для реализации «умного» программного создания документа следуйте алгоритму:
Заполнить() для инициализации объекта.ПриИзменении) и найдите экспортные методы в общих модулях, которые они вызывают.СчетаУчетаНоменклатуры для заполнения бухгалтерской аналитики.ОбработкаТабличныхЧастей для автоматического расчета цен и налогов.МенеджерОбменаЧерезУниверсальныйФормат как библиотеку примеров для сложных случаев заполнения.Такой подход гарантирует, что программно созданные документы не будут отличаться от созданных вручную, а учетные данные останутся корректными.