Добрый день, Коллеги!

На нескольких проектах столкнулись со следующей ситуацией.

Описания кейса:



1) Рассмотрим раздел обращения, Колонки "Контакт" и "Контрагент".

Пробуем добавить новый контакт через "Всплывающее действие" при вводе не существующего ФИО в системе.



https://yadi.sk/i/OQCOmeQw3TedkE



В результате при клике на "действие создания" далее откроется миникарточка контакта для заполнения.

Штатный функционал работает корректно.

 

Потребность:

Необходимо добавить сложный фильтр для lookup "Контакта".

Логика фильтра: Если "Контрагент" заполнен, то отображать к выбору только те контакты, у которых на детали "Карьера контакта" (деталь в разделе контакт) есть записи по связанному контрагенту, Который выбран в обращении.



Был выбран способ реализации путём задания фильтра через атрибуты.

"Contact": {
                lookupListConfig: {
                    filters: [
                        function() {
                            var accountId = this.get("Account");
                            var filterGroup = Ext.create("Terrasoft.FilterGroup");
                            if (accountId){
                                var filterById = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "[ContactCareer:Contact].Account", accountId.value);
                                filterGroup.add("filterById", filterById);
                            return filterGroup;
                        }
                    ]
                }
            }



Фильтрация работает корректно.



2) Однако возникла следующая проблема, которой нет при создании фильтров через бизнес-правила:



При указании такого фильтра, пытаемся выполнить шаги пункта (1) по добавлению не существующего в системе контакта и действием вызвать миникарточку.

В результате после добавления подобного фильтра, действие по добавлению нового значения просто не появляется при указанном Контрагенте.



https://yadi.sk/i/4baUZyPr3Tee7E



Есть только возможность выбора из отфильтрованных значений.



https://yadi.sk/i/a-qH6I0R3TefZq

https://www.screencast.com/t/6Mu2hFnkt



Если, согласно условию if, Контрагент не заполнен, то действие для создания появляется.



https://yadi.sk/i/HaQF5U1L3Teg7r



Коллеги, просим подсказать как можно обойти подобное поведение?

Возможно есть простой способ реализации подобного фильтра через бизнес-правила? У нас попросту не получилось организовать подобный фильтр другим способом.

Заранее спасибо!

Нравится

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

Чисто в теории в LookupQuickAddMixin отсекается возможность быстрого создания, если функция checkIsComplicatedFiltersExists вернёт true. Можно прям на странице переопределить эту функцию

checkIsComplicatedFiltersExists: function() {
	return false;
}

и система предложит создать контакта. Не факт, однако, что что-нибудь не накроется тазом в какой-то момент (не зря же есть функция по проверки сложных фильтров). Лично я быстро накидал, потестил на дефолтной странице договора - все отрабатывает.

Варфоломеев Данила,

Спасибо за подсказку! Закрыли задачу!

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

Можно ли настроить расширенный фильтр по обращениям такого вида: отображать все обращения, с учетом вхождения текущего пользователя в группу поддержки указанную в обращении.

Нравится

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

Здравствуйте, Павел!

Фильтр настроить можно, необходимо фильтр по текущему контакту накладывать на развязочную таблицу "Вхождение пользователя в роли".

Выглядеть он будет так: http://prntscr.com/io67sn

Настройка: http://prntscr.com/io689w

"Количество" потом поменять на "Существует", и внутри указать, собственно, фильтр по текущему контакту.

Спасибо большое!

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

Помогите пожалуйста отфильтровать справочное поле на клиенте,

У меня есть объект CreditCard у которого есть деталь [залоговое обеспечение] они связаны между собой через колонку  [залоговое обеспечение].CCId(идентификатор кредитной карты).

Так же в объекте [залоговое обеспечение] есть справочное поле [Контакт] собственно именно его я и хочу отфильтровать. Чтобы в нем появлялись только те контакты которые присутствуют в другой детали в CreditCard - CC_TxParticipant(деталь) которые связаны так же как и [залоговое обеспечение] через колонку CCId(идентификатор кредитной карты).

 

