Как через расширение добавить поле в форму "Подписи" документа и сохранить его значение?

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

Часто возникает задача добавить в типовой документ дополнительное поле для подписи, например, «Инициатор» или «Согласовал». Классический пример — доработка документа «Реализация товаров и услуг». Разработчик добавляет реквизит в расширении, выводит его на форму подписей, но сталкивается с проблемой: после выбора значения и закрытия формы данные не сохраняются. Выясним, почему так происходит и как правильно решить эту задачу.

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

Решение 1. Доработка механизма передачи данных через код

Это классический способ, который требует понимания логики работы форм. Он дает полный контроль над процессом. Разберем его по шагам.

  1. Добавление реквизита в объект документа

    Прежде всего, данным нужно место для хранения. В расширении добавим в сам объект Документ.РеализацияТоваровУслуг новый реквизит, например, Инициатор1 с типом СправочникСсылка.ФизическиеЛица. Это обеспечит постоянное хранение информации.

  2. Добавление реквизита и элемента на форму подписей

    Теперь подготовим форму ФормаПодписиТовары. Заимствуем ее в расширение. Добавим в реквизиты формы новый реквизит с таким же именем Инициатор1 и типом. После этого перетащим его на форму, чтобы создать поле для ввода.

  3. Передача текущего значения в форму подписей

    Когда основная форма документа открывает форму подписей, она передает ей текущие значения в структуре Параметры. Нам нужно "подхватить" этот момент и прочитать значение нашего нового реквизита. Для этого создадим в расширении для модуля формы ФормаПодписиТовары обработчик события ПриСозданииНаСервере.

    Используем аннотацию &После, чтобы наш код выполнился после основного типового кода.

    
    &После("ПриСозданииНаСервере")
    Процедура Расширение_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        
        // Типовой код уже заполнил стандартные реквизиты из Параметры.
        // Теперь мы дозаполняем наш реквизит.
        ЗаполнитьЗначенияСвойств(ЭтаФорма, Параметры, "Инициатор1");
        
    КонецПроцедуры
    

    Эта простая строчка кода найдет в структуре Параметры ключ "Инициатор1" (который мы передадим из основной формы) и заполнит одноименный реквизит нашей формы подписей.

  4. Возврат измененного значения из формы подписей

    Когда пользователь заполнит поле и нажмет "ОК", форма подписей должна вернуть новые данные обратно. Это происходит в событии ПриЗакрытии. Форма формирует структуру с результатами и передает ее через механизм оповещений. Нам нужно добавить в эту структуру наше поле.

    Здесь может потребоваться аннотация &Вместо, если типовая процедура жестко определяет состав возвращаемой структуры. Проанализируем типовой код и перепишем его, добавив наш реквизит.

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

    Финальный шаг — принять данные в основной форме документа (например, ФормаДокументаТовары) и записать их в реквизит объекта. Для этого находим в модуле основной формы процедуру-обработчик оповещения от формы подписей. Обычно ее можно найти по вызову ОткрытьФорму("...ФормаПодписиТовары", ..., УникальныйИдентификатор). Имя обработчика указывается в последнем параметре.

    Создаем для этого обработчика подписчик с аннотацией &После.

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

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

Решение 2. Использование типового механизма "Дополнительные реквизиты"

Для многих задач, особенно если не требуется сложная логика, а нужно просто добавить поле для хранения данных, существует более простой и предпочтительный способ — без программирования. Он основан на использовании Библиотеки стандартных подсистем (БСП).

Преимущества этого подхода:

Как это сделать:

  1. Перейдите в раздел "Администрирование" – "Общие настройки".
  2. Найдите и включите опцию "Дополнительные реквизиты и сведения".
  3. Перейдите по ссылке "Дополнительные реквизиты".
  4. В открывшемся окне выберите из списка слева объект, который вы хотите доработать (в нашем случае — документ "Реализация (акты, накладные, УПД)").
  5. Нажмите кнопку "Добавить" и выберите "Новый".
  6. Задайте наименование реквизита (например, "Инициатор") и выберите его тип (например, Справочник.ФизическиеЛица).
  7. Сохраните настройку.

После этого в документе "Реализация товаров и услуг" появится ссылка или отдельная вкладка "Дополнительно", где и будет расположено ваше новое поле. Оно будет сохраняться и считываться автоматически.

Важный нюанс: Ошибка версионирования объектов

При добавлении нового реквизита в расширение к объекту, для которого включено версионирование (хранение истории изменений), можно столкнуться с ошибкой:

Метод объекта не обнаружен (ПриОпределенииНастроекВерсионированияОбъектов)

Причина: система версионирования не знает о существовании вашего нового реквизита и не может обработать его при записи новой версии объекта.

Неправильное решение: комментировать строку с вызовом ошибки в общем модуле ВерсионированиеОбъектов. Это приведет к проблемам при обновлении конфигурации.

Правильное решение:

  1. В расширении найдите модуль менеджера дорабатываемого документа (Документ.РеализацияТоваровУслуг).
  2. Найдите в нем экспортную процедуру ПриОпределенииНастроекВерсионированияОбъектов.
  3. Создайте для нее в расширении обработчик с аннотацией &После.
  4. В этом обработчике добавьте ваш новый реквизит в список версионируемых.

&После("ПриОпределенииНастроекВерсионированияОбъектов")
Процедура Расширение_ПриОпределенииНастроекВерсионированияОбъектов(Настройки)
    
    // Добавляем наш реквизит в коллекцию версионируемых реквизитов
    Настройки.ВерсионируемыеРеквизиты.Добавить("Инициатор1");
    
КонецПроцедуры

Этот код корректно "познакомит" систему версионирования с вашим новым реквизитом, и ошибка исчезнет.

← На главную