Добрый день!
Задача такая - в разделе Заказы есть деталь Площадка - объект, куда необходимо доставить продукт. Площадок в заказе может быть несколько. Необходимо отобразить на карте объекты в выбранных заказах.

На странице OrderSectionV2 добавила кнопку "Показать площадку на карте", при этом в В define и function прописала "MapsUtilities", "MapsHelper".
Добавила функцию:

openShowOnMap: function() {
                                var items = this.getSelectedItems();//отмеченные галкой заказы - массив
                                var Farm = [];//массив площадок
                                var select = Ext.create("Terrasoft.EntitySchemaQuery", {
                                        rootSchemaName: "UsrPlatform1C"
                                });
                                select.addColumn("UsrPlatform");
                                select.addColumn("UsrOrder");
                                select.filters.add("UsrPlatformId", this.Terrasoft.createColumnInFilterWithParameters("UsrOrder", items));
                                select.getEntityCollection(function(result) {
                                        if (result.success) {
                                                Terrasoft.each(result.collection.getItems(), function(item) {
                                                        Farm.push(item.set("UsrPlatform").value);
                                                });
                                        }
                                });
                                var selectS = Ext.create("Terrasoft.EntitySchemaQuery", {
                                        rootSchemaName: "UsrFarm"
                                });
                                selectS.addColumn("Id");
                                selectS.addColumn("UsrName");
                                selectS.addColumn("UsrAdress");
                                selectS.addColumn("UsrCity");
                                selectS.addColumn("UsrRegion");
                                selectS.addColumn("UsrCountry");
                                selectS.addColumn("UsrGPSN");
                                selectS.addColumn("UsrGPSE");
                                selectS.filters.add("FarmId", this.Terrasoft.createColumnInFilterWithParameters("Id", Farm));
                                selectS.getEntityCollection(function(result) {
                                        if (result.success) {
                                                var mapsConfig = {
                                                        mapsData: []
                                                };
                                                result.collection.each(function(item) {
                                                                var address = [];
                                                        if (item.get("UsrCountry") && item.get("UsrCountry").displayValue) {
                                                                address.push(item.get("UsrCountry").displayValue);
                                                        }
                                                        if (item.get("UsrRegion") && item.get("UsrRegion").displayValue) {
                                                                address.push(item.get("UsrRegion").displayValue);
                                                        }
                                                        if (item.get("UsrCity") && item.get("UsrCity").displayValue) {
                                                                address.push(item.get("UsrCity").displayValue);
                                                        }
                                                        address.push(item.get("UsrAdress"));
                                                        var dataItem = {
                                                                caption: item.get("UsrName"),
                                                                content: "

"

+ item.get("UsrName") + "
"
+ address.join(", ") + "
",
                                                                address: item.get("UsrAdress") ? address.join(", ") : null,
                                                                //конвертирование полей долготы и широты
                                                                gpsN: parseFloat(item.get("UsrGPSN")),
                                                                gpsE:  parseFloat(item.get("UsrGPSE")),
                                                                updateCoordinatesConfig: {
                                                                        schemaName: "UsrFarm",
                                                                        id: item.get("Id")
                                                                }
                                                        };
                                                        mapsConfig.mapsData.push(dataItem);
                                                });
                                                MapsUtilities.open({
                                                        scope: this,
                                                        mapsConfig: mapsConfig
                                                });
                                        }
                                }, this);
                        }

При отладке кода выяснила, что фильтрация по выбранным заказам выполняется, получаем выбранные заказы и площадки в этих заказах.
А в запросе при выборе Адреса, Региона, Страны получаем данные ВСЕХ площадок, которые есть в базе данных, а не только полученных из предыдущего запроса. (скриншот во вложении). Помогите, пожалуйста, разобраться в чем ошибка в фильтрации в запросе!!!

Нравится

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

Здравствуйте, Юлия.

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

И на момент добавления фильтра в строке:

selectS.filters.add("FarmId", this.Terrasoft.createColumnInFilterWithParameters("Id", Farm));

массив Farm пустой. Следовательно, фильтрация не отрабатывает. Рекомендую Вам смотреть в сторону использования метода Terrasoft.chain или же формировать второй запрос к базе данных в callback функции первого запроса, а если точнее то сразу после кода:

Terrasoft.each(result.collection.getItems(), function(item) {
            Farm.push(item.set("UsrPlatform").value);
        });

Илья, спасибо большое за Ваш ответ.

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

Доброго времени суток!
Возможно ли присоединить схему по обратным связям к схему, которая в свою очередь тоже была присоединена по обратным связям?
К примеру: необходимо отфильтровать справочное поле Контакт, и вывести туда все контакты, входящие в определенную группу пользователей. Т.е. присоединить SysAdminUnit, а к ней SysUserInRole.
Конечно можно вместо справочника Контакт использовать Объект администрирования, и проблема отпадет. Данная фильтрация приведена для примера. Интересует возможность построения таких связей.

