Создание своего типа условия
Создание своего типа условия¶
Для удобства настройки системы в ней есть такой тип карточки, как тип условия. Данный тип карточки позволяет реализовать свой тип условия с заданным редактором условия (поле Тип карточки настроек), местами возможности его использования (поле Места использования), описанием условия и собственно самим скриптом условия.
В качестве типа карточек настроек можно выбрать любой тип карточки системы, который имеет флаги Скрытый и Административный и не имеет флага Единственный экземпляр в настройках типа карточки.
Tip
Если для условий данного типа не требуется редактора, то данное поле можно не заполнять или в качестве типа выбрать Без редактора.
Указанный в карточке типа условия тип карточки настроек будет использован в качестве редактора условия данного типа, а все настройки условия можно использовать в описании условия и в скрипте условия.
Important
После создание нового типа условия или изменения типа карточки настроек редактора для корректной настройки условий данного типа необходимо перезапустить приложение.
Описание условие - это текст, поддерживающий простые плейсхолдеры, вроде {date}, строки локализации и плейсхолдеры {f} и {t}. В качестве данных для плейсхолдеров можно использовать секции и поля из типа карточек, указанного в качестве типа карточек настроек.
Tip
Например строка вида “{$CardTypes_Controls_Partner}: <_row>{t:KrPartnerCondition.PartnerName separate by (, )}; </_row>” позволяет вывести в качестве описания условия текст вида “Контрагенты: <список имен контргагентов из секции KrPartnerCondition, записанный через запятую>.
Условие - это скрипт, который должен вернуть true
, если условие выполнено успешно, иначе он должен вернуть false
. Данный скрипт в качестве параметра принимает параметр context
, который имеет тип IConditionContext
. Данный скрипт - асинхронный метод и поддерживает использование в скрипте асинхронного API с использованием операнда await
(например await context.GetCardAsync()
)
Данный параметр имеет следующие свойства и методы:
-
GetCardAsync - асинхронный метод для получения карточки, по которой идет проверка условия.
-
Settings - набор секций с настройками. Соответствует типу карточек, укказанному в поле “Тип карточки настроек”.
-
DbScope - объект для взаимодействия с базой данных.
-
Session - сессия пользователя.
-
Container - контейнер зависимостей Unity.
-
Info - место хранения дополнительной информации. Может быть использована для хранения данных, полученных через DbScope, и повторного использования в следующих выполнениях проверки условий данного типа.
Особенность проверки условий заключается в том, что в ходе одной проверки условий по карточке все они выполняются с использованием одного и того же объекта context
. Это позволяет в свою очередь в условиях, в которых может производиться загрузка данных из базы данных с использованием DbScope
, производить эту загрузку единожды и записать эту информацию в context.Info
, а все последующие проверки условий данного типа уже могут обращаться к этой информации без повторного обращения к базе данных.
Пример условия По состоянию, которое использует данную особенность.
// Пытаемся получить необходимую информацию из context.Info, и если ее еще там нет, то производим загрузку состояния карточки из базы
if (!(context.Info.TryGetValue("StateID", out var stateIDObj)
&& stateIDObj is int stateID))
{
var db = context.DbScope.Db;
var builder = context.DbScope.BuilderFactory;
stateID = await db.SetCommand(
builder
.Select().Top(1).C("StateID")
.From("KrApprovalCommonInfo").NoLock()
.Where().C("MainCardID").Equals().P("ID")
.Limit(1).Build(),
db.Parameter("ID", context.CardID))
.LogCommand()
.ExecuteAsync<int?>(context.CancellationToken) ?? 0; // 0 - состояние Проект, которое считается состоянием по умолчанию
// Записываем загруженное состояние в context.Info для возможности ее повторного использования
context.Info["StateID"] = stateID;
}
// Возвращаем true, если в строках секции KrDocStateCondition есть хотя бы одна строка, в которой указано данное состояние.
return context.Settings["KrDocStateCondition"].Rows.Any(row =>
{
var settingsStateID = row.TryGet<int>("StateID");
return settingsStateID == stateID;
});
Другой пример типа условия - По контрагенту. В нем уже не используется Info
, т.к. данные грузятся из карточки. Сама же карточка загружается только один раз и только при условии, что она не была еще загружена ранее.
// Получаем карточку из контекста. Непосредственно загрузка карточки из базы произойдет только при условии, что она еще не была загружена.
var card = await context.GetCardAsync();
// Получаем идентификатор контрагента из карточки
var partnerID = card.Sections.GetOrAdd("DocumentCommonInfo").Fields.TryGet<Guid?>("PartnerID");
// Возвращаеи true, если в строках секции KrPartnerCondition есть хотя бы одна строка, в которой указан данный контрагент.
return context.Settings["KrPartnerCondition"].Rows.Any(row =>
{
return partnerID == row.TryGet<Guid>("PartnerID");
});