Как реализовать хранение настроек в разрезе типов документов для фильтрации номенклатуры

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

При разработке сложных систем автоматизации часто возникает задача создания гибких фильтров. Рассмотрим типичную ситуацию: необходимо ограничить список доступной номенклатуры в табличных частях документов (Поступление, Реализация, Списание и др.), но настройки должны задаваться не для каждого конкретного документа, а для типа документа в целом. Основная сложность заключается в том, что стандартное измерение регистра сведений требует указания конкретной ссылки на объект, а нам нужно указать «вид» объекта метаданных.

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

Способ 1. Использование справочника «Идентификаторы объектов метаданных» (стандарт БСП)

Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), то этот метод является наиболее «кошерным» и предпочтительным. В БСП существует специальный справочник ИдентификаторыОбъектовМетаданных, который хранит ссылки на все объекты конфигурации (справочники, документы, отчеты и т.д.).

Алгоритм реализации:

  1. Создадим регистр сведений (например, ДоступнаяНоменклатураПоДокументам).
  2. В качестве первого измерения укажем ТипОбъекта с типом ссылки на справочник ИдентификаторыОбъектовМетаданных.
  3. Вторым измерением добавим Номенклатура (ссылка на соответствующий справочник).
  4. Для удобства пользователя настроим связи параметров выбора, чтобы в справочнике идентификаторов можно было выбирать только документы.

Рассмотрим, как программно получить идентификатор типа документа для поиска в регистре:


// Получаем ссылку на идентификатор метаданных по ссылке на документ
ИдентификаторДокумента = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(ТипЗнч(СсылкаНаДокумент));

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

Запрос.УстановитьПараметр("ТипОбъекта", ИдентификаторДокумента);
СписокНоменклатуры = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Номенклатура");

Этот метод хорош тем, что ссылки на идентификаторы сохраняют свою целостность при переименовании объектов в конфигураторе, так как БСП отслеживает такие изменения.

Способ 2. Хранение имени типа в строковом измерении

Если вы работаете в небольшой самописной конфигурации без БСП, проще всего использовать строковое представление типа объекта. Это надежное и быстрое решение, которое не требует создания лишних объектов в метаданных.

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Очищаем и заполняем список выбора для строкового реквизита
    СписокТипов = Элементы.ИмяТипаДокумента.СписокВыбора;
    СписокТипов.Очистить();
    
    Для Каждого МетаДанноеИзДокументов Из Метаданные.Документы Цикл
        // Проверяем наличие табличной части "Товары", чтобы не предлагать лишние документы
        Если МетаДанноеИзДокументов.ТабличныеЧасти.Найти("Товары") <> Неопределено Тогда
            СписокТипов.Добавить(МетаДанноеИзДокументов.Имя, МетаДанноеИзДокументов.Синоним);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

При проверке условий в коде документа мы будем сравнивать строковое имя метаданных:


ИмяМетаданных = Ссылка.Метаданные().Имя;
// Поиск в регистре по строке ИмяМетаданных

Способ 3. Метод «Пустой ссылки» через Определяемые типы

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

Рассмотрим шаги реализации:

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

Выясним, как это работает в запросе. Платформа 1С поддерживает оператор ТИПЗНАЧЕНИЯ, что позволяет нам написать очень элегантный код:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Регистр.Номенклатура
    |ИЗ
    |	РегистрСведений.ДоступнаяНоменклатураПоДокументам КАК Регистр
    |ГДЕ
    |	ТИПЗНАЧЕНИЯ(Регистр.ТипДокумента) = ТИПЗНАЧЕНИЯ(&ТекущийДокумент)";

Запрос.УстановитьПараметр("ТекущийДокумент", ТекущийОбъект.Ссылка);

Этот метод объединяет в себе строгость типизации и отсутствие необходимости в строковых константах.

Способ 4. Использование Плана видов характеристик (ПВХ)

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

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

Проверка наличия табличных частей в метаданных

Часто возникает вопрос: как автоматически определить все документы, в которых есть табличная часть Товары, чтобы не прописывать их вручную? Проанализируем универсальную функцию, которую можно запустить при первом старте системы или в обработке заполнения настроек:


Функция ПолучитьСписокДокументовСТЧТовары() Экспорт
    СписокДокументов = Новый СписокЗначений;
    
    Для Каждого ДокументМет Из Метаданные.Документы Цикл
        Для Каждого ТЧ Из ДокументМет.ТабличныеЧасти Цикл
            Если ТЧ.Имя = "Товары" Тогда
                СписокДокументов.Добавить(ДокументМет.Имя, ДокументМет.Синоним);
                Прервать; // Переходим к следующему документу
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    Возврат СписокДокументов;
КонецФункции

Подведем итоги и выберем лучшее решение

Мы рассмотрели четыре варианта реализации «предотбора» номенклатуры. Какой же выбрать?

  1. Если есть БСП: Однозначно используйте ИдентификаторыОбъектовМетаданных. Это стандарт индустрии, который обеспечивает максимальную надежность при обновлении и рефакторинге.
  2. Если нужна простота и скорость: Выбирайте строковое измерение. Оно легко отлаживается, понятно любому программисту и работает крайне быстро в SQL-запросах.
  3. Если вы сторонник объектного подхода: Метод пустой ссылки через определяемый тип будет наиболее красивым архитектурным решением.
  4. Если система настроек масштабируема: Используйте План видов характеристик.

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

← На главную