Почему возникает ошибка при вызове ОткрытьФормуМодально в клиент-серверной базе 1С и как правильно проверять заполнение реквизитов?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При переводе информационной базы 1С из файлового режима в клиент-серверный вариант (SQL Server) разработчики нередко сталкиваются с ошибками выполнения кода, который ранее успешно работал. Типичный пример — сбой фонового обмена данными в распределенной информационной базе (РИБ) или падение транзакции проведения документа из-за вызова модальных окон. Разберем подробно, почему интерактивные методы вызывают критические сбои на сервере, к каким последствиям для СУБД это приводит и как правильно организовать контроль заполнения реквизитов.

Причины возникновения ошибки в клиент-серверном режиме

Проанализируем ситуацию, когда в модуле объекта документа (например, в процедуре ОбработкаПроведения или при вызове вспомогательных процедур записи) размещен следующий код:


Процедура ПроверкаЗаполненияПродавец(Продавец)
    Если Продавец.Пустая() Тогда
        Продавец = ОткрытьФормуМодально("Справочник.ФизическиеЛица.ФормаВыбора",,Продавец);
    КонецЕсли;
КонецПроцедуры

В файловой однопользовательской базе данный фрагмент работает без видимых исключений, если запись инициирована пользователем через интерфейс. Однако при переходе на SQL Server и настройке обменов возникают критические проблемы:

  1. Отсутствие пользовательского интерфейса на стороне сервера. В клиент-серверной архитектуре обработка проведения документов, регламентные задания и синхронизация РИБ выполняются в контексте сервера или фонового процесса. На сервере 1С графический интерфейс полностью отсутствует. Попытка вызова методов ОткрытьФорму, ОткрытьФормуМодально, Предупреждение или Вопрос приводит к аварийной остановке с ошибкой недоступности интерактивных операций.
  2. Особенности работы механизмов РИБ. При загрузке сообщений обмена объектам принудительно устанавливается режим ОбменДанными.Загрузка = Истина. Загрузка пакетов выполняется пакетно на сервере. Интерактивные запросы блокируют процесс чтения XML и срывают автоматическую синхронизацию.
  3. Зависание транзакций и блокировки таблиц в SQL Server. Если модальное окно открывается внутри транзакции записи или проведения, СУБД накладывает монопольные блокировки на строки и таблицы. Пока открыт диалог с пользователем, транзакция остается незавершенной. Другие сеансы, пытающиеся обратиться к заблокированным таблицам, зависают по таймауту ожидания блокировки или завершаются взаимоблокировкой (deadlock).
  4. Проблемы пакетных операций. При групповом перепроведении документов или восстановлении последовательности модальные вызовы прерывают автоматическую обработку тысяч документов.

Вариант 1. Перенос проверки в модуль формы документа (интерактивный уровень)

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

Разберем по шагам правильную реализацию в модуле формы (для обычного приложения):


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

В этом случае модальный диалог отрабатывает строго на клиенте до открытия серверной транзакции записи. Если документ проводится программно, через фоновое задание или загружается по РИБ, модуль формы вообще не инициализируется, и ошибка не возникает.

Вариант 2. Контроль заполнения на уровне метаданных и модуля объекта

Для гарантированной проверки данных независимо от того, как записывается объект (интерактивно через форму или программно из внешних источников), правила платформы 1С требуют разделять логику проверки и интерфейс.

Посмотрим, как организовать неинтерактивную проверку:

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

Для визуального выделения поля на форме включим у соответствующего элемента управления свойство АвтоОтметкаНезаполненного = Истина. При таком подходе пользователь сразу видит обязательное поле, а транзакции SQL Server не удерживают блокировки в ожидании действий оператора.

← На главную