В детали CC_TxParticipant есть два справочных поля - 1. Контакт 2. Тип контакта, так вот я не совсем понимаю как сделать так чтобы во время фильтра отсеивались контакты с определенным типом.

 

Сейчас для фильтрации только [Контактов] из CC_TxParticipant я делаю так:

"lookupListConfig": {
"filters": [
function() {
...
var allParticipantsFilter = this.Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "[CC_TxParticipant:Participant:Id].CC", master.value);
...
    }
]

где master.value = идентификатор CreditCard, потом добавляю фильтр в общий фильтр и так далее, таким образом я получаю только тех контактов которые присутствуют в детали CC_TxParticipant именно этого CreditCard

-----------------

Попробую объяснить подробнее

Есть следующие объекты:

 

0.[CreditCard] - к нему относятся 2 детали:

1.[CC_TxParticipant] - связана с [CreditCard] через колонку CCId(идентификатор [CreditCard])

2.[CC_CollateralData] - связана с [CreditCard] через колонку CCId(идентификатор [CreditCard])

 

В объекте [CC_TxParticipant] есть справочное поле Контакт, и справочное поле с типом участника.

В объекте [CC_CollateralData] есть справочное поле Контакт которое требуется отфильтровать таким образом, чтобы появлялись только те контакты которые находятся в детали объекта [CC_TxParticipant], кроме тех у которых скажем Тип участника не равен *какой то айди*.

На данный момент у меня получилось только отфильтровать таким образом чтобы отображались только те контакты которые находятся в объекте [CC_TxParticipant] без учета их типа.

master.value  в коде выше как раз является идентификатором [CreditCard]

Понимаю что объяснение получилось запутанное, поэтому заранее прошу прощения

Нравится

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

Добрый вечер.

Что бы отсеять контакты по типу нужно добавить фильтр где в качестве сравнения будет конфигурационная константа или id «типа контакта» (таблица ContactType). Например:

filterGroup.add("IsEmployeeType", Terrasoft.createColumnFilterWithParameter(                            Terrasoft.ComparisonType.EQUAL, "Contact.Type", ConfigurationConstants.ContactType.Employee));

При этом нужно не забыть указать зависимость на «ConfigurationConstants»:

define("ContactPageV2", ["ConfigurationConstants"],
function(ConfigurationConstants) {

Все типы констант вы можете посмотреть при отладке.

Или же можно сделать запрос используя id из таблицы ContactType:

 filterGroup.add("IsEmployeeType", Terrasoft.createColumnFilterWithParameter(                           Terrasoft.ComparisonType.EQUAL, "Contact.Type",” 806732EE-F36B-1410-A883-16D83CAB0980”));

 

VladKapitanchyk,

Добрый день,

Спасибо за совет, к сожалению построение обычного фильтра не составляет проблемы, мой вопрос несколько сложнее

Сериков Асхат Кайратович пишет:

VladKapitanchyk,

 мой вопрос несколько сложнее

Добрбый день! Если мы не правильно поняли, то просьба переформулировать запрос либо объяснить "на пальцах" . Мы ради будем помочь.

Вильшанский Дмитрий,

Добрый день,

прошу прощения за такой запутанный вопрос, переформулировал, надеюсь получилось

Добрый день.

Спасибо за совет, к сожалению построение обычного фильтра не составляет проблемы

Вам нужно составить фильтр из 2 условий. Т.е. добавить в фильтр группу 2 фильтра(фильтр контактов которые находятся в детали объекта [CC_TxParticipant], и фильтр контактов у которых Тип участника не равен *какой то айди*). На академии можно посмотреть. https://academy.terrasoft.ua/documents/technic-sdk/7-11/primenenie-filt…

VladKapitanchyk,

День добрый,

Разобрался, пытался перемудрить зачем то.

Спасибо большое

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

Помогите сделать фильтр:

Проблема такая: делаю в коде фильтр реестра (показать записи где я ответственный или записи где контрагенты с типом "Дебитор"). Делаю его в initQueryFilters

Все нормально фильтруется.

Но если зайти в расширенный фильтр и проставить другого ответственного. То мне отображаются чужие записи, которые  не должен видеть.

Т.е получается запрос вида owner= 'Иванов'(расширенный фильтр) OR owner = 'Я' OR Тип='Дебитор' . 

В какую сторону копать? В документации ничего не нашел

 

 

 

if(user=='Бизнес менеджер'){
  //esq уже на данном этапе содержит фильтр прилетевший от расширенного фильтра
 
  esq.filters.logicalOperation = Terrasoft.LogicalOperatorType.OR;
 
  //Мои фильтры
  var filterOwner = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,"Owner", key);
  sq.filters.addItem("Ответственный по контрагенту",filterOwner);
 
  var filterType = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,"Type", tDebt);
  esq.filters.addItem("Тип контрагента",filterType);
 
}

 

