Создал иерархическую деталь с редактируемым реестром. Но появилась проблема при количестве дочерних элементов больше 8. Они почему не отображаются, выдается ошибка Cannot read property 'getAttribute' of null. В БД всё верно. 

Вот код детали

define("IDSBRefrigeratorInTMADetail",
    ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"],
    function () {
        return {
            messages: {
                "ReloadRefrigeratorsInTMAGrid": {
                    "mode": Terrasoft.MessageMode.BROADCAST,
                    "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
                }
            },
            entitySchemaName: "IDSBRefrigeratorInTMA",
            attributes: {
                "IsEditable": {
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: true
                }
            },
            mixins: {
                ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
            },
            details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "DataGrid",
                    "values": {
                        "hierarchical": true,
                        "hierarchicalColumnName": "IDSBParent",
                        "maxColumns": 48,
                        "maxRowsCount": 10000,
                        "className": "Terrasoft.ConfigurationGrid",
                        "generator": "ConfigurationGridGenerator.generatePartial",
                        "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
                        "changeRow": { "bindTo": "changeRow" },
                        "unSelectRow": { "bindTo": "unSelectRow" },
                        "onGridClick": { "bindTo": "onGridClick" },
                        "activeRowAction": { "bindTo": "onActiveRowAction" },
                        "initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
                        "multiSelect": false
                    }
                },
                {
                    "operation": "remove",
                    "name": "AddRecordButton"
                }]/**SCHEMA_DIFF*/,
            methods: {
                generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {
                    this.columnsConfig = columnsConfig;
                    var gridData = this.getGridData();
                    var activeRow = gridData.get(id);
                    var isEditableColumn;
                    if (activeRow.values.IDSBParent === "") {
                        isEditableColumn = this.isEditableParentColumn;
                    }
                    else {
                        isEditableColumn = this.isEditableColumn;
                    }
                    var gridLayoutItems = [];
                    var currentColumnIndex = 0;
                    Terrasoft.each(columnsConfig, function (columnConfig) {
                        var cellConfig = this.getActiveRowCellConfig(columnConfig, currentColumnIndex);
                        cellConfig.enabled = isEditableColumn(cellConfig.name);
                        if (!cellConfig.hasOwnProperty("isNotFound")) {
                            gridLayoutItems.push(cellConfig);
                        }
                        currentColumnIndex += cellConfig.layout.colSpan;
                    }, this);
                    this.applyBusinessRulesForActiveRow(id, gridLayoutItems);
                    var viewGenerator = Ext.create(this.getRowViewGeneratorClassName());
                    viewGenerator.viewModelClass = this;
                    var gridLayoutConfig = viewGenerator.generateGridLayout({
                        name: this.name,
                        items: gridLayoutItems
                    });
                    rowConfig.push(gridLayoutConfig);
                },
                isEditableParentColumn: function (columnName) {
                    return false;
                },
                isEditableColumn: function (columnName) {
                    return (columnName === "IDSBBottlePlan");
                }/*,
                init: function () {
                    this.callParent(arguments);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },
                onReloadRefrigeratorsInTMAGrid: function (args) {
                    this.reloadGridData();
                }*/
            }
	};
});

 

Нравится

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

Для упрощения отладки посмотрите SQL профайлером запросы которые отправляются в БД.

Григорий Чех, думаете нужно заместить метод addGridDataColumns?

Григорий имел в виду использование профайлера. Естественно, только для случаев, когда есть доступ к серверу БД.

посмотрел профайлер. Выполняется следующий запрос. Забил его сам в SQL Management. Выдал недостающие элементы, которые как раз невыведены на экран. Ошибка возникает когда нажимаю "Показать больше"

