Динамические поля
Концепция
Механизм динамических полей позволяет работать со сложными структурами данных так, как если бы это была плоская таблица. А благодаря существующим в системе механизмам получения и редактирования данных, имеется возможность работать в том числе и с мультизначениями для одной записи в основной плоской таблице.
Как это работает
В минимальной конфигурации в процессе участвуют 3 сущности. Основная сущность, та которая формирует плоские данные. Вторая сущность, эта та, которая преобразуется в поля основной сущности, то есть это те столбцы, которые должны появиться в основной таблице, чтобы данные более полные. Третья сущность, это таблица связи, таблица со значениями второй сущности для записей в первой.
Как правило это набор характеристик, какой либо сущности. Эти характеристики могут быть разных типов. Тип характеристики определяет тип редактора, который будет установлен (может быть переопределен) в конечной таблице или форме.
Значений характеристики для конкретной записи сущности также может быть несколько, механизм поддерживает возможность работы с мультизначениями. Клиентские таблицы умеют отображать такие данные и позволяют кастомизировать редактор (см. Фрейм для редактора).
Рассмотрим на примере Товаров и их Характеристик. Может быть множество характеристик для различных товаров и так как они могут добавляться и удаляться в процессе работы с системой, а также в силу их большого количества, они не могут быть физическими полями в основной сущности (Товар), кроме того такая структура не позволила бы иметь несколько значений для одной Характеристики конкретного Товара. Поэтому структура может быть следующей. Таблица Товаров, Справочник Характеристик и таблица со Значения_Характеристики_Для_Товара.
Таблица со значениями может быть более сложной структурой, так как, например, для значений вида Справочник, потребуются отдельные таблицы с их значениями, но в этом случае имеет смысл средствами SQL привести таблицу со значениями в уже подготовленную “VIEW”, где хранятся в том числе и физические значения.
Итак, у нас есть Товары и их Характеристики (значения). Если мы хотим вывести данные для одного Товара, то проблем особых не возникает, так как мы можем получить необходимые данные в 2-3 запроса. Однако если мы хотим работать с таблицей, пусть даже с пагинацией, то требуется другой подход получения данных (особенно если вы хотим выгрузить в Excel несколько тысяч записей). Механизм строит оптимальный запрос для получения таких данных, выводя в результате все характеристики как если бы это были поля этой таблицы. А благодаря профайлам, система знает, что это поля из другой таблицы и знает как с ними работать, чтобы обеспечить редактирование.
Ограничение набора динамических полей
Как правило в подобных структурах данных, характеристики относятся к определенным категориям сущности (например Категории_Товаров), тогда нам необходимо иметь возможность ограничить набор динамических полей определенной категорией (и ее дочерними). Система позволяет это сделать, указав таблицу для фильтра. Тогда если данные загружаются в форме (например форма определенной Категории), то система обратится в таблицу фильтров и наложит ограничения таким образом, что будут подгружены только характеристики относящиеся к этой категории.
Иерархия по таблице фильтрации
Если таблица, по которой осуществляется фильтрация является иерархической, как в нашем примере с Категориями (у Категории могут быть подкатегории, а у них свои, и так далее), то фильтр может это учитывать (при определенной настройке) и выдавать Характеристики не только для указанной Категории, но и всех ее дочерних и/или всех родительских.
Справочник характеристик также может быть по умолчанию отфильтрован по какому-либо признаку, не обязательно чтобы все Характеристики попадали в динамику.
Подытоживая, механизм гибкий и может быть доработан еще под большую кастомизацию, если позволить определять функции, которые будут подготавливать срезы данных опираясь на входные параметры. Однако текущей реализации достаточно для описанного сценария. Он позволяет простой настройкой реализовать сложный механизм взаимодействия с данными.
Наследование значений
Ядро поддерживает механизм наследования значений для обычных физических полей в иерархических сущностях. Для этого служит настройка is_inherit в профайле поля. Для динамических полей имеются собственные настройки профайла, которые динамически дополняют профайл основной сущности (см. Настройки профайла динамических полей). Там имеется, в том числе, настройка is_inherit, которая, как и для физических полей, позволяет включить наследование для динамических полей.
Управление
Динамические поля могут быть применены только к клиентскому объекту. Далее он может быть интерфейсно реализован как в форме/фрейме, так и в таблице.
Создание “Пары Динамических Полей”
Откройте меню Dynamic fields -> Dynamic fields pair. Создайте пару. Укажите Наименование, Класс источника (справочник Характеристик(например)), Клиентский объект цели (Клиентский объект основанный на классе, который должен быть дополнен динамическими полями (например Товары)), Таблицу со значениями (таблица, которая хранит значения Источника для Цели (Значения Характеристик для Товара).
У большинства полей есть подсказка, наведите мышкой на заголовок столбца.
Система предполагает что ключи в таблице значений соотносятся с именами таблиц источника и цели (исключая префиксы “ds_” или “d_”), например product_id и trait_id, однако их можно переопределить (Key to target и Key to source).
Система предполагает что значение будет храниться в поле с именем “val1”, но можно переопределить (Value key).
Настройки таблицы фильтров
Вы можете указать таблицу фильтров, тогда фильтр будет применяться на набор характеристик, при запросе данных внутри формы/фрейма (система передает parent_id). При этом, если клиентский объект грузится без parent (а table_for_filter не пустой), то ни одно динамическое поле не будет подгружено.
Укажите table_for_filter, например product_category (таблица связи, определяющая к каким категориям относится Товар).
Укажите parent_class_for_filter, который определит сущность, которая накладывает ограничения (Категории). Это особенно важно, если сущность иерархическая и нужно, чтобы подключались характеристики в том числе и дочерних записей относительно отфильтрованной.
src_key_for_filter. Определяет ключ “характеристики” в таблице фильтра, например trait_id.
this_and_parents_for_filter и this_and_childs_for_filter. Позволяют включить использование иерархии “вверх” и/или “вниз” по таблице фильтров. См. подсказки в интерфейсе. Например, система отфильтровала характеристики по определенной Категории, при данных настройках, система может добавить к ним Характеристики, относящиеся к родительским и/или дочерним Категориям.
Фрейм для редактора
Вы можете создать отдельный (клиентский объект) фрейм, который будет открываться при попытке редактировать динамическое поле. Этот фрейм будет открыт в модальном окне и ему будет передан ID записи цели (Продукта. Соответственно он должен быть создан на основе класса Продукт (frm_edit_product_traits)) и ID записи Источника (Характеристики). В этом фрейме вы можете просто разместить таблицу Значений_Характеристик_Для_Продукта (product_trait_value), которая будет фильтроваться по указанному Продукту и указанной Характеристике. Таким образом вам откроется таблица со значениями именно этой Характеристики для указанного Продукта и вы сможете с ней взаимодействовать, в том числе, например, менять другие поля этой таблицы, например галочку is_active (или еще что-нибудь, что будет соответствовать бизнес логике вашего проекта).
Настройки профайла динамических полей
Так как динамические поля добавляются “на лету”, к основной сущности, то для них нет профайла в основной сущности (Цели), а профайлы полей в таблице со значениями могут не подходить для полей подключенных динамически, хотя за основу берутся именно эти профайлы. Поэтому для них автоматически создаются свои профайлы и они располагаются в меню Dynamic fields -> Dynamic field.
Там вы можете переопределить Наименование поля, а также многие другие настройки для этого поля, также, как если бы вы настраивали профайл обычного поля (например сделать поле не редактируемым).
map_source_to_dynamic_field
Вы можете указать объект в формате JSON, например ‘{“inherit”:“df_is_inherit”}’. Это позволит опираясь на значение поля в таблице источника (например “inherit”) проставить его как значение профайла для соответствующего динамического поля (“df_is_inherit”).