Технические вопросы
7.x

Фильтрация лукапного поля в детали

Подскажите пожалуйста, запутался совсем.
Есть сущности UsrVacancies, UsrCandidates и UsrVacancyCandidates. На основе UsrVacancyCandidates сделана деталь. Заходишь на вакансию, и можешь ассайнить кандидатов, одного или нескольких. Если кандидат УЖЕ добавлен для вакансии, то должно быть невозможно добавить этого же кандидата дважды или более.
Когда нажимаешь "Add" в детали, там есть лукапное поле Candidate (имя - UsrCandidates). Что я хочу сделать - чтобы в этом лукапе НЕ отображались те кандидаты, что УЖЕ добавлены для ЭТОЙ вакансии, т.е. отфильтровать его.
Для этого я должен получить список тех кандидатов, что уже добавлены для этой вакансии, и наложить фильтр на лукап - показывать всех кандидатов, КРОМЕ уже добавленных.

Вот как должно быть. Обратите внимание на переменную "candidates", где я захардкодил айдишники.

attributes: {
        "UsrCandidates": {
                dataValueType: Terrasoft.DataValueType.LOOKUP,
                lookupListConfig: {
                        filter: function() {
                                var candidates = ["5d4d6b06-4de2-4d23-8e6e-f2ab624af5d0", "3c6f72a7-3218-4f23-b96a-e344bac099f4", "a9b68651-d313-4c83-9007-31a659547bd5"];
                                var filterGroup = new Terrasoft.createFilterGroup();
                                var filter1 = Terrasoft.createColumnInFilterWithParameters(
                                        "Id",
                                        candidates);
                                filter1.comparisonType = Terrasoft.ComparisonType.NOT_EQUAL;
                                filterGroup.add("filter1", filter1);
                                return filterGroup;
                        }
                }
        }
},

Однако, мне нужно получить эти айдишники, зная Id текущуй вакансии. Вот ESQ запрос, который возвращает эти айдишники.

getCurrentlyAssignedCandidates: function(vacancyId, callback) {
        var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                rootSchemaName: "UsrVacancyCandidates"
        });
        esq.addColumn("UsrCandidates", "CandidateId");
        esq.filters.add(
                "filter1",
                this.Terrasoft.createColumnFilterWithParameter(
                        Terrasoft.ComparisonType.EQUAL,
                        "UsrVacancies",
                        vacancyId
                )
        );
        esq.getEntityCollection(function(result) {
                var candidates = [];
                if (result.success) {
                        result.collection.each(function(item) {
                                candidates.push(item.get("CandidateId"));
                        });
                        callback.call(this, candidates);
                }
        });
}

Однако, если вызывать callback в "filter", то он выполняется асинхронно, и сама функция выполняется асинхронно. Получается, что функция "filter" возвращает фильтр (который включает в себя ВСЕХ кандидатов) раньше, чем выполняется callback. Т.е. ничего не фильтруется.

Подскажите, пожалуйста, как это реализовать.

Заранее благодарю!

Нравится

4 комментария

На самом деле вариантов несколько:
1. Через filterMethod, добавляете на деталь ссылку на метод, а в самом методе добавляете в фильтр уже добавленные записи
Как пример UIv2/AccountPageV2 только здесь без фильтрации по существующим
[csharp]