Нравится

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

Здравствуйте, Олег.

Предложенным Вами способом решить данную задачу не получится. Вот здесь Вы можете посмотреть решение похожей задачи.

Спасибо

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

Доброго времени суток!
Есть развязочная таблица товаров и статей. Справочное поле "Статья" фильтруется по выбранному товару, на основе развязочной таблицы. Каким образом можно вывести все статьи, если в развязочной таблице отсутствуют записи по выбранному товару?

Нравится

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

Олег, здравствуйте!

Пример фильтрации можете посмотреть в схеме «ActivityPageV2» фильтр по колонке «Result».

Спасибо!

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

Здравствуйте.
Скажите пожалуйста, можно ли убрать из воронки продаж определенные стадии?
Стандартный функционал фильтрации не подходит, т.к. стадия в воронке все-равно присутствует, но со значением 0.

Как отфильтровать воронку,чтобы осталось всего 5 нужных стадий?

Нравится

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

Добрый день, Александр!

Если необходимо минимум вмешательства, а стадии используются не совсем как задумано, то можно их отфильтровать следующим образом: в воронке не отображаются конечные не успешные стадии. То есть, можно всем тем, которые не должны отображаться, установить поле End = 1, а поле Successful = 0.

Если же этот функционал используется, то фильтрацию можно добавить только вмешательством в код. Необходимо замещать модуль OpportunityFunnelDrillDownProvider, полностью копировать его код в новый модуль, и вносить необходимые изменения в метод getFunnelAllowedStagesFilters (для версии 7.6) либо в initOpportunityStage (для версии 7.5).

а разве это не решается через Справочники - Стадии продаж?

"Антон Кравченко" написал:а разве это не решается через Справочники - Стадии продаж?

На базе без данных мы удалили ненужные стадии. Правда, клиент не использует референтный процесс

"Антон Кравченко" написал:а разве это не решается через Справочники - Стадии продаж?

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

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

"Пащенко Александр Сергеевич" написал:Изначально был сделан новый процесс продаж и лишние стадии были удалены, но они снова появились после очередного обновления системы и установки данных, привязанных к пакетам.

Лишние стадии мешают не только в воронке продаж, но и в самой карточке продажи

"Пащенко Александр Сергеевич" написал:Изначально был сделан новый процесс продаж и лишние стадии были удалены, но они снова появились после очередного обновления системы и установки данных, привязанных к пакетам.

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

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

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

Добрый день!
Подскажите, пожалуйста, как правильно обратиться к результату выполнения запроса с использованием прямых связей.
Вот такой пример

есть объект сервис, берем из него в запросе контрагента владельца сервиса,
и значение контрагента получаем и записываем.

var serviceItem = this.get("ServiceItem");
if (!serviceItem) {
return;
}
var select = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "ServiceItem"
});
select.addColumn("Owner.Account");
select.filters.add("ServiceItemIdFilter",
select.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Id", serviceItem.value));
select.getEntityCollection(function(result) {
if (result.success && result.collection.getCount()) {
var entity = result.collection.getByIndex(0);

this.set("UsrColumn", entity.values.Owner.Account);

}
}, this);

Вопрос - как правильно получить здесь значение контрагента ответственного в последней строке?
Такой способ неправильный entity.values.Owner.Account...

Если бы в select получили бы просто select.addColumn("Owner"),
то обратиться можно было бы entity.values.Owner
А как правильно обращаться в случае более сложного селекта select.addColumn("Owner.Account")?
Подскажите, пожалуйста
entity.values.Owner

Нравится

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

Можно добавить колонку в select следующим образом:

select.addColumn("Owner.Account","OwnerAccount");

И затем получить ее по заданному имени:

this.set("UsrColumn", entity.get("OwnerAccount"));

спасибо

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

Добрый день!
Пример с использованием обратных связей
var servicePact = this.get("ServicePact");
if (!servicePact) {
return;
}
var filtersCollection = this.Terrasoft.createFilterGroup();
filtersCollection.add("ServiceItemByServicePactFilter", this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
"[ServiceInServicePact:ServiceItem].ServicePact", servicePact.value));

return filtersCollection;

выполняет следующий запрос
select * from ServiceItem
where exists(select * from ServiceInServicePact
where ServiceInServicePact.ServiceItemID = ServiceItem.ID and
ServiceInServicePact.ServicePactID = @value)

т.е. показываются только те сервисы, которые есть в этом сервисном договоре.

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

select * from ServiceCategory
where exists(select * from ServiceInServicePact
inner join ServiceItem on ServiceInServicePact.ServiceItemID=ServiceItem.ID
where ServiceItem.CategoryID = ServiceCategory.ID and
ServiceInServicePact.ServicePactID = @value)

