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