Как выбрать двух сотрудников в одном реквизите «Ответственный», не меняя его тип?

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

В практике разработки на платформе 1С:Предприятие часто возникает ситуация, когда бизнес-логика требует указания двух или более ответственных лиц в документе. Однако стандартная архитектура подразумевает, что реквизит Ответственный имеет тип СправочникСсылка.Сотрудники (или Пользователи), что физически позволяет хранить только одну ссылку (один GUID) в базе данных. Попытка «впихнуть» два значения в одно поле без изменения типа данных невозможна на уровне СУБД, но мы можем рассмотреть несколько эффективных обходных путей, которые позволят решить задачу, сохранив чистоту конфигурации.

Анализ технического ограничения

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

Решение №1: Использование дополнительных реквизитов (БСП)

Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), самым правильным и «бескровным» методом будет использование механизма дополнительных реквизитов. Рассмотрим подробнее этот алгоритм:

  1. Перейдем в раздел Администрирование — Общие настройки — Дополнительные реквизиты и сведения.
  2. Найдем в списке нужный нам тип документа (например, «Реализация товаров и услуг»).
  3. Добавим новый дополнительный реквизит с наименованием «Второй ответственный» и типом значения СправочникСсылка.Сотрудники.
  4. Настроим видимость реквизита на форме.

Преимущество: Этот метод не требует программирования и изменения конфигурации. Реквизит будет доступен в отчетах и при обновлении системы не возникнет никаких конфликтов.

Решение №2: Расширения конфигурации

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

  1. Создадим новое Расширение конфигурации.
  2. Добавим в расширение объект метаданных (документ), в котором нужно реализовать выбор.
  3. В самом расширении добавим новый реквизит Ответственный2 с нужным типом.
  4. Вынесем это поле на форму документа.

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


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

Решение №3: Реализация через регистр сведений (внешнее хранение)

Иногда требуется хранить не просто двух, а произвольное количество сотрудников. В этом случае создавать множество реквизитов нецелесообразно. Рассмотрим вариант с использованием регистра сведений. Выясним причину, почему это удобно: данные хранятся отдельно, не раздувают таблицу самого документа и позволяют строить сложные отчеты в разрезе всех ответственных.

Создадим независимый регистр сведений ДополнительныеОтветственные со следующей структурой:

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


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ДополнительныеОтветственные.Сотрудник
        |ИЗ
        |	РегистрСведений.ДополнительныеОтветственные КАК ДополнительныеОтветственные
        |ГДЕ
        |	ДополнительныеОтветственные.Объект = &Объект";
    
    Запрос.УстановитьПараметр("Объект", ТекущийОбъект.Ссылка);
    // Заполняем виртуальный реквизит формы (Массив или СписокЗначений)
    Результат = Запрос.Выполнить().Выгрузить();
    // Логика отображения на форме...
КонецПроцедуры

Решение №4: Виртуальный реквизит и программная упаковка

Рассмотрим более экзотический, но рабочий метод, который упоминался в обсуждении как «костыль», но имеющий право на жизнь при жестких ограничениях. Мы можем оставить основной реквизит Ответственный как есть, но на форме вместо него показывать Поле списка или Поле ввода со строковым типом.

Проанализируем ситуацию: пользователь выбирает двух сотрудников в специальном окне подбора, а программа сохраняет их ссылки в скрытую таблицу или упаковывает в строковый комментарий/служебное поле. Посмотрим на пример реализации логики выбора:

  1. Создаем на форме документа реквизит ВыбранныеСотрудникиТекст (тип Строка).
  2. При нажатии на кнопку выбора открываем форму подбора из справочника Сотрудники с множественным выбором.
  3. Результат выбора помещаем в массив и преобразуем в строку для отображения пользователю.

Важный момент: Для того чтобы эти данные не потерялись, их нужно записывать в сопутствующий объект. Например, можно использовать тип ХранилищеЗначения, если реквизиты объекта менять разрешено, но нужно сохранить именно коллекцию (Массив ссылок).

Решение №5: Использование табличных частей

С точки зрения классической архитектуры 1С, если у объекта может быть более одного значения одного типа, должна использоваться Табличная часть. Разберем, как сделать это максимально удобно для пользователя:

  1. Добавим ТЧ СоставОтветственных с единственным реквизитом Сотрудник.
  2. На форме документа выведем эту таблицу, но ограничим ее высоту, чтобы она выглядела как небольшое поле.
  3. Добавим проверку: если в таблице больше двух записей — выдавать предупреждение (если бизнес-логика строго ограничена двумя людьми).

Посмотрим на пример кода валидации перед записью:


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

Итоги и рекомендации

Выяснив причины и проанализировав все способы, можно сделать следующий вывод. Если вы работаете в современной типовой конфигурации — используйте Дополнительные реквизиты. Это самый безопасный метод. Если вы занимаетесь кастомной разработкой и вам важна производительность отчетов — выбирайте Регистр сведений или Табличную часть.

Помните, что попытки «склеивать» фамилии двух сотрудников в одно текстовое поле справочника (как предлагалось в одном из шутливых советов на форуме) — это путь к деградации данных. Вы не сможете построить отчет по конкретному сотруднику, не сможете проверить его права доступа и корректно вывести данные в печатные формы. Используйте типизированные ссылки и штатные механизмы платформы 1С:Предприятие 8.3.

← На главную