Нравится

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

Попробовала такой вариант для вышеописанного запроса

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "ServiceCategory"});
esq.addColumn("Id");
esq.filters.add("servicePactAndCategoryFilter", this.getServiceCategoryFilters());

где
getServiceCategoryFilters: function() {
var servicePact = this.get("ServicePact");
if (!servicePact) {
return;
}
var filtersCollection = this.Terrasoft.createFilterGroup();
filtersCollection.add("ServiceCategoryByServicePactFilter", this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL, "[ServiceInServicePact.ServiceItem:ServiceCategory].ServicePact", servicePact.value));
return filtersCollection;

но такой вариант не работает.

Интересует - насколько корректна конструкция ? filtersCollection.add("ServiceCategoryByServicePactFilter", this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL, "[ServiceInServicePact.ServiceItem:ServiceCategory].ServicePact", servicePact.value));

Аналогична ли она условию в запросе
select * from ServiceCategory
where exists(select * from ServiceInServicePact
inner join ServiceItem on ServiceInServicePact.ServiceItemID=ServiceItem.ID
where ServiceItem.CategoryID = ServiceCategory.ID and
ServiceInServicePact.ServicePactID = @value) ?

Если такая конструкция неверна, то каким образом можно использовать прямые связи в обратных для получения подобного запроса?

Добрый день, Дарья!

Данная логика является специфичной и у нас нет примеров реализации данного функционала, но вероятнее всего в фильтре, который Вы пытаетесь построить должна быть колонка «[ServiceItem:Category].[ServiceInServicePact: ServiceItem].ServicePact».

Спасибо, Елена!
Думаю, это то, что нужно
Итак, фильтр на объект ServiceCategory
«[ServiceItem:Category].[ServiceInServicePact: ServiceItem].ServicePact».

Насколько я поняла, этот фильтр дает такой запрос
select * from ServiceCategory
where exists (select * from ServiceItem
where ServiceItem.CategoryID= ServiceCategory.ID
and exists (select * from ServiceInServicePact
where ServiceInServicePact.ServiceItemId = ServiceItem.ID
and ServiceInServicePact.ServicePactId = @value))

что в общем-то накладывает необходимое условие.

Елена, скажите, пожалуйста, я правильно поняла действие этого условия
[ServiceItem:Category].[ServiceInServicePact: ServiceItem].ServicePact ?

Не могли бы вы пояснить, какой в результате фильтр в терминах sql накладывается на ServiceCategory,
если применить условие
[ServiceItem:Category].[ServiceInServicePact: ServiceItem].ServicePact

Да, Елена, проверила!
Это условие действительно то самое.
Спасибо!

Всегда рада помочь:)

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

Добрый день!

Достаточно тривиальная задача, но не могу разобраться с разбегу.

Создаю пользовательское окно фильтрации FastReport, само окно зависит от выбранного элемента.

Собственно, внимание вопрос: как получить ID выбранного элемента в окне фильтрации?

Нравится

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

Вы хотите выбрать в гриде запись и по ней строить отчёт?
Может, grdData.SelectedIDs?

Нет, не совсем. Запись уже строится, я редактирую пользовательское окно фильтрации FastReport.

То есть, запись УЖЕ выбрана и отчёт по ней УЖЕ строится стандартными средствами, но для фильтрации мне нужно поймать ID этой записи.

Логика запуска построения отчёта по выбранной записи определена в функции ReportMenuItemExecute в скрипте scr_ReportUtils. Насколько вижу, там вызывается одна функция ShowSelectedRecordsReport для отчёта по выбранным записям, но без окна фильтрации, а другая ShowReport — по всем записям, но с окном.

Можно специально для Вашего отчёта дописать третий случай — и с окном, и с выбранными записями. Например, передавать в окно отчёта wnd_BaseFastReportPreview ID записи или IDs записей, а затем в scr_BaseFastReportPreview передавать их в окно фильтрации.

Я сначала несколько удивился тому, что в окно не передаётся ID выбранных записей. Потом почитал исходники и выяснил, что таки передаются. ID банально берутся из Атрибута Self.

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

Все блоги автора

Задача: необходимо реализовать возможность переключения реестра в разделе. То есть, находясь в разделе "Контрагенты" переключать реестры с физическими и юридическими лицами, причём у каждого реестра свои определенные колонки.

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

Решение состоит из 2х частей:

  • Добавить кнопки переключения между представлениями
  • Собственно сделать страницы представленийИзображение удалено.

Добавление кнопок переключения реестров в раздел

Подготовлены спрайты кнопок:

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

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

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