Нравится

1 комментарий

Вы можете настроить для данной таблицы права доступа на записи.

Само правило раздачи прав доступа реализовать, например, в бизнес-процессе, а бизнес-процесс запускать при сохранении новой записи или при сохранении существующей, но только в том случае, если менялись значения либо поля 'Ответственный', либо поля "Тип" = "Дебитор".

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

Есть у меня раздел, а у сущности есть поле "дата доставки".

Как мне отфильтровать так, чтобы вывести только объекты доставленные более Х дней назад, где Х - произвольное число?

Проблема в том, что мне надо занести этот фильтр в группу для пользователей, которые каждый день смотрят такие просрочки и каждый день надо сравнивать дату доставки с сегодня, т.е. с новой датой.

Там есть фильтр "Предыдущих дней", но он как-то странно работает.

Нравится

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

Здравствуйте, Алексей

Прошу Вас уточнить что Вы имеете ввиду под "...но он как-то странно работает"?

По возможности, прошу продемонстрировать что необходимо и как это работает в приложении.

Denys Diachenko,

Я ставлю <= Предыдущих дней "5" и получаю все сущности, как будто и фильтрации не было.

Если я что-то делаю не так, подскажите как. И, если знаете, расскажите, что это за фильтр такой? В какой запрос он конвертируется?

У функции сравнения с датой есть интересная фича (кажется, недокументированная):

Когда Вы используете фильтр <= 100 то учитываются предыдущие 100 дней.

А когда Вы устанавливаете <100, то учитываются даты которые были до предыдущих 100 дней.

 

Владимир Соколов,

Блин, точно! Равенство здесь применять нельзя для моего случая.

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

Добрый день!

Часто возникают ситуации, когда в различных разделах системы добавляются новые категории (например, в поле Состояние заказа добавилась новая категория - Перевод в проект). Из-за такого рода обновлений в системе  фильтры некоторых блоков итогов в дашборде становятся неактуальными, а если дашбордов много, то то держать их в тонусе тяжело.

Вопрос - есть ли возможность выгружать настроенные фильтры во всех  дашбордах в отдельный файл?

Нравится

1 комментарий

Здравствуйте, Александр!

На данный момент, в системе не предусмотрена выгрузка в файл фильтров, согласно которым формируются дашборды В приложении есть возможность выгружать отфильтрованные данные в файл формата *.csv.

Мы зарегистрировали Ваше пожелание, аналитики продукта рассмотрят возможность его реализации в последующих релизах приложения. 

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

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

 Всем пример

Делаю быстрый фильтр по примеру из документации.

Визуально фильтры создаются, но они не заполнены значениями и фильтрация соответственно не работает.

Кейс простой при клике на элементе "Контрагенты"- отобразить уже отфильтрованный реестр. 

Подскажите где моя ошибка или чего я не понимаю

