Часто в практике разработки на 1С возникает задача: при проведении одного документа нужно автоматически создать и провести ряд связанных документов. Многие разработчики пытаются реализовать это прямо внутри процедуры ОбработкаПроведения, используя блоки НачатьТранзакцию() и Попытка...Исключение. Однако при возникновении любой ошибки в дочернем документе вся транзакция становится «битой», что приводит к невозможности завершить проведение основного документа.
Давайте разберем, почему это происходит и как правильно организовать такой процесс, чтобы не нарушить целостность данных и стабильность системы.
Главная причина заключается в том, что платформа 1С:Предприятие не поддерживает вложенные транзакции в классическом понимании. Процедура ОбработкаПроведения уже выполняется в рамках транзакции, которую открывает сама платформа. Когда вы пытаетесь вызвать НачатьТранзакцию() внутри этой процедуры, вы не открываете независимый уровень, а пытаетесь управлять текущим системным процессом.
Если в процессе создания дочернего документа возникает ошибка (например, нехватка остатков или нарушение прав), СУБД помечает текущую транзакцию как нерабочую. После этого любая попытка обращения к базе данных или завершения транзакции (ЗафиксироватьТранзакцию()) будет вызывать исключение. В итоге, даже попытка обработать исключение внутри кода не спасает, так как «битая» транзакция блокирует работу сеанса до самого выхода из процедуры.
Рассмотрим несколько стратегий, которые позволят реализовать бизнес-задачу без использования опасных конструкций.
Это самый архитектурно верный подход. Суть метода заключается в разделении проведения основного документа и создания зависимых сущностей.
ОбработкаПроведения основного документа запишите данные о необходимости создания связных документов в отдельный РегистрСведений («ОчередьЗаданий»).ПослеЗаписи или регламентным заданием по расписанию) запустите фоновое задание.Преимущества: ошибка в создании дочернего документа никак не влияет на основной документ, проведение которого прошло успешно.
Если логика требует немедленной реакции пользователя или если создание документов не обязательно должно быть автоматическим «по щелчку» проведения, перенесите логику в отдельную команду.
Создайте кнопку на форме документа, например, «Сформировать связанные документы». В обработчике команды вы можете выполнять создание документов в блоке НачатьТранзакцию() — в этом случае вы будете полностью контролировать транзакцию, так как она не будет «обернута» в системное проведение.
Процедура КомандаСформироватьСвязанные(Команда)
НачатьТранзакцию();
Попытка
// Логика создания и проведения документов
СоздатьДокумент1();
СоздатьДокумент2();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Ошибка при создании документов: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Не пытайтесь бороться с «битой» транзакцией проверками типа Если ТранзакцияАктивна() Тогда. Как было выяснено в ходе обсуждений на форумах, в рамках ОбработкаПроведения этот флаг почти всегда будет возвращать Истина, даже если транзакция уже не подлежит фиксации из-за возникшей ранее ошибки.
Также избегайте попыток «откатить» часть движений внутри одной процедуры ОбработкаПроведения через ОтменитьТранзакцию(). Это гарантированно приведет к тому, что транзакция станет неактивной для записи, и вы получите ошибку о невозможности завершения транзакции.
Если бизнес требует, чтобы при проведении документа создавались другие документы, следуйте этим рекомендациям:
ОбработкаПроведения, если эти документы критически важны для системы и могут вызвать ошибки при записи.РегламентныеЗадания и очереди сообщений в регистрах сведений. Это современный стандарт разработки, обеспечивающий высокую стабильность и производительность конфигурации.Помните, что проведение документа — это критически важный процесс, который должен работать быстро и предсказуемо. Не перегружайте его «тяжелыми» процедурами создания цепочек документов.