Размер 30*60. Смысл в том, чтобы при наведении мыши фон кнопки съезжал на 30 пикселей, и как бы подсвечивался. Создан модуль, назвать, например SmrCustomButtonsCSS и определить LESS:

.blue-button-wrapper {
     width: 30px;
     height: 30px;
     padding: 0px;
     margin: 0px 5px 0px 5px;
}
.blue-button-image {
     display: inline;
     background-position: 0px 0px;
     width: 30px;
     height: 30px;
     padding: 0px;
     margin: 0px;
}
.blue-button-image:hover {
     display: inline;
     background-position: 0px -30px;
}
.blue-button-pressed {
     display: inline;
     background-position: 0px -30px;
     width: 30px;
     height: 30px;
     padding: 0px;
     margin: 0px;
}

Создана замещающая страница "AccountSectionV2":

 

define("AccountSectionV2", ["ConfigurationConstants", "css!SmrCustomButtonsCSS"],
    function(ConfigurationConstants) {
        return {
            entitySchemaName: "Account",
            attributes: {  },
            methods: {
                showLegalView: function(){
                    this.sandbox. publish( "PushHistoryState", { hash : "SectionModuleV2/LegalAccountSectionV2" });
                },
                showIndividualView: function(){
                    this.sandbox. publish( "PushHistoryState", { hash : "SectionModuleV2/IndividualAccountSectionV2" });
                },
                showAllView: function(){
                    this.sandbox. publish( "PushHistoryState", { hash : "SectionModuleV2/AccountSectionV2" });
                },
                isSwitchButtonsContainerVisible: function() {
                    var isCardVisible = this.get("IsCardVisible");
                    return !isCardVisible;
                }
 
 
            },
            diff: /**SCHEMA_DIFF*/[
 
                {
                    "operation": "insert",
                    "name": "SwitchViewButtonsContainer",
                    "parentName": "ActionButtonsContainer",
                    "propertyName": "items",
                    "values": {
                        "itemType": Terrasoft.ViewItemType.CONTAINER,
                        "visible": {
                            "bindTo": "isSwitchButtonsContainerVisible"
                        },
                        "items": []
                    }
                },
                {
                    "operation": "insert",
                    "parentName": "SwitchViewButtonsContainer",
                    "propertyName": "items",
                    "name": "SwitchToAllDataView",
                    "values": {
                        "layout": {
                            "column": 23,
                            "row": 0,
                            "colSpan": 1,
                            "rowSpan": 1
                        },
                        "itemType": Terrasoft.ViewItemType.BUTTON,
                        "style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                        //"iconAlign": Terrasoft.controls.ButtonEnums.iconAlign.RIGHT,
                        iconAlign: Terrasoft.controls.ButtonEnums.iconAlign.TOP,
                        pressed: {bindTo: "LegalGridActive"},
                        "imageConfig": {
                            "source": Terrasoft.ImageSources.SOURCE_CODE_SCHEMA,
                            "params": {
                                "schemaName": "SmrCustomButtonsCSS",
                                "resourceItemName": "GridDataViewIconBlue"
                            }
                        },
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-pressed"
                        },
                        "click": {"bindTo": "showAllView"}
                    }
                },
                {
                    "operation": "insert",
                    "parentName": "SwitchViewButtonsContainer",
                    "propertyName": "items",
                    "name": "SwitchToPersonalDataView",
                    "values": {
                        "layout": {
                            "column": 23,
                            "row": 0,
                            "colSpan": 1,
                            "rowSpan": 1
                        },
                        "itemType": Terrasoft.ViewItemType.BUTTON,
                        "style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                        //"iconAlign": Terrasoft.controls.ButtonEnums.iconAlign.RIGHT,
                        iconAlign: Terrasoft.controls.ButtonEnums.iconAlign.TOP,
                        pressed: {bindTo: "LegalGridActive"},
                        "imageConfig": {
                            "source": Terrasoft.ImageSources.SOURCE_CODE_SCHEMA,
                            "params": {
                                "schemaName": "SmrCustomButtonsCSS",
                                "resourceItemName": "GridPersonalDataViewIconBlue"
                            }
                        },
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image"
                        },
                        "click": {"bindTo": "showIndividualView"}
                    }
                },
                {
                    "operation": "insert",
                    "parentName": "SwitchViewButtonsContainer",
                    "propertyName": "items",
                    "name": "SwitchToLegalDataView",
                    "values": {
                        "layout": {
                            "column": 23,
                            "row": 0,
                            "colSpan": 1,
                            "rowSpan": 1
                        },
                        "itemType": Terrasoft.ViewItemType.BUTTON,
                        "style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                        //"iconAlign": Terrasoft.controls.ButtonEnums.iconAlign.RIGHT,
                        iconAlign: Terrasoft.controls.ButtonEnums.iconAlign.TOP,
                        pressed: {bindTo: "LegalGridActive"},
                        "imageConfig": {
                            "source": Terrasoft.ImageSources.SOURCE_CODE_SCHEMA,
                            "params": {
                                "schemaName": "SmrCustomButtonsCSS",
                                "resourceItemName": "GridLegalDataViewIconBlue"
                            }
                        },
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image",
                            pressedClass: "blue-button-pressed"
                        },
                        "click": {"bindTo": "showLegalView"}
                    }
                }
 
            ]/**SCHEMA_DIFF*/
        };
    }
);

