В типовых конфигурациях 1С (ERP, КА, УТ) сущности партнеров (управленческий учет) и контрагентов (регламентированный учет) разделены. Часто у одного партнера может быть зарегистрировано несколько юридических лиц (контрагентов). При попытке соединить эти таблицы в запросе динамического списка разработчики сталкиваются с тем, что строки партнера не дублируются под каждого контрагента, либо список начинает работать некорректно.
Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим проверенные способы реализации требуемого интерфейса и поиска.
Проанализируем механику работы динамического списка. Когда в свойствах списка заполнено свойство Основная таблица (например, Справочник.Партнеры), платформа использует ключевое поле (Ссылка) для идентификации строк на клиенте, порционного считывания данных и кэширования.
Если в тексте запроса используется соединение ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты, возвращающее несколько строк на одну ссылку партнера, платформа при отрисовке интерфейса сворачивает дубли по первичному ключу. В итоге отображается только одна из записей либо связанные поля не отображаются вовсе.
Если очистить свойство Основная таблица, строки с дублирующимися ссылками отобразятся, однако это повлечет критические последствия:
Рассмотрим альтернативные варианты решения задачи без отключения основной таблицы.
Этот способ позволяет вывести список наименований всех контрагентов партнера (например, через запятую или с переносом строк) в отдельной колонке формы списка без изменения структуры метаданных.
Разберем по шагам порядок действий:
Строка, не связывая ее с реквизитами динамического списка.ПриПолученииДанныхНаСервере.Посмотрим на пример программного кода:
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, УмеренныеДанные, ОформленияСтрок)
МассивСсылок = Новый Массив;
Для Каждого СтрокаОформления Из ОформленияСтрок Цикл
МассивСсылок.Добавить(СтрокаОформления.КлючЗаписи);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Партнер КАК Партнер,
| Контрагенты.Наименование КАК Наименование
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Партнер В(&МассивСсылок)";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Выборка = Запрос.Выполнить().Выбрать();
СоответствиеКонтрагентов = Новый Соответствие;
Пока Выборка.Следующий() Цикл
ТекСтрока = СоответствиеКонтрагентов[Выборка.Партнер];
Если ТекСтрока = Неопределено Тогда
СоответствиеКонтрагентов.Вставить(Выборка.Партнер, Выборка.Наименование);
Иначе
СоответствиеКонтрагентов.Вставить(Выборка.Партнер, ТекСтрока + ", " + Выборка.Наименование);
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаОформления Из ОформленияСтрок Цикл
НайденныеКонтрагенты = СоответствиеКонтрагентов[СтрокаОформления.КлючЗаписи];
Если НайденныеКонтрагенты <> Неопределено Тогда
СтрокаОформления.Ячейки.КолонкаКонтрагенты.УстановитьТекст(НайденныеКонтрагенты);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Ограничение метода: по колонкам, сформированным динамически в оформлении строк, не работает стандартная строковая фильтрация платформы.
Если пользователям необходим быстрый типовой поиск и сортировка по наименованиям контрагентов прямо в списке партнеров, оптимальным решением является денормализация.
Реализуем данный подход следующим образом:
Партнеры реквизит КонтрагентыСтрокой (строка неограниченной длины или фиксированной длины с включенным индексированием).ПриЗаписи и ПередУдалением для справочника Контрагенты.КонтрагентыСтрокой в динамический список. По нему будут работать полнотекстовый поиск, стандартный поиск платформы и отборы.Если менять структуру метаданных нельзя, а реализовать поиск партнера по наименованию или ИНН его контрагентов необходимо, используем параметризацию запроса динамического списка.
Добавим в текст запроса динамического списка условие отбора:
ГДЕ
&СтрокаПоиска = ""
ИЛИ Партнеры.Ссылка В (
ВЫБРАТЬ
Контрагенты.Партнер
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Наименование ПОДОБНО &СтрокаПоискаШаблон
ИЛИ Контрагенты.ИНН ПОДОБНО &СтрокаПоискаШаблон
)
На форме списка размещаем пользовательское поле ввода для поиска и при его изменении передаем значения в параметры динамического списка:
&НаКлиенте
Процедура ПолеПоискаПриИзменении(Элемент)
Список.Параметры.УстановитьЗначениеПараметра("СтрокаПоиска", ПолеПоиска);
Список.Параметры.УстановитьЗначениеПараметра("СтрокаПоискаШаблон", "%" + ПолеПоиска + "%");
КонецПроцедуры
Для сохранения типовой функциональности списка партнеров (панели фильтров, контактная информация, сегменты) и удобного просмотра связанных контрагентов можно разместить на форме списка подчиненную таблицу:
Справочник.Контрагенты.ГДЕ Контрагенты.Партнер = &ТекущийПартнер.СписокПриАктивизацииСтроки основного списка партнеров обновляем параметр ТекущийПартнер подчиненного списка.Такой подход обеспечивает максимальное быстродействие, сохраняет все стандартные возможности платформы и дает пользователю полную информацию обо всех контрагентах текущего выбранного партнера.