SELECT
	[IDSBRefrigeratorInTMA].[Id] [Id],
	[IDSBRefrigeratorInTMA].[IDSBStreet] [IDSBStreet],
	[IDSBRefrigeratorInTMA].[IDSBCustomerInTMAId] [IDSBCustomerInTMAId],
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] [ITTradeMarketId],
	[ITTradeMarket].[ITName] [ITTradeMarket.ITName],
	[IDSBRefrigeratorInTMA].[MonthId] [MonthId],
	[Month].[Name] [Month.Name],
	[IDSBRefrigeratorInTMA].[IDSBBottlePlan] [IDSBBottlePlan],
	[IDSBRefrigeratorInTMA].[IDSBParentId] [IDSBParentId],
	[IDSBParent].[IDSBStreet] [IDSBParent.IDSBStreet],
	[ITTradeMarket].[ITTypeId] [ITTradeMarket.ITTypeId],
	[ITType].[Name] [ITType.Name],
	(
SELECT
	COUNT([SubEntryPoint].[Id]) [Count]
FROM
	[dbo].[EntryPoint] [SubEntryPoint] WITH(NOLOCK)
WHERE
	[SubEntryPoint].[EntityId] = [IDSBRefrigeratorInTMA].[Id]
	AND [SubEntryPoint].[IsActive] = 1) [SubEntryPoint],
	[IDSBRefrigeratorInTMA].[CreatedOn] [CreatedOn],
	[IDSBRefrigeratorInTMA].[CreatedById] [CreatedById],
	[CreatedBy].[Name] [CreatedBy.Name],
	[CreatedBy].[PhotoId] [CreatedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ModifiedOn] [ModifiedOn],
	[IDSBRefrigeratorInTMA].[ModifiedById] [ModifiedById],
	[ModifiedBy].[Name] [ModifiedBy.Name],
	[ModifiedBy].[PhotoId] [ModifiedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ProcessListeners] [ProcessListeners]
FROM
	[dbo].[IDSBRefrigeratorInTMA] [IDSBRefrigeratorInTMA] WITH(NOLOCK)
	LEFT OUTER JOIN [dbo].[ITTradeMarket] [ITTradeMarket] WITH(NOLOCK) ON ([ITTradeMarket].[Id] = [IDSBRefrigeratorInTMA].[ITTradeMarketId])
	LEFT OUTER JOIN [dbo].[Month] [Month] WITH(NOLOCK) ON ([Month].[Id] = [IDSBRefrigeratorInTMA].[MonthId])
	LEFT OUTER JOIN [dbo].[IDSBRefrigeratorInTMA] [IDSBParent] WITH(NOLOCK) ON ([IDSBParent].[Id] = [IDSBRefrigeratorInTMA].[IDSBParentId])
	LEFT OUTER JOIN [dbo].[ITITTradeMarketType1] [ITType] WITH(NOLOCK) ON ([ITType].[Id] = [ITTradeMarket].[ITTypeId])
	LEFT OUTER JOIN [dbo].[Contact] [CreatedBy] WITH(NOLOCK) ON ([CreatedBy].[Id] = [IDSBRefrigeratorInTMA].[CreatedById])
	LEFT OUTER JOIN [dbo].[Contact] [ModifiedBy] WITH(NOLOCK) ON ([ModifiedBy].[Id] = [IDSBRefrigeratorInTMA].[ModifiedById])
WHERE
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] = '54368FDE-6D00-4BDE-BAAE-EDEA56EBAA33'
ORDER BY
	[Id] ASC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

 

Может, 8 элементов видно как раз из-за выборки порциями по 10? Судя по окончанию SQL-запроса, это как раз вторая десятка, первая пропущена.

А где именно вылетает «Cannot read property 'getAttribute' of null», полный стек не видно?

Вылетает на этом методе. В строке var n = this.getDomRow(i) в n кладется undefined и далее соответственно вылетает ошибка. В i в этот момент родительская колонка

onCollectionDataLoaded: function(e, t, a) {
        if (this.theoreticallyActiveRows = null,
        !this.rows.length)
            return this.collection = this.collection || e,
            this.prepareCollectionData(),
            void this.safeRerender();
        if (!Ext.Object.isEmpty(t) && this.rendered) {
            var r = []
              , s = {
                rows: r
            };
            if (t.each(function(e) {
                this.prepareCollectionItem(e);
                var t = this.getRow(e);
                r.push(t),
                a && ("top" !== a.mode ? this.rows.push(t) : this.rows.splice(0, 0, t))
            }, this),
            this.hierarchical && !t.isEmpty()) {
                var i = t.getByIndex(0).get(this.hierarchicalColumnName);
                if (s[this.hierarchicalColumnName] = i,
                "listed" === this.type && i) {
                    var n = this.getDomRow(i)
                      , o = parseInt(n.getAttribute("level"), 10);
                    s.rowLevel = o + 1
                }
            }
            var l = [];
            this.renderGrid(l, s);
            for (var c = "", h = 0, u = l.length; h < u; h += 1)
                c += Ext.DomHelper.createHtml(l[h]);
            Ext.Object.isEmpty(a) && (a = {
                mode: "bottom"
            }),
            this.addRows(c, a),
            this.checkNeedLoadData()
        }
    },

 