define("AccountSectionV2", ["BaseFiltersGenerateModule","jQuery"], function(BaseFiltersGenerateModule) {
 
 
 
 
	return {
		entitySchemaName: "Account",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		attributes: {
 
        },
		methods: {
			initFilters: function() {
				  console.log("initFilters");
					this.initFilterActions();
					this.initFixedFiltersConfig();
					this.subscribeFiltersChanged();
					this.subscribeFilterGetConfigMessages();
					this.loadFiltersModule();
				},
			initQueryFilters: function(esq) {
				//this.callParent(arguments);
				console.log("initQueryFilters");
					var filters = this.getFilters();
					if (filters) {
						console.log(filters);
						esq.filters.addItem(filters);
                 	}
 
	          },
 
			// Инициализирует фиксированные фильтры.
            initFixedFiltersConfig: function() {
            	console.log("initFixedFiltersConfig");
                // Создание конфигурационного объекта.
                var fixedFilterConfig = {
                    // В качестве схемы объекта для фиксированных фильтров указывается схема объекта раздела.
                    entitySchema: this.entitySchema,
                    // Массив фильтров.
                    filters: [
                                   // Фильтр периода.
                        {
                            // Название фильтра.
                            name: "PeriodFilter",
                            // Заголовок фильтра.
                            caption: this.get("Resources.Strings.PeriodFilterCaption"),
                            // Тип данных — дата.
                            dataValueType: this.Terrasoft.DataValueType.DATE,
                            // Дата начала периода фильтрации.
                            startDate: {
                                // Фильтруются данные из колонки [Date].
                                columnName: "StartDate",
                                // Значение по умолчанию.
                                defValue: this.Terrasoft.startOfWeek(new Date())
                            },
                            // Дата завершения периода фильтрации.
                            dueDate: {
                                columnName: "StartDate",
                                defValue: this.Terrasoft.endOfWeek(new Date())
                            }
                        },
                        // Фильтр ответственного.
                        {
                            // Название фильтра.
                            name: "Owner",
                            // Заголовок фильтра.
                            caption: this.get("Resources.Strings.OwnerFilterCaption"),
                            // Фильтрация данных из колонки [Owner].
                            columnName: "Owner",
                            // В качестве значения по умолчанию указывается контакт текущего пользователя.
                            // Значение берется из системной настройки.
                            defValue: this.Terrasoft.SysValue.CURRENT_USER_CONTACT,
                            // Тип данных — справочник.
                            dataValueType: this.Terrasoft.DataValueType.LOOKUP,
                            // Фильтр.
                            filter: BaseFiltersGenerateModule.OwnerFilter
                        }
                    ]
                };
                // Колонке [FixedFilterConfig] присваивается ссылка на созданный конфигурационный объект.
                this.set("FixedFilterConfig", fixedFilterConfig);
            }
 
 
		}
	};
});

Изображение удалено.

Нравится

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

1) Сложно без кода страницы что-то конкретное сказать.

2) У вас точно колонка Owner в объекте есть? И точно ли она ссылается на Контактов.

3) " ...при клике на элементе "Контрагенты"..." — При чём тут контрагенты?

Варфоломеев Данила,

1. Код щас приложу

2. Owner - точно есть

3. Мне надо показать пользователю в реестре только созданных им контрагентов

1) Resources.Strings.OwnerFilterCaption не определён в localizableStrings, поэтому на скрине пустота

2) Пусто внутри выборки контрагентов потому, что срабатывает фильтр 

filter: BaseFiltersGenerateModule.OwnerFilter

Подробнее - посмотрите в BaseFiltersGenerateModule, если не нужна фильтрация - закомментируйте эту строчку

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

Здравствуйте, продолжаю осваивать версию 7.10 после 10 лет использования 3.0.4.122.

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

Нравится

1 комментарий

Попробуйте строить примерно такую фильтрацию для совмещения даты и времени:

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

