В разработках на платформе 1С:Предприятие 7.7 периодически возникает задача: при проведении одного документа необходимо автоматически сформировать, заполнить и записать отдельную бухгалтерскую операцию или другой документ. Однако при попытке реализовать такую логику непосредственно внутри процедуры ОбработкаПроведения() разработчики сталкиваются с тем, что созданный объект либо не сохраняется в базе вовсе, либо выдает ошибку вида <Объект не найден> при просмотре в мониторе пользователей.
Рассмотрим подробно причины такого поведения платформы 1С 7.7 и разберем проверенные архитектурные решения этой проблемы.
Посмотрим на классический пример кода, который часто пытается использовать разработчик внутри модуля проведения документа:
Процедура ОбработкаПроведения()
// Формирование и заполнение ТЗ остатков...
Если Тз.КоличествоСтрок() > 0 Тогда
Тз.ВыбратьСтроки();
Оп2 = СоздатьОбъект("Операция");
Оп2.Новая();
Пока Тз.ПолучитьСтроку() = 1 Цикл
Оп2.НоваяПроводка();
Оп2.Дебет.Счет = Тз.ДебетСчет;
Оп2.Дебет.Суб1 = Тз.Суб1;
Оп2.Кредит.Счет = Тз.КредитСчет;
Оп2.Дебет.Суб2 = Тз.Суб2;
Оп2.Сумма = Тз.Сум;
КонецЦикла;
Оп2.Содержание = "Дополнительная операция";
Оп2.ДатаОперации = ДатаДок;
Оп2.ЗаписатьПроводки();
Оп2.Записать();
// Интерактивное открытие формы созданной операции
ОткрытьФормуМодально(Оп2.Документ);
КонецЕсли;
КонецПроцедуры
При таком подходе визуально форма операции может даже открыться, содержать правильные проводки, реквизиты и номер. Однако после завершения проведения документа созданная операция бесследно исчезает из базы данных.
Проанализируем физику работы платформы 1С 7.7, чтобы понять, почему этот код не работает так, как ожидается:
ОбработкаПроведения() в 1С 7.7 всегда исполняется платформой внутри служебной неявной транзакции. Все действия с объектами внутри этого блока объединяются. Платформа 7.7 не поддерживает автономные или независящие от родителя вложенные транзакции.СоздатьОбъект("Операция") без корректного документа-контейнера вне текущей транзакции не позволяет платформе правильно зафиксировать объект в системных таблицах (в частности, в 1SJOURN).ОткрытьФормуМодально(), прямо в момент активной транзакции проведения блокирует системные таблицы и нарушает логику контекста записи, что приводит к откату изменений и появлению записи <Объект не найден>.Разберем способы решения данной задачи в зависимости от требований бизнес-логики.
Если цель состоит лишь в том, чтобы сформировать дополнительные движения по счетам, не создавая отдельный документ в журнале, правильнее задействовать механизм движения самого проводимого документа:
Процедура ОбработкаПроведения()
// Работаем напрямую с операцией текущего документа
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоДебету;
Операция.Кредит.Счет = СчетПоКредиту;
Операция.Сумма = СуммаОперации;
// При завершении проведения платформа сама запишет проводки
КонецПроцедуры
Если бизнес-процесс требует именно создания отдельного независимого документа «Операция» (например, для корректировки остатков до проведения основного документа), создание этой операции необходимо полностью вынести за пределы проведения.
Рассмотрим алгоритм реализации через форму документа:
ПриЗаписи().
// Пример создания независимой операции из модуля формы
Процедура СформироватьКорректировку()
ДокОперация = СоздатьОбъект("Документ.Операция");
ДокОперация.Новый();
ДокОперация.ДатаДок = ДатаДок;
ДокОперация.Записать();
Оп = СоздатьОбъект("Операция");
Оп.НайтиОперацию(ДокОперация.ТекущийДокумент());
// Заполнение проводок...
Оп.НоваяПроводка();
Оп.Дебет.Счет = СчетПоДебету;
Оп.Кредит.Счет = СчетПоКредиту;
Оп.Сумма = СуммаОперации;
Оп.Записать();
Сообщить("Корректирующая операция успешно создана: " + ДокОперация.ТекущийДокумент());
КонецПроцедуры
Если создание операции должно происходить автоматически при отмене проведения, в форме документа можно перехватить факт отказа проведения и передать процедуру создания операции в фоновую обработку через ОбработкаОжидания("ИмяПроцедуры", 1). Данный метод выполнит код через 1 секунду — уже после того, как платформа полностью завершит транзакцию проведения и снимет все блокировки.
Главное правило при работе с 1С 7.7: нельзя создавать, модифицировать и записывать сторонние транзакционные объекты (другие документы и операции) внутри процедуры ОбработкаПроведения(). Для корректной работы всегда разделяйте процесс создания подчинённых/вспомогательных объектов и процесс проведения основного документа на уровне контекста формы.