Страницы разделов

Созданы 2 страницы разделов. Код для реестра физических лиц:

define("IndividualAccountSectionV2", ["ConfigurationConstants", "css!SmrCustomButtonsCSS"],
    function(ConfigurationConstants) {
        return {
            entitySchemaName: "Account",
            methods: {
                /**
                 * Инициализирует  фильтры экземпляра запроса
                 * @protected
                 * @overridden
                 * @param {Terrasoft.EntitySchemaQuery} esq Запрос, в котором будут инициированы фильтры
                 */
                initQueryFilters: function (esq) {
                    this.callParent(arguments);
                    esq.filters.removeByKey("ClientType");
                    esq.filters.add("ClientType", this.Terrasoft.createColumnFilterWithParameter(
                        this.Terrasoft.ComparisonType.EQUAL, "SmrClientType.Id", "80FD3F74-0AF4-4F8A-9F0B-F626E4F05147"));
                },
                /**
                 * Возвращает представления раздела по умолчанию.
                 * Реестр, Аналитика не создаётся
                 * @overridden
                 * @return {Object} Представления раздела по умолчанию
                 */
                getDefaultDataViews: function() {
                    var gridDataView = {
                        name: this.get("GridDataViewName"),
                        caption: this.getDefaultGridDataViewCaption(),
                        icon: this.getDefaultGridDataViewIcon()
                    };
                    var analyticsDataView = {
 
                    };
                    return {
                        "GridDataView": gridDataView,
                        "AnalyticsDataView": analyticsDataView
                    };
                },
                /**
                 * Получает пункты меню кнопки "Вид"
                 * @overridden
                 * @virtual
                 * @return {Terrasoft.BaseViewModelCollection} Возвращает пункты меню кнопки "Вид"
                 */
                getViewOptions: function() {
                    var viewOptions = this.Ext.create("Terrasoft.BaseViewModelCollection");
                    viewOptions.addItem(this.getButtonMenuItem({
                        "Caption": {"bindTo": "Resources.Strings.SortMenuCaption"},
                        "Items": this.get("SortColumns")
                    }));
                    viewOptions.addItem(this.getButtonMenuItem({
                        "Caption": {"bindTo": "Resources.Strings.OpenGridSettingsCaption"},
                        "Click": {"bindTo": "openGridSettings"}
                    }));
                    return viewOptions;
                }
            },
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "SwitchToAllDataView",
                    "values": {
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image"
                        }
                    }
                },
                {
                    "operation": "merge",
                    "name": "SwitchToPersonalDataView",
                    "values": {
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-pressed"
                        }
                    }
                },
                {
                    "operation": "merge",
                    "name": "SwitchToLegalDataView",
                    "values": {
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image"
                        }
                    }
                }
            ]/**SCHEMA_DIFF*/
        };
    }
);

Код страницы для реестра юридических лиц:

define("LegalAccountSectionV2", ["RightUtilities", "ConfigurationConstants", "css!SmrCustomButtonsCSS"],
    function (RightUtilities, ConfigurationConstants) {
        return {
            entitySchemaName: "Account",
            attributes: {},
            messages: {},
            methods: {
                /**
                 * Инициализирует  фильтры экземпляра запроса
                 * @protected
                 * @overridden
                 * @param {Terrasoft.EntitySchemaQuery} esq Запрос, в котором будут инициированы фильтры
                 */
                initQueryFilters: function (esq) {
                    this.callParent(arguments);
                    esq.filters.removeByKey("ClientType");
                    esq.filters.add("ClientType", this.Terrasoft.createColumnFilterWithParameter(
                        this.Terrasoft.ComparisonType.EQUAL, "SmrClientType.Id", "DD4E6E34-21D3-4F09-A417-6FC4116876B5"));
                },
                /**
                 * Возвращает представления раздела по умолчанию.
                 * Реестр, Аналитика не создаётся
                 * @overridden
                 * @return {Object} Представления раздела по умолчанию
                 */
                getDefaultDataViews: function() {
                    var gridDataView = {
                        name: this.get("GridDataViewName"),
                        caption: this.getDefaultGridDataViewCaption(),
                        icon: this.getDefaultGridDataViewIcon()
                    };
                    var analyticsDataView = {
 
                    };
                    return {
                        "GridDataView": gridDataView,
                        "AnalyticsDataView": analyticsDataView
                    };
                },
                /**
                 * Получает пункты меню кнопки "Вид"
                 * @overridden
                 * @virtual
                 * @return {Terrasoft.BaseViewModelCollection} Возвращает пункты меню кнопки "Вид"
                 */
                getViewOptions: function() {
                    var viewOptions = this.Ext.create("Terrasoft.BaseViewModelCollection");
                    viewOptions.addItem(this.getButtonMenuItem({
                        "Caption": {"bindTo": "Resources.Strings.SortMenuCaption"},
                        "Items": this.get("SortColumns")
                    }));
                    viewOptions.addItem(this.getButtonMenuItem({
                        "Caption": {"bindTo": "Resources.Strings.OpenGridSettingsCaption"},
                        "Click": {"bindTo": "openGridSettings"}
                    }));
                    return viewOptions;
                }
            },
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "SwitchToAllDataView",
                    "values": {
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image"
 
                        }
                    }
                },
                {
                    "operation": "merge",
                    "name": "SwitchToPersonalDataView",
                    "values": {
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image"
                        }
                    }
                },
                {
                    "operation": "merge",
                    "name": "SwitchToLegalDataView",
                    "values": {
                        classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-pressed"
                        }
                    }
                }
            ]/**SCHEMA_DIFF*/
        };
    });