Что-то не могу найти такой функции в «коробке».

А иерархичность и редактируемость сами по себе совместимы? На других таких деталях ограничения в 8 нет?

Если убираю редактируемость, ошибка не исчезает. Если убираю иерархичность, всё отображается нормально

Это логично, если сбой при превышении 8 потомков. В плоской детали никаких потомков нет. Сравните с другими иерархическими деталями, есть там такое ограничение или нет?

Решил проблему. Добавил значения атрибутов, чтобы всё грузилось сразу. В моем случае такое решение вполне подходит

init: function () {
                    this.callParent(arguments);
                    this.set("IsPageable", false);
                    this.set("RowCount", 28000);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },

 

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

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

Добрый день! Подскажите, пожалуйста, кто как решал задачу с добавлением, сохранением и использованием регистрационных данных (ИНН, ЕДРПОУ (Украина)) 

Нравится

8 комментариев
Лучший ответ

Виктория,

Вариантов реализации масса)))

Можно, как предложил Гриша, и это, наверное, самый простой способ, который однако не позволяет хранить историю изменения этих данных.

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

А можно ещё объединить эти 2 варианта и реализовать синхронизацию данных в карточке и детали, как это настроено, например, в карточке контакта для основных средств связи или должность с деталью карьера.

В конечном счете все зависит от Ваших потребностей в работе с данной функциональностью.

Быстро и дешево расширить нужные вам объекты и добавить туда ИНН, ЕДРПОУ ....

Григорий Чех,

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

В версии 3.Х было при помощи механизма пользовательских полей сделано сложнее, с возможностью настройки реквизитов по странам и добавлением произвольных  полей нужного типа. При желании можно попробовать реализовать что-то подобное.

Зверев Александр,

Спасибо, этот вариант тоже очень интересен.

Виктория,

Вариантов реализации масса)))

Можно, как предложил Гриша, и это, наверное, самый простой способ, который однако не позволяет хранить историю изменения этих данных.

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

А можно ещё объединить эти 2 варианта и реализовать синхронизацию данных в карточке и детали, как это настроено, например, в карточке контакта для основных средств связи или должность с деталью карьера.

В конечном счете все зависит от Ваших потребностей в работе с данной функциональностью.

Алла Савельева,

Спасибо. У меня была иллюзия, что есть какой-то стандартный вариант решения данной задачи :)

Немировская Виктория пишет:

У меня была иллюзия, что есть какой-то стандартный вариант решения данной задачи :)

На самом деле, для разработчика данная задача не является сложной.

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

Синхронизировать данные можно попробовать с помощью бизнес-процессов и для этого в них использовать пользовательские средства настройки.

Я эти поля в AccountBillingInfo добавил

Показать все комментарии
Добрый день, коллеги,
Не подскажете, как настроить фильтр по Сервису и Группе ответственных в карточке Обращения в продукте bpm'online Customer Center?
Что сделано и что имеем:
Продукт - bpm'online Customer Center
  1. В схему Custom добавил Объект UsrServiceEngineer
  2. В объект UsrServiceEngineer добавил два поля UsrServiceItem и UsrEngineer типа справочник
Изображение удалено.
Изображение удалено.
Изображение удалено.
 
3. Добавил новую Схему модели представления детали с реестром UsrServiceEngineerDetail
Изображение удалено.
4. В схему ServiceItemPage добавить код для добавления детали в раздел Сервисы:
==
 
