На главную   На главную   Форумы Новости Документация Скачать Купить  
Регистрация  
Система Allegro
Oб Allegro Характеристики Пример конфигурации Документация База ошибок Развитие
Версия для печати К списку книг Вернуться к оглавлению Предыдущий параграф Следующий параграф
Поиск по книге

Глава 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.



Система Allegro. Руководство разработчика Наверх