Как реализовать интерактивный выбор элемента при вводе документа на основании в 1С?

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

При разработке прикладных решений часто возникает сценарий: на основании одного исходного документа необходимо создать подчиненный, однако состав данных требует интерактивного участия пользователя. Например, в документе-источнике содержится табличная часть с перечнем объектов, и на каждый объект разрешено сформировать только один подчиненный документ. Если пользователь инициирует создание, система должна показать только те позиции, по которым подчиненные документы еще не оформлены, а если свободных объектов не осталось — предупредить и отменить операцию.

Разберем архитектурные ограничения платформы 1С:Предприятие 8.3 и выясним причину, почему стандартная процедура ОбработкаЗаполнения не позволяет решить данную задачу «в лоб», а также рассмотрим проверенные способы реализации требуемого поведения.

Архитектурные ограничения процедуры ОбработкаЗаполнения

Проанализируем, почему вызов методов отображения диалогов (таких как ПоказатьВыборИзСписка или ПоказатьВыборЭлемента) невозможен внутри события ОбработкаЗаполнения:

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

Решение 1: Собственная команда на форме с передачей параметров заполнения

Рассмотрим основной и наиболее гибкий способ, к которому пришел автор темы: вынесение интерактивного взаимодействия на клиента до момента инициализации нового документа.

Вместо стандартного системного механизма ввода на основании мы создаем собственную команду на форме документа-источника. Разберем по шагам алгоритм ее работы:

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

Посмотрим на пример клиентского кода команды в форме документа-источника:


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

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

Теперь разберем, как подчиненный документ принимает эти данные. В модуле объекта подчиненного документа обработчик ОбработкаЗаполнения считывает переданную структуру из параметра ДанныеЗаполнения:


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

Решение 2: Отмена создания в событии формы ПриСозданииНаСервере

Если необходимо сохранить стандартную командную панель платформы («Создать на основании»), можно использовать обработчик формы подчиненного документа.

В этом сценарии стандартное заполнение по ссылке на документ-основание отрабатывает штатно в модуле объекта, а проверку и блокировку открытия формы мы переносим в форму документа-приемника. Рассмотрим подробнее реализацию в событии ПриСозданииНаСервере:


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

Если в ПриСозданииНаСервере выставить флаг Отказ = Истина, форма не будет создана и не откроется на клиенте.

Решение 3: Использование промежуточной формы-мастера

Для сохранения типовой команды ввода на основании в модуле менеджера подчиненного документа можно переопределить обработчик ОбработкаПолученияФормы. Проанализируем эту схему:

  1. Система перехватывает запрос на получение основной формы объекта при наличии параметров ввода на основании.
  2. Вместо формы документа открывается специализированная обработка-помощник (мастер ввода).
  3. Пользователь в диалоговом окне видит доступные остатки или варианты выбора.
  4. После подтверждения форма-помощник программно формирует готовый документ или открывает его форму с заполненными параметрами.

Контроль целостности данных и защита от дублей

Важно помнить: любая проверка доступных объектов на клиенте или перед открытием формы защищает только от случайных ошибок пользователя при последовательной работе. Если два пользователя одновременно нажмут команду создания документа, они оба увидят один и тот же свободный объект.

Для обеспечения строгой целостности данных разберем следующие правила:

  1. Хранение связей: Рекомендуется фиксировать связь документа-основания и выбранного объекта в отдельном регистре сведений.
  2. Контроль при проведении: Окончательную проверку уникальности пары «Основание — Объект» необходимо выполнять в обработчике ОбработкаПроведения подчиненного документа с установкой управляемых блокировок в транзакции. Это исключит появление дублирующих документов при параллельной работе нескольких пользователей.
← На главную