Что нужно отметить в этих страницах:

/**
 * Инициализирует  фильтры экземпляра запроса
 * @protected
 * @overridden
 * @param {Terrasoft.EntitySchemaQuery} esq Запрос, в котором будут инициированы фильтры
 */
initQueryFilters: function (esq) {
        this.callParent(arguments);
        esq.filters.removeByKey("ClientType");
        esq.filters.add("ClientType", this.Terrasoft.createColumnFilterWithParameter(
                this.Terrasoft.ComparisonType.EQUAL, "SmrClientType.Id", "DD4E6E34-21D3-4F09-A417-6FC4116876B5"));
}

Мы переопределяем метод для установки фильтрации записей (например, только физические лица).

Также, переопределяем методы getDefaultDataViews и getViewOptions, чтобы скрыть функции, которые не работают в новых реестрах (почему - не было времени разбираться).

 

Проблемы

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

P.S.: Очень ждем возможности использовать такую возможность базовыми средствами, кейсов много - это и деление на сотрудники/контакты и физ/юр лица. В ситуациях, когда набор колонок одинаковый, конечно рекомендуется пользоваться стандартными динамическими группами.

Нравится

Поделиться

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

Эх, еще бы это в Мастер раздела :)

Кстати, а кейс ведения физических и юридических лиц в Контрагентах давно стал практикой?

Это практика при условиях, что:

  • Клиенту нужно смотреть суммарную разнообразную аналитику по всем клиентам физики+юрики, создаваемую через стандартные средства (в представлении "Аналитика")
  • Клиента бесит, когда ему каждый раз заходя в раздел Контакты, нужно отфильтровывать своих сотрудников и сотрудников подрядчиков, чтобы поработать с клиентами:smile:

Александр, золотой вы человек :twisted:
Как раз ломал голову как бы не убить кучу времени и реализовать представления с переключением, а тут пример живой.

Рад помочь, для этого и нужно комьюнити:smile:. Если есть еще вопросы в стиле "В 3ке это делалось в 5 кликов аналитиком, а как это сделать это в 7ке?" - спрашивайте, наверняка найдем проектное решения в закромах, пусть и не всегда очевидное:lol:

"Александр Свистунов" написал:спрашивайте, наверняка найдем проектное решения в закромах

Я ж воспользуюсь :)
Case: отфильтровать в разделе Счета все счета, к которым прикреплен продукт = "ххх". То есть фильтр по вхождению некой информации в деталь - аналогично в любом разделе. Так как штатно доступны только фильтры по детали с агрегатной функцией, то видимо надо как-то добавлять свой фильтр?
В 3х это делалось через модификацию sq_, в 5х вроде как вообще работало штатно через обратные связи.
Раздел итоги элемент список не предлагать :) там делается посредством списка на основании Продукт в счете - пробовал, работает.

Александр, если я правильно понял ваш Кейс, то это делается через подобный фильтр

Продукт в счете

"Толмачев Дмитрий Юрьевич" написал:делается через подобный фильтр

Вот только сейчас сумел поменять count на exists - после того как выбрал хоть какую-то колонку при фильтрации по связанной таблице.
Именно это и было нужно, спасибо
Ну вот как надо было догадаться сначала выбрать произвольное поле типа Количество, чтобы попасть обратно в настройки фильтра... Идем и ищем (с)

