При программном создании договоров контрагентов разработчики часто сталкиваются с неожиданным поведением: в реквизитах договора группа финансового учета (ГФУ) заполнена корректно (например, указан счет 76.05), однако при проведении документов проводки упорно ложатся на стандартный счет 60.01. Если же открыть этот договор интерактивно в пользовательском режиме, вручную перевыбрать ту же самую группу финансового учета и нажать кнопку записи, проводки начинают формироваться правильно. Разберем детально, с чем связано такое поведение и как корректно создавать договоры программно.
Проанализируем внутреннее устройство типовых конфигураций «1С:Комплексная автоматизация 2» и «1С:ERP Управление предприятием». В современных версиях учет взаиморасчетов и их отражение в бухгалтерском учете строятся через служебный справочник ОбъектыРасчетов.
Механизм отражения документов в регламентированном учете устроен следующим образом:
ДоговорыКонтрагентов, а через реквизит ГруппаФинансовогоУчета соответствующего элемента справочника ОбъектыРасчетов.ОбъектыРасчетов, где в реквизите Объект хранится ссылка на договор.ОбъектыРасчетов поле ГФУ не заполнено, система использует стандартные счета расчетов по умолчанию (для поставщика — 60.01 и 60.02 вместо заданного субсчета 76).Когда пользователь меняет реквизиты договора в форме, срабатывают типовые обработчики формы и модуля объекта, которые автоматически находят служебный объект расчетов и перезаписывают в нем группу финансового учета. При программной же записи разработчики часто нарушают штатную последовательность вызовов или отключают обработчики.
Рассмотрим типичные сценарии, приводящие к расхождению данных:
ОбменДанными.Загрузка = Истина, платформа отключает обработчики событий ПередЗаписью и ПриЗаписи модуля объекта. В результате штатные процедуры подсистем ВзаиморасчетыСервер и ОбъектыРасчетовСервер не вызываются, и служебный элемент расчетов либо не создается вовсе, либо остается с пустыми реквизитами.ПолучитьСсылку() или записывают пустую «болванку» договора, а затем дописывают реквизиты. При первой записи создается объект расчетов со значениями по умолчанию. Последующая запись измененного договора без вызова процедур обновления расчетов оставляет старый объект расчетов без изменений.Разберем базовый вариант: если договор создается в рамках штатной логики конфигурации, крайне не рекомендуется использовать режим загрузки. Заполнение реквизитов необходимо выполнять до первой записи объекта.
Посмотрим на пример правильного заполнения и записи договора:
НовыйДоговор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
НовыйДоговор.Заполнить(Неопределено);
НовыйДоговор.Наименование = "Договор поставки №123";
НовыйДоговор.Организация = ВыбраннаяОрганизация;
НовыйДоговор.Партнер = ВыбранныйПартнер;
НовыйДоговор.Контрагент = ВыбранныйКонтрагент;
НовыйДоговор.ПорядокРасчетов = Перечисления.ПорядокРасчетов.ПоДоговорамКонтрагентов;
НовыйДоговор.ГруппаФинансовогоУчета = НужнаяГФУ; // Например, ГФУ со счетом 76.05
// Записываем БЕЗ ОбменДанными.Загрузка = Истина!
НовыйДоговор.Записать();
При таком подходе типовые подписки на события и модуль объекта автоматически вызовут процедуры формирования объекта расчетов с переданной группой финансового учета.
Если договор создается в рамках обмена данными, где флаг ОбменДанными.Загрузка = Истина необходим, штатные механизмы не сработают. В этом случае нам потребуется принудительно обновить связанный объект расчетов с помощью типовых процедур конфигурации.
Разберем программный код для синхронизации объекта расчетов:
// Создание и запись договора в режиме загрузки
ДоговорОбъект = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();
ДоговорОбъект.ОбменДанными.Загрузка = Истина;
// Заполнение реквизитов
ДоговорОбъект.Наименование = "Договор аренды №456";
ДоговорОбъект.Организация = ВыбраннаяОрганизация;
ДоговорОбъект.Партнер = ВыбранныйПартнер;
ДоговорОбъект.Контрагент = ВыбранныйКонтрагент;
ДоговорОбъект.ГруппаФинансовогоУчета = НужнаяГФУ;
ДоговорОбъект.Записать();
// Принудительное обновление объекта расчетов через типовой модуль
ОбъектыРасчетовСервер.ОбновитьОбъектРасчетов(ДоговорОбъект.Ссылка);
Процедура ОбновитьОбъектРасчетов модуля ОбъектыРасчетовСервер находит существующий элемент справочника ОбъектыРасчетов или создает новый, перенося в него актуальные реквизиты договора, включая ГруппаФинансовогоУчета.
Если по какой-то причине вызов типовых экспортных процедур недоступен, проанализируем прямой поиск и запись объекта расчетов:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОбъектыРасчетов.Ссылка КАК Ссылка
|ИЗ
| Справочник.ОбъектыРасчетов КАК ОбъектыРасчетов
|ГДЕ
| ОбъектыРасчетов.Объект = &Договор";
Запрос.УстановитьПараметр("Договор", ДоговорСсылка);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
ОбъектРасчетовОбъект = Выборка.Ссылка.ПолучитьОбъект();
ОбъектРасчетовОбъект.ГруппаФинансовогоУчета = НужнаяГФУ;
ОбъектРасчетовОбъект.Записать();
Иначе
// Если объект расчетов еще не был создан
ОбъектРасчетовОбъект = Справочники.ОбъектыРасчетов.СоздатьЭлемент();
ОбъектРасчетовОбъект.Объект = ДоговорСсылка;
ОбъектРасчетовОбъект.Партнер = ДоговорСсылка.Партнер;
ОбъектРасчетовОбъект.Контрагент = ДоговорСсылка.Контрагент;
ОбъектРасчетовОбъект.Организация = ДоговорСсылка.Организация;
ОбъектРасчетовОбъект.ГруппаФинансовогоУчета = НужнаяГФУ;
ОбъектРасчетовОбъект.Записать();
КонецЕсли;
Обратим внимание на особенности ведения взаиморасчетов, которые необходимо учитывать: