Как спроектировать подсистему контроля ввода свойств характеристик в 1С:ERP и проверять условия с помощью СКД

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

При разработке крупных корпоративных систем на базе 1С:ERP Управление предприятием часто возникает задача динамического контроля ввода свойств или характеристик номенклатуры. Типичный сценарий: в зависимости от выбора одних свойств (например, вида материала или габаритов), необходимо накладывать жесткие ограничения на доступность, видимость или обязательность заполнения других свойств.

Сложность заключается в том, что условия взаимосвязи свойств редко бывают линейными. Они могут содержать сложные логические конструкции: «Если Свойство 1 заполнено И Свойство 3 НЕ равно Значению А, ТО Свойство 2 становится обязательным для заполнения, а из списка выбора Свойства 2 исключаются определенные значения».

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

Архитектурный подход к хранению условий

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

  1. Сериализация в ХранилищеЗначения (XML или Двоичные данные):

    Этот способ кажется простым, так как позволяет напрямую сериализовать настройки компоновщика отбора. Однако у него есть критический недостаток — отсутствие контроля ссылочной целостности. Если пользователь решит удалить одно из свойств или конкретное значение свойства, система не сможет штатно отследить, что эта ссылка используется внутри сериализованного объекта в Хранилище Значения. В результате при проверке правил система начнет выдавать труднодиагностируемые ошибки («битые ссылки»).

  2. Хранение структуры условий в справочниках и табличных частях (Реляционный подход):

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

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

Решение проблемы проверки условий: Метод виртуальной таблицы значений и СКД

Когда структура хранения определена, возникает следующая сложная задача: как быстро и универсально проверить, удовлетворяют ли текущие значения свойств, выбранные пользователем на форме, настроенному правилу отбора?

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

Рассмотрим подробный алгоритм решения этой задачи:

  1. На форме в момент изменения любого свойства мы собираем текущее состояние всех заполненных свойств в одну строку таблицы значений. Колонками этой таблицы выступают идентификаторы (или ссылки) свойств, а значениями — выбранные пользователем данные.
  2. Программно конструируем минимальную схему компоновки данных (СКД), где источником данных объявляем нашу таблицу значений.
  3. Переносим сохраненные настройки отбора в компоновщик настроек СКД.
  4. Инициализируем процессор компоновки и выводим результат во временную таблицу значений.
  5. Анализируем результат: Если на выходе мы получили строку таблицы — значит, текущие значения свойств удовлетворяют условиям отбора. Если таблица пустая — условия не выполнены.

Проанализируем программную реализацию этого алгоритма на встроенном языке 1С:


// Функция проверяет, соответствуют ли текущие значения свойств заданному отбору СКД
//
// Параметры:
//  ТекущиеСвойства - Структура - Ключ: Свойство (ссылка), Значение: ВыбранноеЗначение
//  НастройкиОтбора - НастройкиКомпоновкиДанных - сохраненные настройки отбора
//
// Возвращает:
//  Булево - Истина, если свойства удовлетворяют условиям отбора
//
Функция ПроверитьСоответствиеСвойствОтбору(ТекущиеСвойства, НастройкиОтбора) Экспорт

    // 1. Создаем таблицу значений с одной строкой
    ТаблицаДанных = Новый ТаблицаЗначений;
    НоваяСтрока = ТаблицаДанных.Добавить();
    
    Для Каждого КлючИЗначение Из ТекущиеСвойства Цикл
        // Имя колонки формируем уникальным образом на основе УИД свойства, 
        // чтобы избежать недопустимых символов в именах полей СКД
        ИмяКолонки = "П_" + СтрЗаменить(Строка(КлючИЗначение.Ключ.УникальныйИдентификатор()), "-", "_");
        ТаблицаДанных.Колонки.Добавить(ИмяКолонки);
        НоваяСтрока[ИмяКолонки] = КлючИЗначение.Value;
    КонецЦикла;

    // 2. Программно создаем схему компоновки данных
    СхемаСКД = Новый СхемаКомпоновкиДанных;
    
    ИсточникДанных = СхемаСКД.ИсточникиДанных.Добавить("ИсточникДанных1");
    ИсточникДанных.ТипИсточникаДанных = "Local";
    
    НаборДанных = СхемаСКД.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
    НаборДанных.Имя = "НаборДанных1";
    НаборДанных.ИмяОбъекта = "ТаблицаДанных";
    НаборДанных.ИсточникДанных = "ИсточникДанных1";
    
    // Добавляем поля в набор данных схемы
    Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
        ПолеСхемы = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
        ПолеСхемы.ПутьКДанным = Колонка.Имя;
        ПолеСхемы.Поле = Колонка.Имя;
        ПолеСхемы.Заголовок = Колонка.Имя;
    КонецЦикла;
    
    // 3. Инициализируем компоновщик настроек и загружаем в него отбор
    КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
    КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаСКД));
    
    // Загружаем сохраненный отбор в настройки компоновщика
    КомпоновщикНастроек.ЗагрузитьНастройки(НастройкиОтбора);
    
    // 4. Выполняем компоновку данных
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаСКД, КомпоновщикНастроек.ПолучитьНастройки(), , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ВнешниеНаборы = Новый Структура("ТаблицаДанных", ТаблицаДанных);
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборы);
    
    РезультатТаблица = Новый ТаблицаЗначений;
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ПроцессорВывода.УстановитьОбъект(РезультатТаблица);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // 5. Если строка осталась после применения отбора - условия выполнены
    Возврат РезультатТаблица.Количество() > 0;

КонецФункции

Методы оптимизации производительности

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

Рассмотрим несколько приемов, которые позволят оптимизировать этот механизм и сделать его работу мгновенной:

1. Кэширование структуры схемы СКД

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

2. Гибридный расчет условий («Быстрый проход»)

Далеко не все условия в вашей системе будут сложными. По статистике, около 80–90% условий представляют собой простые проверки вида «Свойство равно Значению» или «Свойство заполнено». Для таких простых правил запускать полноценный механизм СКД избыточно.

Мы рекомендуем разработать легкую функцию-препроцессор на встроенном языке 1С. Она будет обходить коллекцию элементов отбора и выполнять простые проверки (равенство, неравенство, проверка на заполненность) напрямую в коде. И только если препроцессор обнаружит сложные виды сравнения (например, «В группе», «В списке» или сложные логические группы «ИЛИ», «НЕ»), система передаст задачу тяжеловесному механизму СКД. Это снизит нагрузку на сервер в разы.

3. Пакетная проверка правил

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

Используя предложенную архитектуру хранения и гибридный метод проверки условий через виртуальные таблицы СКД, вы сможете построить отказоустойчивую, гибкую и быстродействующую подсистему контроля ввода свойств в 1С:ERP, которая будет легко масштабироваться под любые требования бизнеса.

← На главную