Чтобы темы не плодить... товарищи, как бы попроще скрыть из меню Edit, Copy и особенно Delete для детали, основанной на вьюшке?
Деталь самодельная, родитель BaseGridDetailV2.

Александр,

Для решения вашей задачи достаточно переопределить функцию addRecordOperationsMenuItems на созданной вами странице реестра

methods: {
	/**
	 * @overridden
	 */
	addRecordOperationsMenuItems: Ext.emptyFn
	//...
}

"Толмачев Дмитрий Юрьевич" написал:Ext.emptyFn

Спасибо, попробую так.
Я ее нашел, только наивно переопределял как

addRecordOperationsMenuItems: function() {
}

То есть пытался заполнить "ничем"...

А я где-то такую функцию нашёл

getAddRecordButtonVisible: function() {
	return false;
},

Добрый день!

Александр, спасибо за предоставленной пример, остался один непонятный для меня момент, какие действия нужно выполнить, что бы новая страница раздела (например, IndividualAccountSectionV2) стала доступна по URL "http://localhost/0/Nui/ViewModule.aspx#SectionModuleV2/IndividualAccoun…"?

Сергей,

Если навскидку, то достаточно чтобы в качестве родительской страницы использовалась страница "Базовая схема раздела".

В данном случае, насколько я помню, у страниц LegalAccountSectionV2 и IndividualAccountSectionV2 в качестве родительской использовалась "AccountSectionV2", т.к. по сути это дочерние ветки.

Александр, большое спасибо за то что делитесь отличным материалом!

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

1. Правильно ли я понимаю, что через свойства Diff:

pressed: {bindTo: "LegalGridActive"},

и

classes: {
                            wrapperClass: "blue-button-wrapper",
                            imageClass: "blue-button-image",
                            pressedClass: "blue-button-pressed"
                        },

Вы указываете, будет ли элемент содержать класс "blue-button-pressed" ?
Если да, то что в этом случае должна возвращать функция "LegalGridActive" - true или false?

У меня на версии 7.7 не получилось сделать так, чтобы к елементу "прицепился" мой класс указанный в pressedClass (как у Вашем примере: pressedClass: "blue-button-pressed"). Вместо него появился "дефолтный" класс - t-btn-pressed.
вот код DIFF:

	{
		"operation": "insert",
		"parentName": "SignButtonsContainer",
		"propertyName": "items",
		"name": "SignBtnVip",
		"values": {
			"itemType": Terrasoft.ViewItemType.BUTTON,
			"caption": {"bindTo": "sign_Vip"},
			"hint": {"bindTo": "Resources.Strings.sign_Vip"},
			"imageConfig" : {"bindTo": "Resources.Images.sign_vip_Image"},
			//"click": {"bindTo": "onVipButtonClick"},
			pressed : {bindTo : "VipButtonPressed"},
			classes : {
				wrapperClass : "sign-btn",
				imageClass   : "sign-img",
				pressedClass : "sign-img-pressed"
			},
			"visible": true
		}
	},

В итоге вместо ожидаемого css-класса "sign-img-pressed" - появляется "t-btn-pressed". Не могу понять что я сделал не так...

2. Можно ли какимто образом отключить для моего елемента генерацию стандрартных css-классов?
(для элемента Terrasoft.ViewItemType.BUTTON сгенерировались - t-btn-wrapper, t-btn-no-text-padding, t-btn-style-default )

3. Глобальный вопрос - не могли бы Вы подсказать, какой подход можно применить для того, чтобы можно было динамически (например по кнопочке) добавлять или удалять указанные кастомные css-классы для элемента?

В целом, очень хорошо что в 7-ке есть возможность подключать свои css-стили, это очень удобно, но вот генерация самих классов для элемента происходит немного не очевидно... :smile:

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

Добрый день.
Возникла необходимость добавить в деталь блок быстрой фильтрации, как в модуле активности (даты, ответственный). Если с добавлением такого блока в другой раздел проблем нет, то с деталью все сложнее. Буду признателен за помощь в решении этой задачи.
BPM 7.5

Нравится

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

В 7.6 сделали функциональность такую, но крайне урезанную

Иван, добрый день!

Данный функционал был реализован в 7.6.
В 7.5. добавление фильтрации в детали трудозатратно, так как для данной реализации необходимо полностью переделывать модуль фильтрации, добавлять связи, добавлять колонки/поля и т.д.

Как вариант можете обновить приложение до версии 7.6.

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

Здравствуйте,

BPM 7.5.
Есть объекты "UsrDepartment" и "UsrKnowledgeLevel", связанные отношением "многие-ко-многим", т.е. с одним департаментом может быть связаны одно или несколько левелов, а один и тот-же левел может принадлежать многим департаментам. Создал для этой цели состаной справочник.

Составной справочник

