Как запросить параметры у пользователя при записи документа в управляемых формах 1С?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

При переводе конфигураций с обычного приложения на управляемые формы разработчики нередко сталкиваются с ситуацией, когда в обычном приложении в модуле объекта внутри события ПередЗаписью вызывалось модальное диалоговое окно для ввода недостающих параметров. В управляемом приложении такой подход вызывает ошибку: метод ОткрытьФорму() недоступен на сервере. Проанализируем, почему возникает данное ограничение платформы 1С и как правильно перестроить архитектуру решения под современные стандарты разработки.

Выясним причину ошибки. В клиент-серверной архитектуре управляемого приложения сервер не имеет визуального контекста: на сервере нет экранных форм, модальных окон и диалогов взаимодействия с пользователем. Кроме того, транзакция записи объекта не может быть приостановлена в ожидании действий человека. Если бы сервер ждал реакции пользователя, строки таблиц в базе данных оставались бы заблокированными на неопределенный срок, что привело бы к взаимным блокировкам (deadlock) и тайм-аутам у других пользователей системы. Также серверный код модулей объектов выполняется в фоновых потоках, регламентных заданиях и веб-сервисах, где интерактивный пользовательский интерфейс отсутствует вовсе.

Рассмотрим, какими способами можно правильно организовать интерактивный ввод параметров перед записью и проведением документа.

Способ 1. Программное добавление реквизитов и элементов на форму

Если требуется добавить ввод параметров в большое количество однотипных форм конфигурации, не изменяя вручную каждую форму в конфигураторе, воспользуемся возможностью динамического создания реквизитов и элементов управления на сервере.

Разберем по шагам реализацию этого механизма:

  1. Создадим общий модуль (например, МодификацияФормКлиентСервер), в котором разместим логику добавления реквизитов и полей ввода.
  2. Вызовем процедуру общего модуля в обработчике события формы ПриСозданииНаСервере. Если типовая конфигурация использует механизм БСП, врезку можно сделать в общую точку подключения, например ДополнительныеОтчетыИОбработки.ПриСозданииНаСервере, либо подключить через расширение с аннотацией &После("ПриСозданииНаСервере").
  3. В модуле программно добавим новые реквизиты в коллекцию формы через ИзменитьРеквизиты() и свяжем с ними созданные элементы управления.

Посмотрим на пример процедуры добавления полей ввода в форму на сервере:


Процедура ДобавитьПоляПараметров(Форма) Экспорт
    
    // Создаем массив добавляемых реквизитов
    МассивРеквизитов = Новый Массив;
    МассивРеквизитов.Добавить(Новый РеквизитФормы("ДополнительныйПараметр", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(100))));
    
    Форма.ИзменитьРеквизиты(МассивРеквизитов);
    
    // Создаем элемент формы для отображения реквизита
    Элемент = Форма.Элементы.Добавить("ПолеДополнительныйПараметр", Тип("ПолеФормы"), Форма);
    Элемент.Вид = ВидПоляФормы.ПолеВвода;
    Элемент.ПутьКДанным = "ДополнительныйПараметр";
    Элемент.Заголовок = "Дополнительный параметр";
    
КонецПроцедуры

При таком подходе данные вводятся пользователем штатно в открытой форме документа до нажатия кнопок проведения и записи.

Способ 2. Двухэтапный асинхронный диалог в событии ПередЗаписью формы

Если бизнес-логика требует вызова отдельного диалогового окна именно перед нажатием кнопок «Записать» или «Провести», перенесем логику проверки с модуля объекта на клиентский уровень формы в процедуру ПередЗаписью(Отказ, ПараметрыЗаписи).

Разберем алгоритм двухэтапного подтверждения без использования модальности:

  1. В клиентском обработчике ПередЗаписью формы проверяем, заполнены ли требуемые параметры во временной переменной или реквизите.
  2. Если параметры не заполнены, прерываем стандартную запись установкой флага Отказ = Истина.
  3. Сохраняем текущую структуру ПараметрыЗаписи в переменную формы.
  4. Открываем диалоговую форму ввода значений с помощью метода ОткрытьФорму() или ПоказатьВводЗначения(), передав в качестве параметра объект ОписаниеОповещения.
  5. В процедуре-обработчике оповещения считываем введенные пользователем данные, сохраняем их в контексте формы и повторно вызываем метод Записать(СохраненныеПараметрыЗаписи).
  6. При повторном входе в процедуру ПередЗаписью проверка параметров успешно проходит, флаг Отказ не устанавливается, и объект записывается на сервере.

Посмотрим на пример реализации данного алгоритма в модуле формы:


&НаКлиенте
Перем СтруктураПараметровЗаписи;

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    
    // Если параметр уже получен на предыдущем шаге, продолжаем запись
    Если ЗначениеЗаполнено(ЭтотОбъект.ВведенныйПараметр) Тогда
        Возврат;
    КонецЕсли;
    
    // Прерываем текущую запись и запоминаем контекст вызова
    Отказ = Истина;
    СтруктураПараметровЗаписи = ПараметрыЗаписи;
    
    // Настраиваем обработчик оповещения
    Оповещение = Новый ОписаниеОповещения("ПослеВводаПараметра", ЭтотОбъект);
    ПоказатьВводЗначения(Оповещение, "", "Введите параметр для проведения:");
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаПараметра(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = Неопределено Тогда
        // Пользователь нажал "Отмена"
        Возврат;
    КонецЕсли;
    
    ЭтотОбъект.ВведенныйПараметр = Результат;
    
    // Повторно инициируем штатную запись объекта
    Записать(СтруктураПараметровЗаписи);
    
КонецПроцедуры

Способ 3. Контроль заполнения параметров в модуле объекта и отказ с сообщением

Рассмотрим случай, когда проведение документа запускается не из формы, а из списка документов или в рамках программного вызова. В этом случае правильный архитектурный паттерн платформы 1С строится по следующей схеме:

  1. В обработчике ОбработкаПроведения модуля объекта или в подписке на событие проверяем наличие требуемых данных в объекте или во временном свойстве ДополнительныеСвойства.
  2. Если данных нет, формируем понятное пользователю сообщение через объект СообщениеПользователю, устанавливаем параметр Отказ = Истина и завершаем проведение.
  3. Для проведения «не из формы» в форме динамического списка перехватываем событие ПередНачаломПроведения на клиенте, где проверяем готовность выбранных документов к проведению. При отсутствии параметров отменяем операцию, запрашиваем значения через диалог и передаем их в процедуру проведения.

Посмотрим на пример серверной проверки в модуле объекта:


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

Таким образом, разделение логики на клиентскую интерактивную часть и строгую серверную проверку обеспечивает стабильную работу конфигурации без взаимных блокировок, зависаний сеансов и ошибок выполнения на сервере.

← На главную