При разработке прикладных решений на платформе 1С:Предприятие часто возникает задача создать универсальное поле, которое могло бы принимать значения из разных источников. Классический пример — документ Поступление в кассу, где источником оплаты может выступать как Контрагент, так и Сотрудник или Физическое лицо. В этой статье мы подробно разберем, как реализовать такой механизм правильно, избежав типичных ошибок новичков и проблем с производительностью базы данных.
Первое, что нам необходимо усвоить: в 1С нет необходимости создавать несколько скрытых реквизитов для хранения ссылок разных типов. Платформа обладает встроенным механизмом, который называется Составной тип данных. Рассмотрим, как это работает. При создании реквизита в конфигураторе (например, реквизита ИсточникПоступления в документе), в окне выбора типа данных мы можем отметить галочками сразу несколько справочников. Платформа сама создаст необходимые механизмы для хранения этой информации.
Рассмотрим ситуацию, когда нам нужно выбрать между справочниками Контрагенты, Сотрудники и Клиенты. Мы просто устанавливаем тип «Ссылка» для каждого из них в настройках одного реквизита. Проанализируем, что происходит в этот момент в интерфейсе пользователя: при нажатии на кнопку выбора в поле ввода система сначала предложит выбрать тип данных из списка, а затем откроет форму выбора соответствующего справочника.
Чтобы писать качественный код, мы должны понимать, как наши действия отражаются на работе СУБД. Проанализируем внутреннюю структуру: когда вы назначаете реквизиту составной тип, 1С на уровне SQL-таблицы выделяет не одну колонку, а несколько. Обычно это:
Важный момент, который часто упускают: если вы укажете тип Любая ссылка, платформа будет вынуждена при каждом обращении к этому полю в запросе соединяться со всеми таблицами справочников, существующих в системе. Это может привести к тому, что ваш запрос «удавит» SQL-сервер из-за огромного количества LEFT OUTER JOIN. Поэтому всегда ограничивайте состав типов только теми объектами, которые действительно необходимы.
Разберем ситуацию, когда нам нужно программно определить, ссылка какого типа хранится в реквизите в данный момент. Для этого в языке 1С предусмотрена функция ТипЗнч(). Рассмотрим пример кода, который можно использовать в модуле формы для управления видимостью элементов в зависимости от выбранного источника:
&НаКлиенте
Процедура ИсточникПоступленияПриИзменении(Элемент)
ТекущееЗначение = Объект.ИсточникПоступления;
// Проверяем тип выбранного значения
Если ТипЗнч(ТекущееЗначение) = Тип("СправочникСсылка.Контрагенты") Тогда
// Выполняем действия для контрагента
Сообщить("Выбран контрагент: " + ТекущееЗначение);
ИначеЕсли ТипЗнч(ТекущееЗначение) = Тип("СправочникСсылка.Сотрудники") Тогда
// Выполняем действия для сотрудника
Сообщить("Выбран сотрудник");
КонецЕсли;
КонецПроцедуры
Если же вам необходимо найти элемент справочника программно по наименованию и записать его в такой реквизит, помните, что нужно обращаться к менеджеру конкретного справочника. Посмотрим на пример:
&НаСервере
Процедура НайтиИУстановитьИсточник(ИмяПоиска, ВидОбъекта)
Если ВидОбъекта = "Клиент" Тогда
НайденнаяСсылка = Справочники.Клиенты.НайтиПоНаименованию(ИмяПоиска);
Иначе
НайденнаяСсылка = Справочники.Контрагенты.НайтиПоНаименованию(ИмяПоиска);
КонецЕсли;
Если Не НайденнаяСсылка.Пустая() Тогда
Объект.ИсточникПоступления = НайденнаяСсылка;
КонецЕсли;
КонецПроцедуры
Работа с составными типами в запросах требует особого внимания. Выясним причину возможных тормозов: если вы просто напишете Запрос.ИсточникПоступления.ИНН, и в составном типе есть 10 справочников, 1С попытается найти поле ИНН в каждом из них. Правильный подход заключается в использовании операторов ССЫЛКА и ВЫРАЗИТЬ.
Рассмотрим пример правильного запроса, где мы получаем ИНН только если источником является Контрагент:
ВЫБРАТЬ
ВЫБОР
КОГДА Док.ИсточникПоступления ССЫЛКА Справочник.Контрагенты
ТОГДА ВЫРАЗИТЬ(Док.ИсточникПоступления КАК Справочник.Контрагенты).ИНН
ИНАЧЕ ""
КОНЕЦ КАК ИНН_Контрагента
ИЗ
Документ.ПоступлениеВКассу КАК Док
Использование ВЫРАЗИТЬ — это критически важный момент для производительности. Это «подсказка» платформе, что в данной ветке условия значение нужно трактовать как конкретный тип, что позволяет системе построить оптимальный SQL-план без лишних соединений.
Проанализируем ситуацию: что если у вас в конфигурации 20 документов, в каждом из которых есть реквизит Источник с набором из одних и тех же справочников? Если завтра добавится новый справочник Агенты, вам придется вручную менять типы в 20 местах. Чтобы избежать этого, используйте объект метаданных Определяемый тип.
ОпределяемыйТип.СубъектОплаты.ОпределяемыйТип.СубъектОплаты.Теперь при расширении бизнеса вам достаточно изменить состав типов в одном месте. Это считается «золотым стандартом» разработки на управляемых формах.
Иногда пользователям неудобно каждый раз выбирать тип из выпадающего списка. Рассмотрим способ упрощения жизни пользователя. В свойствах поля ввода на форме есть настройка Параметры выбора и Связи параметров выбора. Если вы заранее знаете, что в определенном контексте в этом поле должен быть только Сотрудник, вы можете программно ограничить выбор:
// Пример ограничения типа выбора на лету
ЭлементОтбора = Новый ПараметрВыбора("Отбор.Статус", Перечисления.Статусы.Активен);
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(ЭлементОтбора);
Элементы.ИсточникПоступления.ПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
Также полезно знать о свойстве ВыбиратьТип. Если в реквизите уже хранится значение (например, Контрагент), то при попытке перевыбора система сразу откроет справочник Контрагентов. Если же вы хотите, чтобы пользователь всегда мог сменить тип, убедитесь, что кнопка выбора типа доступна в поле ввода.
Подведем итог нашему разбору. Использование составных типов — мощный и гибкий инструмент 1С. Главное — соблюдать баланс: не использовать «Любую ссылку» без крайней необходимости, активно применять ВЫРАЗИТЬ в запросах и группировать общие наборы типов в Определяемые типы. Такой подход гарантирует стабильную работу системы и легкость ее дальнейшей поддержки.