Есть форма, на ней поля "Department" и "KnowledgeLevel". Нужно реализовать, чтобы при изменении значения департамента изменялся список доступных для выбора поле в "KnowledgeLevel". Как это реализовать? Лучше клиентским JavaScript, хотя можно и C#, только плиз опишите подробно, куда его тогда вставить.

Фильтрация левела от департмента

И еще вопрос, в данный момент подчинённый объект "KnowledgeLevel" НЕ содержит колонку-ссылка на родительский объект. Необходима ли она? И если да, как сделать так, чтобы она автоматически заполнялась UId выбранного департамента при добавлении записи "KnowledgeLevel" в окне составного справочника?

Спасибо!

Нравится

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

Думаю, что вам необходимо реализовать на js подобную конструкцию:

attributes: {
	"UsrKnowledgeLevel": {
		lookupListConfig: {
			filter: function() {
				var department = this.get("UsrDepartment");
				var leftExpression = "[UsrKnowledgeLevelInUsrDepartment:UsrKnowledgeLevel].UsrDepartment";
				var filter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
						leftExpression, department);
				return filter;
			}
		}
	}
}

*var leftExpression = "[UsrKnowledgeLevelInUsrDepartment:UsrKnowledgeLevel].UsrDepartment";

Подразумевается, что есть объект для связи "многие-ко-многим" - UsrKnowledgeLevelInUsrDepartment, у которого есть поля UsrKnowledgeLevel и UsrDepartment

Добрый день! Комментарий предоставлен по пунктам.

Настройка логики полей карточки (бизнес-правила)

Настройка происходит в карточке путем изменения конфигурации полей.

Подготовка
Для работы с бизнес правилами нужно добавить в страницу зависимость от модуля бизнес правил:

Пример
Название бизнес-правила может быть произвольным, но оно должно содержать в себе информацию о его предназначении.
Например, бизнес-правило по фильтрации поля Контакт по полю Контрагент может быть названо FiltrationContactByAccount.

rules: {
    "Contact": {
        FiltrationContactByAccount: {
            //Указываем тип правила
            ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
           //Указываем будет ли обратное автозаполнение
            autocomplete: true,
            //Указываем мета-путь относительно базового обьекта('Contact') 
            //по которому будем фильтровать
            baseAttributePatch: "Account",
            //Указываем тип фильтрации
            comparisonType: Terrasoft.ComparisonType.EQUAL,
            //Указываем тип значения для фильтрации
            type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
            //Указываем атрибут модели для сравнения (если тип значения - атрибут)
            attribute: "Account",
            //Указываем мета-путь значения в выбранном атрибуте (если нужно)
            attributePath: "",
            //Если тип значения не атрибут, указываем значение 
            //(константа | имя системной настройки | имя системного значения)
            value: ""
        }
    },
    "City": {
        FiltrationCityByCounty: {
            ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
            autocomplete: true,
            baseAttributePatch: "Country",
            comparisonType: Terrasoft.ComparisonType.EQUAL,
            type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
            attribute: "Country",
            attributePath: "",
            value: ""
        },
        FiltrationCityByRegion: {
            ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
            autocomplete: true,
            baseAttributePatch: "Region",
            comparisonType: Terrasoft.ComparisonType.EQUAL,
            type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
            attribute: "Region",
            attributePath: "",
            value: ""
        }
    }
}

Описание зависимостей между колонками, нужно указывать в описание колонок в объекте attributes в свойстве колонки dependencies
Наложении произвольной фильтрации, сортировка и добавление дополнительных колонок в запрос при отображении выпадающего списка нужно указывать явно в описание колонок в объекте attributes в свойстве колонке lookupListConfig.

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

attributes: {
    "Probability": {
        dependencies: [
            {
                columns: ["Owner"],
                methodName: "getProbability"
            }
        ],
        lookupListConfig: {
            columns: ["Value"],
            orders: [
                {
                    columnPath: "Value",
                    direction: Terrasoft.OrderDirection.DESC
                }
            ],
            filter: function() {
                return Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.GREATER,
                    "Value", 40);
            }
        }
    }
}

Спасибо, заработало! Правда Вы немного ошиблись в createColumnFilterWithParameter, нужно 3м параметром не "department", а "department.value", и после этого работает! Правда, если в поле KnowledgeLevel выбрал левел для Department1, и мы меняем департмент на Department2, то поле не очищается от прежнего значения, уже, возможно, некорректного для Department2.
Вот мой полный код:

attributes: 
{
    "UsrKnowledgeLevel":
    {
        lookupListConfig:
            {
                filter: function () {
                    var department = this.get("UsrDepartmentUsr");
                    var leftExpression = "[UsrDepartmentByLevel:UsrKnowledgeLevel].UsrDepartment";
                    var filter = Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL,
						leftExpression,
						department.value
					);
                    return filter;
                }
            }
    }
Показать все комментарии