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