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