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