Динамическое добавление фильтров в деталь

Добрый день. Возникла проблема добавление фильтров в деталь:

var parentApplyFilter = this.methods.applyFilter;
                        this.methods.applyFilter = function(select, args) {
                               
                                var parentThis = this;
                                var filterGroup = Terrasoft.createFilterGroup();
                                var filterPath = this.filterPath;
                                var filterValue = this.filterValue;
                                var ContactId;
                                if (args) {
                                        filterPath = this.filterPath = args.filterPath;
                                        filterValue = this.filterValue = args.filterValue;
                                        // get contact id from Application
                                        var getContactIdESQ = Ext.create('Terrasoft.EntitySchemaQuery', {rootSchemaName: 'Application'});
                                        getContactIdESQ.addColumn('Contact');
                                        getContactIdESQ.getEntity(filterValue, function(result) {
                                                                if (result.success) {
                                                                        ContactId = result.entity.values.Contact.value;
                                                                        // get subcontacts of contact
                                                                        var getContactsInContactESQ = Ext.create('Terrasoft.EntitySchemaQuery', {rootSchemaName: 'UsrContactInContact'});
                                                                        getContactsInContactESQ.addColumn('UsrContact');
                                                                        getContactsInContactESQ.filters.add('parentContactFilter', Terrasoft.createColumnFilterWithParameter(
                                                                                                                                                                                                Terrasoft.ComparisonType.EQUAL,
                                                                                                                                                                                                'UsrParentContact.Id', ContactId));
                                                                        getContactsInContactESQ.getEntityCollection(function(result2) {
                                                                                if (result2.success) {
                                                                                        // creating group of filters for all subcontacts entries
                                                                                        filterGroup.logicalOperation = Terrasoft.LogicalOperatorType.OR;
                                                                                       
                                                                                        var contacts = result2.collection.getItems();
                                                                                        if (contacts && contacts.length > 0) {
                                                                                                Terrasoft.each(contacts, function(contact) {
                                                                                                        var contactFilter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, 'Contact', contact.get('UsrContact').value);
                                                                                                        filterGroup.add('contactFilter' + contact.get('UsrContact').value, contactFilter);
                                                                                                }, this);
                                                                                                select.filters.add(filterGroup);
                                                                                        }
                                                                                        else {
                                                                                                select.filters.add('contactFilter', Terrasoft.createColumnFilterWithParameter(
                                                                                                                Terrasoft.ComparisonType.EQUAL,
                                                                                                                'Contact.Id', '025375D6-3290-4AC7-8451-B569BBAB026A'));
                                                                                        }
                                                                                }
                                                                        }, this);
                                                                }
                                                        }, this);
                                }
                                // Type - calls
                                select.filters.add('callsTypeFilter', Terrasoft.createColumnFilterWithParameter(
                                                                                                        Terrasoft.ComparisonType.EQUAL,
                                                                                                        'Type.Id', 'e1831dec-cfc0-df11-b00f-001d60e938c6'));
                                       
                                select.filters.add('callsAppFilter', Terrasoft.createColumnFilterWithParameter(
                                                                                                        Terrasoft.ComparisonType.EQUAL,
                                                                                                        'Application.Id', filterValue));
                               
                               
                        };

Нужно сделать несколько запросов в бд ( getContactIdESQ getContactsInContactESQ ) и в зависимости от полученного результата добавить в select.filters новые фильтры (contactFilter). Однако из-за асинхронного, видимо, характера запросов эти фильтры не добавляются. В результате в запрос попадают только два фильтра - callsTypeFilter и callsAppFilter.
Каким образом можно обойти эту проблему?
Спасибо.

BPMonline Lending Версия 7.2.2.257

Нравится

8 комментариев

Здравствуйте, Акмаль!
А Вы смотрели дебагером, корретно ли выполняются Ваши esq-запросы, и в какой момент упарвление приходит в коллбэк запроса.
Возможно, стоит выполнить запросы раньше, например, при инициализации страницы, и передать результаты в деталь в отдельное свойство.

Добрый день,
Необходимо добавлять в деталь динамично фильтр, код выше я так и не смог разобраться. Как возможно реализовать подобное: есть деталь, есть три поля, необходимо ее фильтровать по тому полю которое заполнено, некоторые из них могут быть пустые. Подскажите какие функции можно использовать для реализации?

Версия BPMonline 7.4

Здравствуйте, Олег!
Код выше не полностью применим к 7.4, поэтому я бы рекомендовал Вам создать отдельную тему.
В общем, для наложения такой фильтрации необходимо на запрос наложить 3 идентичные группы фильтров для каждого поля. Примерно так:

var columnValue = "some value"; //значение колонки
var filterGroup = Terrasoft.createFilterGroup(); //создаем группу сильтров
filterGroup.name = "ColumnOneFilterGroup";
filterGroup.logicalOperation = Terrasoft.LogicalOperatorType.OR;	//логическая операция ИЛИ
filterGroup.add("ColumnOneValueFilter", Terrasoft.createColumnFilterWithParameter(	//фильтр по значению колонки
	Terrasoft.ComparisonType.EQUAL,
	"ColumnName",
	columnValue));
filterGroup.add("nullType", Terrasoft.createColumnIsNullFilter("ColumnName"));	//фильтр is null 
//(если у Вас строковый или числовой тип данных, то нужно заменить на сравнение со значением по умолчанию)