Здравствуйте, Коллеги! У меня возник вопрос по фильтрам, почему когда массив arrayNeededIdOfSalesCenter пуст, он мне выводит все значения, а не пустоту? Когда массив не пуст, все нормально отрабатывает. Как получить именно пустоту? Заранее спасибо за помощь.
"ITSaleCenter": {
"lookupListConfig": {
"filters": [
function() {
var currentSaleArea = this.get("ITSaleArea"),
filterGroupMain = Ext.create("Terrasoft.FilterGroup");
if (currentSaleArea) {
var arrayNeededIdOfSalesCenter = [];
this.get("CollectionSaleCenter").each(function(item) {
arrayNeededIdOfSalesCenter.push(item.get("ITSysAdminUnit.Name"));
});
filterGroupMain.add("IsNeededNameSaleCenter",
Terrasoft.createColumnInFilterWithParameters(
"Name",
arrayNeededIdOfSalesCenter));
}
return filterGroupMain;
}
]
}
},

Нравится

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

Понял вас, самый простой способ проверить размер массива и добавить туда несуществующее значение.

"ITSaleCenter": {
"lookupListConfig": {
"filters": [
function() {
var currentSaleArea = this.get("ITSaleArea"),
filterGroupMain = Ext.create("Terrasoft.FilterGroup");
if (currentSaleArea) {
var arrayNeededIdOfSalesCenter = [];
this.get("CollectionSaleCenter").each(function(item) {
arrayNeededIdOfSalesCenter.push(item.get("ITSysAdminUnit.Name"));
});

if (arrayNeededIdOfSalesCenter.length == 0) {
arrayNeededIdOfSalesCenter.push("#!@^");
}

filterGroupMain.add("IsNeededNameSaleCenter",
Terrasoft.createColumnInFilterWithParameters(
"Name",
arrayNeededIdOfSalesCenter));
}
return filterGroupMain;
}
]
}
},

В таком случае при отсутствии значений в arrayNeededIdOfSalesCenter, ITSaleCenter будет пуст.

Да, поведение не совсем очевидное, но оно действительно такое.
Необходимо проверять массив на пустоту, перед формированием фильтра, если он не пуст - формируем Ваш createColumnInFilterWithParameters, в случае пустого массива - возвращать другой фильтр, специальный который всегда в окне справочника будет выдавать "пустоту"
я обычно использую такой "попросим вернуть Id равные NULL":

Terrasoft.createColumnIsNullFilter("Id");

решение универсальное, колонка Id у нас есть везде, а нулевые значения в ней не встречаются :)

Всем спасибо :)

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

В окне выбора контрагента при первом нажатии на лупу пусто. При повторном появляются нужные строки. Происходит это из-за того, что в запрос дописываются строки
LEFT OUTER JOIN
[dbo].[tbl_AccountInGroup] AS [tbl_AccountInGroupAccountID] ON [tbl_AccountInGroupAccountID].[AccountID] = [tbl_Account].[ID]

[tbl_AccountInGroupAccountID].[GroupID] = @P4

Нам эта таблица вообще не нужна, мы ею не пользуемся. Во вьюшке vw_Account ее нет. Почему она цепляется к запросу и как от нее избавиться?

Детали в прикрепленном файле

Нравится

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

Либо эта связь прописана в sq, на основе которой построен датасет, либо накладывается программно в карточке на событии открытия лукапа.

В sq этой связи нет. В коде не нашел. Код ниже. Может быть, подскажете, где конкретно это может быть?

function edtAccountOnPrepareSelectWindow(LookupDataControl, SelectWindow) {
if (System.GetLocalComputerName() == 'PEUWUD14431') {
debugger;
}
var LookupDataset = LookupDataControl.DataField.LookupDataset;
var CallContactID = dlData.Dataset('ContactID');
var CallDeliveryPointID = dlData.Dataset('DeliveryPointID');
EnableDatasetFilters(LookupDataset, false);
EnableDatasetFilters(LookupDataset, true, ['LawOrPersonType']);
EnableDatasetFilters(LookupDataset, true, ['IsTurnedOff']);
ApplyDatasetFilter(LookupDataset, 'CallDeliveryPointID', CallDeliveryPointID,
!IsEmptyValue(CallDeliveryPointID));
if (IsEmptyValue(CallDeliveryPointID)) {
ApplyDatasetFilter(LookupDataset, 'CallContactID', CallContactID,
!IsEmptyValue(CallContactID));
}
}