define("ServiceItemPage", [], function() {
                return {
                               entitySchemaName: "ServiceItem",
                               attributes: {},
                               modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
                               details: /**SCHEMA_DETAILS*/{
                                               "UsrServiceEngineerDetail": {
                                                               "schemaName": "UsrServiceEngineerDetail",
                                                               "entitySchemaName": "UsrServiceEngineer",
                                                               "filter": {
                                                                               "detailColumn": "UsrServiceItem",
                                                                               "masterColumn": "Id"
                                                               }
                                               }
                               }/**SCHEMA_DETAILS*/
==
5. Деталь привязана и наполнена для каждого Сервиса в разделе Сервисы.

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

 

 

Коллеги, не подскажете, как настроить фильтр по Сервису и Группе ответственных в карточке обращения в продукте bpm'online Customer Center?

Нужно реализовать фильтр, чтобы при выборе Сервиса в карточке Обращения, автоматически выбирались только те Группы ответственных, которые связаны с выбранным Сервисом по детали Сервисные инженеры.

Заранее благодарен.

--

С уважением,

Дмитрий.

Нравится

2 комментария
Лучший ответ

Добрый день!

Добавьте на странице обращения данный атрибут:

attributes: {
	"Group": {
		lookupListConfig: {
			"filters": [
                      function() {
                          var service = this.get("ServiceItem");
						  var filterGroup = Ext.create("Terrasoft.FilterGroup");
						  if (service) {
							var serviceFilter = Terrasoft.createColumnFilterWithParameter(
								Terrasoft.ComparisonType.EQUAL, "[UsrServiceEngineer:UsrEngineer].UsrServiceItem", service.value);
							  filterGroup.add("filter1", serviceFilter);
						  }
                          return filterGroup;
                      }
                  ]
		}
 
	}
},

 

Добрый день!

Добавьте на странице обращения данный атрибут:

attributes: {
	"Group": {
		lookupListConfig: {
			"filters": [
                      function() {
                          var service = this.get("ServiceItem");
						  var filterGroup = Ext.create("Terrasoft.FilterGroup");
						  if (service) {
							var serviceFilter = Terrasoft.createColumnFilterWithParameter(
								Terrasoft.ComparisonType.EQUAL, "[UsrServiceEngineer:UsrEngineer].UsrServiceItem", service.value);
							  filterGroup.add("filter1", serviceFilter);
						  }
                          return filterGroup;
                      }
                  ]
		}
 
	}
},

 

Сидоров Александр В.,

Александр, огромнейшее спасибо!!!

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

Добрый день!

В коробке в карточке "Сотрудник" есть поле "Подразделение" типа Справочник.

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

Есть ли возможность в отдельном поле типа Справочник создать аналогичный формат поиска записи?

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

Нравится

4 комментария
Лучший ответ

Добрый день!

Нужно на странице объявить атрибут:

"OrgStructureUnit": {
	"lookupConfig": {
		"hierarchical": true
	},
	"lookupListConfig": {
		"columns": ["FullName", "Head", "Parent.Head"]
	}
},

И ваш справочник должен поддерживать иерархичность: иметь ссылку Parent на себя.

Подробнее можно посмотреть на странице EmployeePage

Добрый день!

Нужно на странице объявить атрибут:

"OrgStructureUnit": {
	"lookupConfig": {
		"hierarchical": true
	},
	"lookupListConfig": {
		"columns": ["FullName", "Head", "Parent.Head"]
	}
},

И ваш справочник должен поддерживать иерархичность: иметь ссылку Parent на себя.

Подробнее можно посмотреть на странице EmployeePage

Сидоров Александр В.,

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

Выбор система предлагает делать в виде дерева. Это заработало. 

Только в результате в поле указывается не "FullName", а "Name".

Требуется ли прописывать дополнительный код или FullName должно заполняться сразу?

Вот пример кода (по сути тут указаны все те же настройки, что и для коробочного поля):

"UsrDep": {

                    "lookupConfig": {

                        "hierarchical": true

                    },

                    "lookupListConfig": {

                        "columns": ["FullName", "Head", "Parent.Head"]

                    }

                }

Можно попробовать на уровне схемы справочника сменить первичное поле для отображения.

Коллеги, спасибо!

Вопрос решен. Ранее уже про правку кода нашел примеры в логике, на которую Сидоров Александр ссылался.

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

Добрый день, коллеги)



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

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



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

Нравится

2 комментария
Лучший ответ

Через мастер раздела. Нажимаете "Редактировать мини-карточку", далее выбираете мини-карточку просмотра.

Через мастер раздела. Нажимаете "Редактировать мини-карточку", далее выбираете мини-карточку просмотра.

Поля,которые отображаются на миникарточке просмотра имеют такие вот свойства:

{
	"operation": "insert",
	"name": "ModifiedOn33771683-e6ec-4df3-b715-8c71fe93163a",
	"values": {
		"layout": {
			"colSpan": 24,
			"rowSpan": 1,
			"column": 0,
			"row": 13,
			"layoutName": "MiniPage"
		},
		"isMiniPageModelItem": true,
		"visible": {
			"bindTo": "isViewMode"
		},
		"bindTo": "ModifiedOn"
	},
	"parentName": "MiniPage",
	"propertyName": "items",
	"index": 8
},

 

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

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

Нравится

5 комментариев
Лучший ответ

Добрый день!

Если не нужно при этом генерировать сигналы объектов, то посоветую реализовать все в хранимой процедуре. Там уже реализовать цикл. Тем самым вы добьетесь максимальной производительности. А процедуру вызывать в скрипте C#.

Добрый день!

Если не нужно при этом генерировать сигналы объектов, то посоветую реализовать все в хранимой процедуре. Там уже реализовать цикл. Тем самым вы добьетесь максимальной производительности. А процедуру вызывать в скрипте C#.

Если доступа к серверу нет, то можно и без хранимок, используя в C#-скрипте БП классы Select и Update. С ними тоже сигналы не генерируются. А если нужно, чтобы по каждой записи отрабатывала логика встроенных и отдельных БП на изменение ответственного, то только с использованием класса EntitySchemaQuery.

Зверев Александр,

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

 

Пробовал реализовать через esq: 

          var isOwnerInChange = true;

           while (isOwnerInChange) {

                var subQuery = new EntitySchemaQuery(_uc.EntitySchemaManager,"UsrChangeOwnerHelperLog");

                    subQuery.AddColumn("UsrEntityId");

    

                var entitySchemaManager = _uc.EntitySchemaManager;

                var esq = new EntitySchemaQuery(entitySchemaManager, "Название схемы");

                esq.UseAdminRights = false;

                esq.AddAllSchemaColumns();



              //  какие то фильтры

                

                var mainFilter = new EntitySchemaQueryFilter(FilterComparisonType.NotExists);

                    mainFilter.LeftExpression = esq.CreateSchemaColumnExpression("Id");

                    mainFilter.RightExpressions.Add(new EntitySchemaQueryExpression(subQuery));

                    esq.Filters.Add(mainFilter);

                

                esq.RowCount=1000;

                    

                var entities = esq.GetEntityCollection(_uc);

                

                if (entities.Count > 0)

                    {

                        foreach (Entity entity in entities)

                        {

                            var entityId = entity.GetTypedColumnValue<Guid>("Id");

                            var newOwnerId = SearchOwner(accountId, "Account");



                            //Какая то логика

                        }

                } else {

                    isOwnerInChange = false;

                }

            }

В конце не забудьте каждой entity.Save();

Показать все комментарии
	var controlConfig = {
		text: {
			customConfig: {
				className: "Terrasoft.MemoEdit",
				height: "150px",
			},
			dataValueType: Terrasoft.DataValueType.TEXT,
			caption: "Поле 1:",
			value: ""
		},
		costs: {
			customConfig: {
				className: "Terrasoft.FloatEdit",
			},
			dataValueType: Terrasoft.DataValueType.FLOAT,
			caption: "Поле 2:",
			value: { bindTo: "getСosts" }
		}
	};
	Terrasoft.utils.inputBox("Заголовок",
		function(buttonCode, controlData) {
			if (buttonCode === "ok") {
//Что-то делаем
			}
		},
		["ok", "cancel"],
		this,
		controlConfig,
		{defaultButton: 0}
	);

Есть такой код. Не могу заполнить поля value из переменной (атрибута/функции). Подскажите, как правильно забиндиться? Если написать в value какое значение сразу, то все работает, а если попробовать забиндиться, то пусто.

Нравится

2 комментария
Лучший ответ

Добрый день!

Не очень понятен кейс, зачем нужно биндить значения этих полей.

Заполнить их можно при создании объекта controlConfig. Если надо из переменной, то, например так:

costs: {
	customConfig: {
		className: "Terrasoft.FloatEdit",
	},
	dataValueType: Terrasoft.DataValueType.FLOAT,
	caption: "Поле 2:",
	value: this.get("getСosts")
}

 

Добрый день!

Не очень понятен кейс, зачем нужно биндить значения этих полей.

Заполнить их можно при создании объекта controlConfig. Если надо из переменной, то, например так:

costs: {
	customConfig: {
		className: "Terrasoft.FloatEdit",
	},
	dataValueType: Terrasoft.DataValueType.FLOAT,
	caption: "Поле 2:",
	value: this.get("getСosts")
}

 

Сидоров Александр В., спасибо, решение оказалось проще, чем я думал.

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

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

Нравится

2 комментария
Лучший ответ

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

Подробнее о настройке выгрузки исходного кода и его отладке почитайте в статье.

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

Подробнее о настройке выгрузки исходного кода и его отладке почитайте в статье.

Если есть доступ в базу, можно делать выборку по полю Source таблицы SysSchemaSource (для C#-кода) и Content таблицы SysSchemaContent (для JS-кода).

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

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

В разделе создал пользовательские фильтры Улица, Дом , Квартира. Значения в фильтре Дом зависят от Улицы, а значения в фильтре Квартира от значения Дом.

Если нажимать на "лупу" то фильтрация успешно отрабатывает. Но если вводить значения в поле - фильтр в выпадающем списке не срабатывает.

Как реализовать фильтрацию выпадающего списка в разделе?

Код схемы раздела:

define("VcApartments1Section", ["BaseFiltersGenerateModule", "css!VcMyFilterStyle"], 
function(BaseFiltersGenerateModule) {
	return {
		entitySchemaName: "VcApartments",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "MyFilterGroupContainer",
				"parentName": "LeftGridUtilsContainer",
				"propertyName": "items",
				"index": 0,
				"values": {
					"id": "MyFilterGroupContainer",
					"itemType": this.Terrasoft.ViewItemType.CONTAINER,
					"items": []
				}
			},
			{
				"operation": "insert",
				"name": "MyFilterContainer",
				"parentName": "MyFilterGroupContainer",
				"propertyName": "items",
				"index": 0,
				"values": {
					"id": "MyFilterContainer",
					"itemType": this.Terrasoft.ViewItemType.CONTAINER,
					"items": []
				}
			},
			{
				"operation": "insert",
				"parentName": "MyFilterContainer",
				"propertyName": "items",
				"name": "VcStreetFilter",
				"values": {
					"bindTo": "VcStreetFilter",
					"caption": "Улица"
				}
			},
			{
				"operation": "insert",
				"name": "MyFilterContainer2",
				"parentName": "MyFilterGroupContainer",
				"propertyName": "items",
				"index": 1,
				"values": {
					"id": "MyFilterContainer2",
					"itemType": this.Terrasoft.ViewItemType.CONTAINER,
					"items": []
				}
			},
				{
				"operation": "insert",
				"parentName": "MyFilterContainer2",
				"propertyName": "items",
				"name": "VcHouseFilter",
				"values": {
					"bindTo": "VcHouseFilter",
					"caption": "Дом"
					// "controlConfig": {
					// 	"prepareList": {
	    //                         "bindTo": "VcHouseFilter"
	    //                     }
					// // "contentType": Terrasoft.ContentType.ENUM
					// }
				}
			},
			{
				"operation": "insert",
				"name": "MyFilterContainer3",
				"parentName": "MyFilterGroupContainer",
				"propertyName": "items",
				"index": 2,
				"values": {
					"id": "MyFilterContainer3",
					"itemType": this.Terrasoft.ViewItemType.CONTAINER,
					"items": []
				}
			},
			{
				"operation": "insert",
				"parentName": "MyFilterContainer3",
				"propertyName": "items",
				"name": "VcNameFilter",
				"values": {
					"bindTo": "VcNameFilter",
					"caption": "Квартира"
				}
			}
			]/**SCHEMA_DIFF*/,
		attributes: {
			"VcStreetFilter": {
				"dataValueType": Terrasoft.DataValueType.LOOKUP,
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				isLookup: true,
				caption: "VcStreet",
				referenceSchemaName: "VcStreet"
			},
			"VcHouseFilter": {
				"dataValueType": Terrasoft.DataValueType.LOOKUP,
				"lookupListConfig": {
					// Массив фильтров, применяемых к запросу для формирования данных поля-справочника.
					"filters": [
						function() {
							var filterGroup = Ext.create("Terrasoft.FilterGroup");
							var VcStreetFilter = this.get("VcStreetFilter");
							if (VcStreetFilter && VcStreetFilter.value) {
							filterGroup.add("VcStreetFilter",Terrasoft.createColumnFilterWithParameter
							(Terrasoft.ComparisonType.EQUAL, "[VcHouses:Id].VcStreet", VcStreetFilter.value));
							} else {
								filterGroup.removeByKey("VcStreetFilter");
							}
							return filterGroup;
						}
					]
				},
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				isLookup: true,
				caption: "VcHouse",
				referenceSchemaName: "VcHouses"
			},
			"VcNameFilter": {
				"dataValueType": Terrasoft.DataValueType.LOOKUP,
				"lookupListConfig": {
					// Массив фильтров, применяемых к запросу для формирования данных поля-справочника.
					"filters": [
						function() {
							var filterGroup = Ext.create("Terrasoft.FilterGroup");
							var VcHouseFilter = this.get("VcHouseFilter");
							if (VcHouseFilter && VcHouseFilter.value) {
							filterGroup.add("VcHouseFilter",Terrasoft.createColumnFilterWithParameter
							(Terrasoft.ComparisonType.EQUAL, "[VcApartments:Id].VcHouse", VcHouseFilter.value));
							} else {
								filterGroup.removeByKey("VcHouseFilter");
							}
							return filterGroup;
 
						}
					]
				},
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				isLookup: true,
				caption: "VcName",
				referenceSchemaName: "VcApartments"
			}
		},
		mixins: {
			LookupQuickAddMixin: "Terrasoft.LookupQuickAddMixin"
		},
		methods: {
			onLookupChange: function(newValue, columnName) {
				this.callParent(arguments);
				if (columnName === "VcStreetFilter") {
					this.set("VcStreetFilter", newValue);
					this.onVcStreetFilterChanged();
				}
				if (columnName === "VcHouseFilter") {
					this.set("VcHouseFilter", newValue);
					this.onVcHouseFilterChanged();
				}
				if (columnName === "VcNameFilter") {
					this.set("VcNameFilter", newValue);
					this.onVcNameFilterChanged();
				}
			},
 			// Обновляет грид
			onVcStreetFilterChanged: function() {
				this.reloadGridData();
			},
 
			onVcHouseFilterChanged: function() {
				this.reloadGridData();
			},
 
 			onVcNameFilterChanged: function() {
				this.reloadGridData();
			},
			// Инициализирует фиксированные фильтры
			initQueryFilters: function(esq) {
				this.callParent(arguments);
			// Фильтр по Улице
				var VcStreetFilter = this.get("VcStreetFilter");
 
				if (VcStreetFilter && VcStreetFilter.value) {
					esq.filters.add("VcStreetFilter", this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL, "[VcApartments:Id].VcStreet", VcStreetFilter.value));
				} else {
					esq.filters.removeByKey("VcStreetFilter");
				}
			// Фильтр по Дому
				var VcHouseFilter = this.get("VcHouseFilter");
 
				if (VcHouseFilter && VcHouseFilter.value) {
					esq.filters.add("VcHouseFilter", this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL, "[VcApartments:Id].VcHouse", VcHouseFilter.value));
				} else {
					esq.filters.removeByKey("VcHouseFilter");
				}
			// Фильтр по названию
				var VcNameFilter = this.get("VcNameFilter");
 
				if (VcNameFilter && VcNameFilter.value) {
					esq.filters.add("VcNameFilter", this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL, "[VcApartments:Id].Id", VcNameFilter.value));
				} else {
					esq.filters.removeByKey("VcNameFilter");
				}
			}
		}
	};
});

 