details: /**SCHEMA_DETAILS*/{
EmailDetailV2: {
schemaName: "EmailDetailV2",
filter: {
masterColumn: "Id",
detailColumn: "Account"
},
filterMethod: "emailDetailFilter"
}

/**
* Функция создания фильтров детали email
* @protected
* @returns {createFilterGroup}
*/
emailDetailFilter: function() {
var recordId = this.get("Id");
var filterGroup = new this.Terrasoft.createFilterGroup();
filterGroup.add("AccountNotNull", this.Terrasoft.createColumnIsNotNullFilter("Account"));
filterGroup.add("AccountConnection", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Account", recordId));
filterGroup.add("ActivityType", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Type", ConfigurationConstants.Activity.Type.Email));
return filterGroup;
},
[/csharp]
Но здесь возникнут сложности в асинхронностью, но Вы можете формировать первоначальную коллекцию например в методе init, а затем актуализировать эту коллекцию при изменении детали через подписку на сообщение updateDetail
2. Через правила
Как пример UIv2/ContactAddressPageV2
[javascript]

rules: {
"AddressType": {
"FiltrationAddressTypeByOwner": {
ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
autocomplete: true,
baseAttributePatch: "ForContact",
comparisonType: Terrasoft.ComparisonType.EQUAL,
type: BusinessRuleModule.enums.ValueType.CONSTANT,
value: true
}
}
},
или NUI/ActivityPage
[/javascript]

3. Через один из методов Lookup, как пример loadVocabulary или prepareLookupList
[javascript]
/**
* Подготовка параметров для открытия окна выбора из пользователей.
* @return {Object} Config настроек окна выбора из справочника.
*/
prepareLookupConfig: function() {
var filters = this.getLookupFilter();
var config = {
entitySchemaName: "SysAdminUnit",
multiSelect: true,
columns: ["Contact", "Name"],
hideActions: true,
filters: filters
};
return config;
}

getLookupFilter: function(isDelegate) {
var filters = this.Terrasoft.createFilterGroup();
var parentFilter = this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL,
isDelegate ? "GrantorSysAdminUnit.Id" : "GranteeSysAdminUnit.Id",
this.get("MasterRecordId"));
var sameIdFilter = this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.NOT_EQUAL,
"Id",
this.get("MasterRecordId"));
...
filters.addItem(sameIdFilter);
return filters;
},
[/javascript]
Подобный вопрос задавали http://www.community.terrasoft.ru/forum/topic/11658

Мне нужно сформировать в javascript подобный запрос для фильтрации
[sql]
declare @vacancyId uniqueidentifier = '3984d4b1-de5d-405b-b7c6-320b03b0a8ec';
select distinct
vc.UsrCandidatesId
from UsrVacancyCandidates vc
where
vc.UsrCandidatesId not in(
select vc.UsrCandidatesId from UsrVacancyCandidates vc
where vc.UsrVacanciesId = @vacancyId
);
[/sql]

Пока не могу понять, как..

1. SELECT DISTINCT vc.UsrCandidatesId

реализуется так:
[javascript]
esq.isDistinct = true;
esq.addColumn("UsrCandidatesId");
[/javascript]

2. vc.UsrCandidatesId NOT IN(
[javascript]
SELECT vc.UsrCandidatesId FROM UsrVacancyCandidates vc
WHERE vc.UsrVacanciesId = @vacancyId
);

Реализуется через NOT_EQUAL

Пример NUI/InFolderDetail

var filterGroup = Terrasoft.createFilterGroup();
if (inFolders.length > 0) {
var notInFilter = Terrasoft.createColumnInFilterWithParameters('Id', inFolders);
notInFilter.comparisonType = Terrasoft.ComparisonType.NOT_EQUAL;
filterGroup.addItem(notInFilter);
}

[/javascript]
Можете переделать NOT IN на Not Exists тогда, как пример фильтр в модуле [csharp]
LeadContactsInFolderDetailV2

/**
* Метод действия "Добавить группу контактов".
* @private
*/
addContactFolder: function() {
var masterColumnValue = this.get("MasterRecordId");
var config = {
entitySchemaName: "ContactFolder",
multiSelect: true,
columns: ["FolderType", "Id"]
};
var existsFilterGroup = this.Terrasoft.createFilterGroup();
existsFilterGroup.addItem(this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Contact", masterColumnValue));
var existsFilter = this.Terrasoft.createNotExistsFilter("[ContactInFolder:Folder:Id].Contact",
existsFilterGroup);
var filterGroup = this.Terrasoft.createFilterGroup();
filterGroup.addItem(existsFilter);
var folderFilter = this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "FolderType", ConfigurationConstants.Folder.Type.General);
filterGroup.addItem(folderFilter);
config.filters = filterGroup;
this.openLookup(config, this.addContactCallback, this);
},
[/csharp]
Теория по Exists
http://www.terrasoft.ua/bpmonlinesdk/Terrasoft.Core~Terrasoft.Core.Enti…

Спасибо, разобрался. Сделал так:
[javascript]
attributes:
{
"UsrCandidates":
{
dataValueType: Terrasoft.DataValueType.LOOKUP,
lookupListConfig:
{
filter: function()
{
var vacancy = this.get("UsrVacancies");
if (!this.Ext.isEmpty(vacancy))
{
var filterGroup1 = this.Terrasoft.createFilterGroup();
var filter1 = this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL,
"[UsrVacancyCandidates:UsrCandidates].UsrVacancies", vacancy
.value);
filterGroup1.addItem(filter1);
var filterGroup2 = this.Terrasoft.createFilterGroup();
var filter2 = this.Terrasoft.createNotExistsFilter(
"[UsrCandidates:Id].Id", filterGroup1);
filterGroup2.addItem(filter2);
return filterGroup2;
}
}
}
},
},
[/javascript]

Показать все комментарии