function Initialize(Window) { // if (System.GetLocalComputerName() == 'PEUWUD14431') { debugger; }
InitializeGlobalVariables();
InitializeDataset(Window);
InitializeButtons(SelectData.Dataset);
InitializeGlobalDatalinks();
InitializeGroups(SelectData.Dataset, Window);
InitializeGridArea(Window);
SetWindowCaption(Window);
ReadAttributes(Window);
InitalizeImages(Window);
edtSearchFor.Value = SelectData.SearchValue;
if (SelectData.IsInitialized != true) {
AddDisplayFields();
SelectData.IsInitialized = true;
}
AddSearchFields();
}

function SimpleWindowOnPrepare(Window) {
if (Window.Attributes('EventsLogTag') == 2) {
return;
}
if (Main.ToLogGridWindow && (Window.TemplateWindowUSI == 'wnd_BaseGridArea')) {
EventLog_ParseObjectInfo(Window);
} else if (Main.ToLogEditWindow &&
((Window.TemplateWindowUSI == 'wnd_BaseDBEdit') ||
(Window.TemplateWindowUSI == 'wnd_BaseDBEditEx'))) {
EventLog_ParseObjectInfo(Window);
}
Window.Attributes('EventsLogTag') = 2;
}

В sq этой связи нет. В коде не нашел. Код ниже. Может быть, подскажете, где конкретно это может быть?

function edtAccountOnPrepareSelectWindow(LookupDataControl, SelectWindow) {
if (System.GetLocalComputerName() == 'PEUWUD14431') {
debugger;
}
var LookupDataset = LookupDataControl.DataField.LookupDataset;
var CallContactID = dlData.Dataset('ContactID');
var CallDeliveryPointID = dlData.Dataset('DeliveryPointID');
EnableDatasetFilters(LookupDataset, false);
EnableDatasetFilters(LookupDataset, true, ['LawOrPersonType']);
EnableDatasetFilters(LookupDataset, true, ['IsTurnedOff']);
ApplyDatasetFilter(LookupDataset, 'CallDeliveryPointID', CallDeliveryPointID,
!IsEmptyValue(CallDeliveryPointID));
if (IsEmptyValue(CallDeliveryPointID)) {
ApplyDatasetFilter(LookupDataset, 'CallContactID', CallContactID,
!IsEmptyValue(CallContactID));
}
}

function Initialize(Window) { // if (System.GetLocalComputerName() == 'PEUWUD14431') { debugger; }
InitializeGlobalVariables();
InitializeDataset(Window);
InitializeButtons(SelectData.Dataset);
InitializeGlobalDatalinks();
InitializeGroups(SelectData.Dataset, Window);
InitializeGridArea(Window);
SetWindowCaption(Window);
ReadAttributes(Window);
InitalizeImages(Window);
edtSearchFor.Value = SelectData.SearchValue;
if (SelectData.IsInitialized != true) {
AddDisplayFields();
SelectData.IsInitialized = true;
}
AddSearchFields();
}

function SimpleWindowOnPrepare(Window) {
if (Window.Attributes('EventsLogTag') == 2) {
return;
}
if (Main.ToLogGridWindow && (Window.TemplateWindowUSI == 'wnd_BaseGridArea')) {
EventLog_ParseObjectInfo(Window);
} else if (Main.ToLogEditWindow &&
((Window.TemplateWindowUSI == 'wnd_BaseDBEdit') ||
(Window.TemplateWindowUSI == 'wnd_BaseDBEditEx'))) {
EventLog_ParseObjectInfo(Window);
}
Window.Attributes('EventsLogTag') = 2;
}

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

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