Нравится

2 комментария
Лучший ответ

Сталкивался с подобной проблемой. Пришлось заместить данные методы на странице редактирования (в моем случае) InvoiceSectionV2

			/**
			 * @inheritdoc Terrasoft.BaseViewModel#onLookupDataLoaded
			 * @override
			 */
			onLookupDataLoaded: function(config) {
				this.callParent(arguments);
				this.mixins.LookupQuickAddMixin.onLookupDataLoaded.call(this, config);
			},
			getLookupListConfig: function() {
				return this.mixins.LookupQuickAddMixin.getLookupListConfig.apply(this, arguments);
			},
 
			/**
			 * @inheritdoc Terrasoft.BaseViewModel#getLookupQuery
			 * @override
			 */
			getLookupQuery: function(filterValue, columnName) {
				var esq = this.callParent(arguments);
				this.applyColumnsOrderToLookupQuery(esq, columnName);
				var filterGroup = this.getLookupQueryFilters(columnName);
				esq.filters.addItem(filterGroup);
				return esq;
			},
			/**
			 * Applies order information to lookup entity schema query.
			 * @protected
			 * @param {Terrasoft.EntitySchemaQuery} esq Entity schema query.
			 * @param {String} columnName Lookup column name.
			 */
			applyColumnsOrderToLookupQuery: function(esq, columnName) {
				var lookupColumn = this.getColumnByName(columnName);
				var lookupListConfig = lookupColumn.lookupListConfig;
				if (!lookupListConfig || !lookupListConfig.orders) {
					return;
				}
				var columns = esq.columns;
				this.Terrasoft.each(lookupListConfig.orders, function(order) {
					var orderColumnPath = order.columnPath;
					if (!columns.contains(orderColumnPath)) {
						esq.addColumn(orderColumnPath);
					}
					var sortedColumn = columns.get(orderColumnPath);
					var direction = order.direction;
					sortedColumn.orderDirection = direction ? direction : Terrasoft.OrderDirection.ASC;
					var position = order.position;
					sortedColumn.orderPosition = position ? position : 1;
					this.shiftColumnsOrderPosition(columns, sortedColumn);
				}, this);
			},
			/**
			 * Shift columns order position.
			 * @private
			 * @param {Array} columns Entity columns.
			 * @param {Object} sortedColumn Entity sorting column.
			 */
			shiftColumnsOrderPosition: function(columns, sortedColumn) {
				var sortedColumnOrderPosition = sortedColumn.orderPosition;
				if (Ext.isNumber(sortedColumnOrderPosition)) {
					columns.each(function(column) {
						if (column !== sortedColumn &amp;&amp; Ext.isNumber(column.orderPosition) &amp;&amp;
							column.orderPosition &gt;= sortedColumnOrderPosition) {
							column.orderPosition += 1;
						}
					});
				}
			},

 

