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