Как реализовать связь параметров выбора справочника в зависимости от даты документа или версии НСИ

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

В процессе разработки часто возникает задача ограничить список доступных для выбора элементов справочника в зависимости от контекста документа. Типичный пример — медицинские специальности или товарные позиции, которые имеют определенный период действия или привязаны к конкретным версиям нормативно-справочной информации (НСИ). Разберем, как реализовать такую фильтрацию эффективно, чтобы система работала быстро даже при наличии нескольких тысяч элементов.

Анализ архитектуры хранения данных: Табличная часть или Регистр сведений

Прежде чем приступать к программному коду, проанализируем, где лучше хранить информацию о вхождении элемента в ту или иную версию НСИ. В исходной постановке задачи упоминается использование табличной части самого справочника. Однако для целей фильтрации в динамических списках и формах выбора это решение имеет существенные недостатки.

Рассмотрим причины, по которым использование регистра сведений предпочтительнее:

  1. Производительность: При фильтрации по табличной части платформа генерирует сложные SQL-запросы с использованием операторов EXISTS или JOIN, что на больших объемах данных (от 4000 элементов и выше) может привести к замедлению открытия формы выбора.
  2. Индексация: В независимом регистре сведений мы можем четко задать измерения (например, Версия и Специальность), что обеспечит мгновенный поиск по индексам.
  3. Гибкость: Регистр позволяет легко хранить дополнительные сведения о периоде действия версии, не меняя структуру справочника.

Поэтому в качестве первого шага разберем создание независимого регистра сведений СоставВерсийНСИ с измерениями ВерсияНСИ (Тип: СправочникСсылка.ВерсииНСИ) и Специальность (Тип: СправочникСсылка.Специальности).

Способ 1: Использование механизма «Связи параметров выбора»

Если в вашем документе есть реквизит ВерсияНСИ, который однозначно определяет актуальный набор специальностей, мы можем воспользоваться стандартным механизмом платформы без написания сложного кода. Выясним, как это настроить в конфигураторе.

В свойствах реквизита документа Специальность найдем поле Связи параметров выбора. Здесь можно настроить соответствие между полем документа ВерсияНСИ и полем отбора в форме выбора справочника. Если бы мы использовали подчинение (владелец), это настраивалось бы через Отбор.Владелец. Но так как у нас связь через регистр или ТЧ, стандартная настройка напрямую может быть ограничена.

В таких случаях лучше использовать программную установку параметров в событии НачалоВыбора.

Способ 2: Программная установка отбора в событии НачалоВыбора

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

Посмотрим на пример реализации в модуле формы документа:


&НаКлиенте
Процедура СпециальностьНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь; // Отменяем стандартное открытие, чтобы передать свои параметры
    
    // Определяем параметры для открытия формы выбора
    ПараметрыВыбора = Новый Структура;
    
    // Формируем структуру отбора
    СтруктураОтбора = Новый Структура;
    
    // Получаем массив актуальных ссылок на сервере
    МассивРазрешенныхСсылок = ПолучитьАктуальныеСпециальностиНаСервере(Объект.Дата);
    
    // Устанавливаем отбор по ссылке (вхождение в массив)
    СтруктураОтбора.Вставить("Ссылка", МассивРазрешенныхСсылок);
    
    ПараметрыВыбора.Вставить("Отбор", СтруктураОтбора);
    
    // Открываем форму выбора справочника "Специальности"
    ОткрытьФорму("Справочник.Специальности.ФормаВыбора", ПараметрыВыбора, Элемент);
    
КонецПроцедуры

Разберем серверную функцию получения данных:


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

Способ 3: Настройка динамического списка формы выбора

Иногда требуется не просто передать массив, а полностью изменить логику работы формы выбора, например, если нужно выводить дополнительные колонки или использовать сложные условия. В этом случае мы можем передать в форму выбора параметр (например, ВерсияНСИ), а в самой форме выбора настроить ДинамическийСписок.

В событии ПриСозданииНаСервере формы выбора справочника мы можем программно изменить текст запроса динамического списка:


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

Важные нюансы при работе с историей выбора

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

Чтобы избежать этой ситуации, выполним следующие действия:

Обработка "заднего числа"

Ситуация, когда документ правится "задним числом", требует особого внимания. Если пользователь меняет дату документа, актуальная версия НСИ может измениться. Следовательно, уже выбранная специальность может стать неактуальной для этой даты.

Рекомендуется следующий алгоритм действий:

  1. В событии ПриИзменении даты документа проверять, остается ли текущая специальность актуальной для новой даты.
  2. Если специальность более не входит в актуальную версию, выводить предупреждение пользователю или очищать поле (в зависимости от бизнес-логики).
  3. Обновлять параметры выбора для поля Специальность, чтобы при следующем нажатии кнопки выбора открылся верный список.

Заключение и выводы

Мы рассмотрели несколько подходов к решению задачи. Для небольших справочников (до 1000 элементов) вполне допустимо использование табличных частей и передача массива ссылок. Однако для профессиональной разработки и обеспечения высокой производительности системы оптимальным является использование независимого регистра сведений в сочетании с модификацией запроса динамического списка в форме выбора.

Помните, что "красота" решения в 1С заключается не только в краткости кода, но и в том, насколько стабильно оно будет работать при росте базы данных. Использование индексов регистра сведений — это залог того, что через год, когда количество версий НСИ вырастет, ваши документы будут открываться так же быстро, как и в первый день.

← На главную