Сталкивался с подобной проблемой. Пришлось заместить данные методы на странице редактирования (в моем случае) InvoiceSectionV2

			/**
			 * @inheritdoc Terrasoft.BaseViewModel#onLookupDataLoaded
			 * @override
			 */
			onLookupDataLoaded: function(config) {
				this.callParent(arguments);
				this.mixins.LookupQuickAddMixin.onLookupDataLoaded.call(this, config);
			},
			getLookupListConfig: function() {
				return this.mixins.LookupQuickAddMixin.getLookupListConfig.apply(this, arguments);
			},
 
			/**
			 * @inheritdoc Terrasoft.BaseViewModel#getLookupQuery
			 * @override
			 */
			getLookupQuery: function(filterValue, columnName) {
				var esq = this.callParent(arguments);
				this.applyColumnsOrderToLookupQuery(esq, columnName);
				var filterGroup = this.getLookupQueryFilters(columnName);
				esq.filters.addItem(filterGroup);
				return esq;
			},
			/**
			 * Applies order information to lookup entity schema query.
			 * @protected
			 * @param {Terrasoft.EntitySchemaQuery} esq Entity schema query.
			 * @param {String} columnName Lookup column name.
			 */
			applyColumnsOrderToLookupQuery: function(esq, columnName) {
				var lookupColumn = this.getColumnByName(columnName);
				var lookupListConfig = lookupColumn.lookupListConfig;
				if (!lookupListConfig || !lookupListConfig.orders) {
					return;
				}
				var columns = esq.columns;
				this.Terrasoft.each(lookupListConfig.orders, function(order) {
					var orderColumnPath = order.columnPath;
					if (!columns.contains(orderColumnPath)) {
						esq.addColumn(orderColumnPath);
					}
					var sortedColumn = columns.get(orderColumnPath);
					var direction = order.direction;
					sortedColumn.orderDirection = direction ? direction : Terrasoft.OrderDirection.ASC;
					var position = order.position;
					sortedColumn.orderPosition = position ? position : 1;
					this.shiftColumnsOrderPosition(columns, sortedColumn);
				}, this);
			},
			/**
			 * Shift columns order position.
			 * @private
			 * @param {Array} columns Entity columns.
			 * @param {Object} sortedColumn Entity sorting column.
			 */
			shiftColumnsOrderPosition: function(columns, sortedColumn) {
				var sortedColumnOrderPosition = sortedColumn.orderPosition;
				if (Ext.isNumber(sortedColumnOrderPosition)) {
					columns.each(function(column) {
						if (column !== sortedColumn &amp;&amp; Ext.isNumber(column.orderPosition) &amp;&amp;
							column.orderPosition &gt;= sortedColumnOrderPosition) {
							column.orderPosition += 1;
						}
					});
				}
			},

 

Спасибо, все получилось!

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

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

Нравится

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

Для вывода сообщения используется функция:

Terrasoft.MessageBox.Show({message:'текст',title:'заголовок'})

 

Зверев Александр,

Это понятно как выводить сообщения. Интересует вывод после завершения синхронизации данных.

Определить, загружались ли вообще по синхронизации данные, можно посредством:

!Ext.isEmpty(Terrasoft.CurrentUserInfo.lastSyncDate)

А первый или не первый раз, самому где-то хранить значение-флажок.

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