Далее эти группы добавить к основному запросу. Это можно сделать, переопределив метод getFilters на странице детали. Нужно сначала вызвать базовый, который вернет Вам группу фильтров, добавить в него Вашу фильтрацию и вернуть результат.

Добрый день, Андрей,
Простите не совсем понял, я создаю три фильтра с разными названиями и передаю сюда свое значение

var columnValue = "some value"

но не понял куда все это добавить? на страницу где находится эта деталь? Детали у меня используются стандартные, следовательно если я добавлю все это на страницу детали, то и в остальных разделах она поведет себя так же, и совсем не понятно как на страницу детали передавать значение из страницы реестра раздела.
К примеру мне нужно добавить деталь "Средства связи" и "Продажи" и фильтровать их по дополнительно добавленным полям в "Активность" - "Контакт", "Контрагент", "Лид", в зависимости от того какое из этих полей заполнено, т.е. если контакт и лид заполнены - брать для фильтрации контакт, если контакт пустой брать лид и т.д.
Логику выбора значения для фильтрации не составляет труда реализовать, но дальше куда добавлять код для фильтров. Распишите пожалуйста хотя бы алгоритмически что куда добавить, чтобы в других разделах эти детали не сломались

Здравствуйте, Олег!
По поводу стандартных деталей. Можно выйти из ситуации двумя способами:
1. На странице детали получить текущий history state и посмотреть там, какая страница сейчас открыта. Пример:

var currentHistoryState = this.sandbox.publish('GetHistoryState');
var cardName = currentHistoryState.state.schemaName;

Если это выполнить в init страницы детали, то в cardName будет содержаться название текущей страницы, например "OrderPageV2".
2. Создать отдельную страницу детали, которую можно унаследовать от базовой и использовать ее.

Далее, по вопросу "куда все это добавить". Нужно добавлять на ту страницу, которая инициализирует запрос данных с сервера, то есть на страницу детали.
Теперь предлагаю Вам открыть исходный код страницы "BaseGridDetailV2", от которой наследуются все детали с реестром, и проследить, что происходит при загрузке детали. А происходит примерно следующее:
1. Сама "BaseGridDetailV2" наследуется от "BaseDetailV2". Метод, который вызывается в начале загрузки страницы, init определен именно там. Помимо всего прочего, он вызывает "initData", который уже определен в "BaseGridDetailV2".
2. В "initData" вызывается "loadGridData", который вызывает "this.mixins.GridUtilities.loadGridData". То есть идем в GridUtilitiesV2 и смотрим, что там.
3. Находим "loadGridData" и видим, что в нем вызывается ряд методов, которые формируют итоговый запрос, который будет выполнен для получения данных детали. Помимо прочих есть метод "initQueryFilters", который инициализирует фильтры экземпляра запроса.
4. Смотрим в него, а он просто добавляет те фильтры, которые вернет ему "this.getFilters()". Метод выполняется в контексте детиали, поэтому будет вызван тот "getFilters", который определен в детали. Вот мы и пришли к ответу на Ваш вопрос:
для того, чтобы модифицировать запрос, выполняемый для получения списка нужно на странице детали переопределить метод "getFilters" таким образом, чтобы он возвращал нужную группу фильтров. Именно эта группа и будет применена к запросу.
Надеюсь, понятно объяснил. )

Андрей, огромное спасибо :smile:

Подскажите, а как со страницы детали получить значения полей со страницы Активности? Копаюсь в переменной Terrasoft, но что то не могу ничего найти толкового. Чтобы было с чем сравнивать в фильтре

var columnValue = "some value"; //значение колонки

И еще может можно проще сделать вроде привязки к методу фильтрации как в продажах ?

"OppContactV2": {
	"schemaName": "OpportunityDetailV2",
	"entitySchemaName": "Opportunity",
	"filterMethod": "contactAccountFilter"
},

и возвращать необходимый фильтр в зависимости от заполненности полей

contactAccountFilter: function() {
	var filter;
	var contact =  this.get("Contact");
	var contactId = this.Terrasoft.GUID_EMPTY;
	if (contact && contact.value) {
	  contactId = contact.value;
	  filter = this.Terrasoft.createColumnFilterWithParameter( this.Terrasoft.ComparisonType.EQUAL, "Contact", contactId);
	};
	var account = this.get("Account");
	var accountId = this.Terrasoft.GUID_EMPY;
	if (account && account.value) {
	  accountId = account.value;
	  filter = this.Terrasoft.createColumnFilterWithParameter( this.Terrasoft.ComparisonType.EQUAL, "Account", accoutnId);
	};
	return filter;

Олег, страница и деталь могут общаться посредством сообщений. Например, в методе updateDetail на BaseGridDetailV2 происходит как раз получение параметров из карточки:

var detailInfo = this.sandbox.publish("GetDetailInfo", null, [this.sandbox.id]) || {};

Публикуется сообщение GetDetailInfo. А в BasePageV2 есть метод subscribeDetailEvents, где происходит подписка на это сообщение:

sandbox.subscribe("GetDetailInfo", function() {...}, this, [detailId]);

И когда деталь публикует это сообщение, на странице вызывается функция, которая передается вторым параметром и возвращает результат. Третий параметр - контекст выполнения функции, четвертый - Id детали, на сообщение от которой происходит подписка.

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