Глава 7. СПРАВОЧНИКИ
Иерархические фильтры. Системная таблица RUBRIC
Иерархические фильтры (рубрикаторы) позволяют имитировать «иерархические справочники
» при том, что на самом деле данные хранятся
в «плоских справочниках». Главное назначение рубрикаторов – упростить
навигацию по имеющимся данным и ускорить ввод новых данных за
счет того, что рубрикаторы не только фильтруют справочник по
значениям в каких-то полях, но и подставляют
соответствующие начальные значения в эти поля при добавлении новой записи
. Рубрикаторы создаются вручную и состоят из папок, каждая
из которых может добавить одно условие фильтрации вида Атрибут=
Значение или не добавить никакой фильтрации вообще. Каждая папка
имеет свой класс. Сочетая папки-классы с дочерними
папками-фильтрами по каким-то полям, можно
построить очень мощную систему каталогизации справочников, в которых имеется
иерархия классов и наследование свойств. При этом все данные
хранятся в строго нормализованных таблицах, а система фильтров в
любой момент может быть дополнена или перестроена.
Интерфейс рубрикаторов в окне диалога справочника автоматически формирует SQL-
запросы, объединяя условия фильтрации разных уровней дерева фильтров.
При этом чем ниже мы находимся в дереве, тем
все больше условий фильтрации может быть наложено.
Папки могут быть трех типов:
- Класс
- Фильтр по атрибуту
- Папка «Прочее»
Папка типа «Класс» ограничивает все справочные элементы классом
, который ей присвоен. Объекты дочерних классов также входят
в это множество. Папка типа «фильтр по атрибуту
» добавляет одно условие фильтрации. Все объекты в этой
папке будут отфильтрованы по этому атрибуту. Папка «Прочее
» вставляет в SQL-запрос вложенный подзапрос вида NOT
IN (SELECT ….), который отсеивает все объекты, подпавшие
под «фильтры по атрибуту» и оставляет те,
которые не прошли фильтрацию по атрибуту на этом уровне дерева
. Проще говоря в папку «Прочее» на этом
уровне попадает «все остальное». Если пользователь добавит на
этом уровне дерева рубрик еще один фильтр по тому же
атрибуту, в котором укажет значение из «Прочего»,
то соответствующие объекты «исчезнут» из папки «Прочее
» и окажутся в папке, которую он создал.
Таким образом папка «Прочее» позволяет ограничить дерево созданием
самых необходимых для работы и часто применяющихся каталогов, помещая
в «Прочее» все остальное.
Фильтры можно создавать массово и массово удалять, что позволяет
очень быстро построить требуемую каталогизацию. Преимущество фильтров перед обычными
деревьями, которые часто применяют в «иерархических справочниках»
в том, что:
- Не нужно иметь строгих административных циркуляров о том, что
в какую папку следует помещать, так как все и
так автоматически окажется в нужных папках.
- Не нужно мучительно решать, какие атрибуты объектов поместить «
на верхний уровень» дерева, а какие «на
нижних уровнях», так как в одном и том же
дереве возможно построить альтернативные способы каталогизации и один и тот
же объект окажется «во всех нужных местах».
- Возможно создание фильтров по атрибутам, которые не исключают одновременного
попадания объекта в несколько папок. Например, в справочнике
«Контрагенты» можно создать два логических поля: «
Поставщик» и «Покупатель», а в дереве рубрик
– две соответствующие рубрики, фильтрующие каждая по своему полю
. Покупатели автоматически окажутся в одной папке, а поставщики
– в другой. Если же кто-то из
контрагентов является одновременно и поставщиком и покупателем, то он
окажется в обеих папках одновременно.
- Так как в дереве фильтров не хранится никакой информации о
самих объектах (даже неявно), можно не создавать папки
, в которых мало элементов. Часто в обычных «
иерархических справочниках» это приходится делать ради поддержания единообразия способа
хранения данных.
- В папках фильтров по атрибутам типа «ссылка на другой
справочник» названия могут не храниться, а браться «
на лету» из кратких отформатированных наименований объектов, хранящихся
в этом справочнике. Если в справочнике исправили грамматическую ошибку
, она автоматически исправится и во всех рубрикаторах тоже.
- Если какое-то значение из справочника, на который
ссылался атрибут, больше не используется, при удалении из
справочника одновременно автоматически удалятся и все соответствующие этому значению папки
фильтров.
- Все данные справочников хранятся в строгом виде, подходящем для
SQL-запросов и гарантирующем строгость и быстроту любых финансовых
отчетов с группировкой по любым атрибутам объектов.
Ниже приведен пример SQL-запроса, формируемого рубрикатором товаров
, в котором пользователь зашел в папку марки товара «
BOSCH», а затем выбрал в ней папку «Кофеварка
». Жирным шрифтом отмечена та часть, которую иерархический фильтр
вставил в SQL-запрос:
SELECT
GOODS.ID GOODS_ID,
GOODS.GOODS_KIND,
O1.SHORT_NAME GOODS_KIND_LK,
GOODS.GOODS_MARK,
O2.SHORT_NAME GOODS_MARK_LK,
GOODS.ARTICLE,
GOODS.PRICE_W,
GOODS.PRICE_R
FROM
GOODS,
OBJECT_NAMES O1,
OBJECT_NAMES O2
WHERE
GOODS.GOODS_KIND=O1.OBJECT_ID AND
GOODS.GOODS_MARK=O2.OBJECT_ID AND
GOODS_KIND=8 AND /*кофеварка*/
GOODS_MARK=17 /*BOSCH*/
ORDER BY GOODS.ID
А вот пример запроса, который формируется, если пользователь
выбрал папку «Прочее» среди видов товара, продолжая
находиться в папке «BOSCH»:
SELECT
GOODS.ID GOODS_ID,
GOODS.GOODS_KIND,
O1.SHORT_NAME GOODS_KIND_LK,
GOODS.GOODS_MARK,
O2.SHORT_NAME GOODS_MARK_LK,
GOODS.ARTICLE,
GOODS.PRICE_W,
GOODS.PRICE_R
FROM
GOODS,
OBJECT_NAMES O1,
OBJECT_NAMES O2
WHERE
GOODS.GOODS_KIND=O1.OBJECT_ID AND
GOODS.GOODS_MARK=O2.OBJECT_ID AND
(GOODS_KIND NOT IN (SELECT OBJECT_ID FROM RUBRIC
WHERE PARENT_ID = 45 AND
FILTER_FIELD_NAME = 'GOODS_KIND' AND
FILTER_KIND = 1)) AND /*Прочее*/
GOODS_MARK=17 /*BOSCH*/
ORDER BY GOODS.ID
Интерфейс дерева рубрикаторов устроен таким образом, что если на
каком-то уровне ветви дерева фильтрация по данному атрибуту
уже имеется, то этот атрибут исключается из списка атрибутов
, по которым пользователь может создать фильтрацию на всех нижних
уровнях, если только они не дочерние к папке «
Прочее». Это исключает вероятность случайного создания противоречивых условий фильтрации
на разных уровнях рубрикатора. Таким образом каждый фильтр по
атрибуту сокращает возможный список атрибутов для фильтрации, а каждый
дочерний класс, как правило, добавляет новые атрибуты в
список, так как дочерние классы справочников как правило обладают
дополнительной атрибутикой по отношению к классам-предкам.
Дерево рубрикаторов придает системе классов справочников законченный и стройный вид
. Само дерево рубрикаторов появилось в системе Allegro, начиная
с версии 1.8 и заменило собой дерево классов
справочников в левой стороне окна «Все справочники». Поэтому
теперь после создания нового справочника конфигурирующий сам решает, включать
его, как рубрику в дерево рубрикаторов или не включать
. Особенно это актуально для множества мелких справочников первого уровня
, которые раньше загромождали окно «Все справочники». Теперь
их можно просто не включать в дерево рубрик.
Информация о дереве иерархических фильтров справочников хранится в таблице RUBRIC
.
Системная таблица RUBRIC
Название поля |
Тип данных |
Назначение |
ID |
INTEGER |
Внутренний ID рубрики |
PARENT_ID |
INTEGER |
Внутренний ID родительской рубрики |
HAS_CHILDREN |
SMALLINT |
Если рубрика имеет дочерние рубрики, то в этом поле
записывается 1, если нет, то записывается 0 |
CLASS_ID |
INTEGER |
Внутренний ID класса |
FILTER_KIND |
SMALLINT |
Тип рубрики: 0 – класс, 1 - фильтр
по атрибуту, 2 - папка "Прочее" |
FILTER_FIELD_NAME |
VARCHAR(31) |
Имя поля, по которому производится фильтрация в справочнике |
OBJECT_ID |
INTEGER |
Внутренний ID объекта ссылки, если установлен фильтр по полю
типа TREFERENCE |
INTEGER_VALUE |
INTEGER |
Значение фильтра, если оно - целое число |
IS_AUTONAME |
SMALLINT |
Если рубрика использует автоматическое наименование, то в этом поле
записывается 1, а если ручное, то записывается 0 |
NAME |
VARCHAR(64) |
Ручное наименование рубрики |
Каждая рубрика имеет свой ID, который поставляется генератором RUBRIC
_ID_GEN. Рубрики образуют бесконечные деревья.
Все базовые рубрики (корневые) имеют PARENT_ID
= 0.
|