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

 

Надеюсь на скорый ответ.

Нравится

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

Добрый день.

 

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

Аналогичный вопрос рассматривался в статье

 

Переопределить логику LookupPageViewModelGenerator  нет возможности.

Однако в будущих релизах планируется перевод иерархических реестров на Angular, где этот подход поменяется.

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

Добрый день!

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

*Запрос отправляется.

*Ответ приходит.

*В объекте, по которому делается деталь, "Родитель иерархии" указан.

 

Код детали: 

define("NorbitContactProductDetail", ["ConfigurationGrid", "ConfigurationGridGenerator",
	 "ConfigurationGridUtilities"], function() {
	return {
		entitySchemaName: "NorbitContactProduct",
		messages: {},
		mixins: {},
		attributes: {},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			/**
			 * Скрыть кнопку "Добавить".
			 */
			/*{
				"operation": "remove",
				"name": "AddRecordButton"
			},*/
 
			/**
			 * Подключение иерархии детали.
			 */
			{
				"operation": "merge",
				"name": "DataGrid",
				"values": {
					"visible": true,
					"type": "listed",
					"hierarchical": true,
					"hierarchicalColumnName": "NorbitParentContactProduct",
					"useLevelRendering": true
				}
			},
		]/**SCHEMA_DIFF*/,
		methods: {
 
			addGridDataColumns: function (esq) {
			   this.callParent(arguments);
				if (!esq.columns.contains("Name")) {
					esq.addColumn("Name");
				}
				if (!esq.columns.contains("NorbitCount")) {
					esq.addColumn("NorbitCount");
				}
				if (!esq.columns.contains("NorbitParentContactProduct")) {
					esq.addColumn("NorbitParentContactProduct");
				}
			},
 
 
			/**
			 * Скрыть пункт меню "Копировать".
			 */
			getCopyRecordMenuItem: Terrasoft.emptyFn,
 
			/**
			 * Скрыть пункт меню "Изменить".
			 */
			getEditRecordMenuItem: Terrasoft.emptyFn,
 
			/**
			 * Скрыть пункт меню "Удалить".
			 */
			getDeleteRecordMenuItem: Terrasoft.emptyFn,
		}
	};
});

 

Нравится

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

Александр, смотрю в существующих схемах деталей, например, в ProjectStructureDetailV2:

"hierarchicalColumnName": "ParentId", 

Может, и у Вас надо было писать не NorbitParentContactProduct, а NorbitParentContactProductId?

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

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

На странице есть справочник "Сотрудник" при нажатии выходит окно Выбора - можно ли сделать этот выбор в виде дерева по "Подразделение"? То есть при нажатии на папку "Подразделение 1" выходили все сотрудники этого подразделения.

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

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

Нравится

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

Доброе утро.

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

Посмотрите обсуждение подобной темы в этом посте.

 

Доброе утро.

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

Посмотрите обсуждение подобной темы в этом посте.

 

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

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

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

Select accountSelect = GetAccountSelectQuery(accountId, additionalColumnNames);
var hierarhicalOptions = new HierarchicalSelectOptions {
PrimaryColumnName = "AccountId",
ParentColumnName = "ParentAccountId",
SelectType = HierarchicalSelectType.Parents,
MaxDepthParameter = select.Parameters.GetByName("MaxDepth"),
IncludeLevelColumn = true
};
QueryCondition startingCondition = hierarhicalOptions.StartingPrimaryColumnCondition;
startingCondition.LeftExpression = new QueryColumnExpression("AccountId");
startingCondition.IsEqual(select.Parameters.GetByName("RootAccountId"));
string sqlText = UserConnection.DBEngine.GetQuerySqlText(accountSelect, hierarhicalOptions);
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
using (IDataReader reader = dbExecutor.ExecuteReader(sqlText, accountSelect.Parameters)) {
while (reader.Read()) {
ancestors.Add(reader.GetColumnValue("AccountId"););
}

Нравится

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

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

Идея Ваша ясна, но реализовать вот прямо как код написан вряд ли удастся, только если писать какие-то костыли. Допустим, а) если количество предков или наследников или наследников будет строго меньше N, можно сделать N полей, но это плохо с той стороны, что большое количество полей будет просто излишним, б) сделать какое-то поле, в котором будут сконкатенированы, допустим, через запятую id`шники предков, и потом его парсить, но это нарушение реляционности, да и в принципе очень проблематично. Рекомендую все же пересмотреть иерархию и подобрать другое решение.

Советую посмотреть деталь взаимосвязей и сделать аналогично (только там программное ограничение на одного родителя, но это тоже можно обойти)

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

Добрый день, форумчане.

Задача: сделать деталь "Продукты в продаже" в виде иерархии. За основу решил взять деталь "Структура организации" из раздела "Контрагенты".

Создал свой объект SuOpportunityProductInterest. В качестве родителя указал объект "Продукт в продаже ( Opportunity )". В него
добавил справочное поле SuParent, где в качестве справочника указал SuOpportunityProductInterest.

Создал свою деталь на основе объекта SuOpportunityProductInterest.

На странице детали SuOpportunityProductDetailV2 написал следующий код:

define("SuOpportunityProductDetailV2", [/*"terrasoft"*/], function(/*Terrasoft*/) {
        return {
                entitySchemaName: "SuOpportunityProductInterest",
                details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
                        methods: {
                        /**
                                 * Открывает страницу добавления детали
                                 * @protected
                                 * @overridden
                                 * @param {String} editPageUId Значение колонки типа
                                 * @param {Boolean} keepParentId (optional) Не удалять из DefaultValues элемент с ключем Parent
                                 */

                                addRecord: function(editPageUId, keepParentId) {
                                        if (!keepParentId) {
                                                var defaultValues = this.get("DefaultValues");
                                                var result = this.Ext.Array.filter(defaultValues, function(item) {
                                                        return (item.name !== "SuParent");
                                                }, this);
                                                this.set("DefaultValues", result);
                                        }
                                        this.callParent(editPageUId);
                                },
                               
                                /**
                                 *Получает колонки, которые всегда выбираются запросом
                                 *@protected
                                 *@overridden
                                 *@return {Object} Возвращает колонки, которые всегда выбираются запросом
                                 */

                                getGridDataColumns: function() {
                                        var gridDataColumns = this.callParent(arguments);
                                        if (!gridDataColumns.SuParent) {
                                                gridDataColumns.SuParent = {
                                                        path: "SuParent"
                                                };
                                        }
                                        return gridDataColumns;
                                },
                       
                               
                                prepareResponseCollection: function(collection) {
                                        collection.each(function(item) {
                                                var parent = item.get("SuParent");
                                                var parentId = parent && parent.value;
                                                if (parentId) {
                                                        item.set("SuParentId", parentId);
                                                }
                                                Terrasoft.each(item.columns, function(column) {
                                                        this.addColumnLink(item, column);
                                                        this.applyColumnDefaults(column);
                                                }, this);
                                        }, this);
                                },

                               
                                getHideQuickFilterButton: function() {
                                        return false;
                                },
                               
                                getShowQuickFilterButton: function() {
                                        return false;
                                },
                               
                                updateDetail: function(config) {
                                        config.reloadAll = true;
                                        this.callParent([config]);

                                },

                               
                                getAddChildElementButtonEnabled: function() {
                                        return !this.Ext.isEmpty(this.getSelectedItems());
                                },
                               
                                addChildElementRecord: function() {
                                        var selectedItems = this.getSelectedItems();
                                        if (this.Ext.isEmpty(selectedItems)) {
                                                return;
                                        }
                                        var parentId = selectedItems[0];
                                        var defaultValues = this.get("DefaultValues");
                                        var result = this.Ext.Array.filter(defaultValues, function(item) {
                                                return (item.name !== "SuParent");
                                        }, this);
                                        result.push({
                                                        name: "SuParent",
                                                        value: parentId
                                                });
                                        this.set("DefaultValues", result);
                                        this.addRecord(null, true);
                                },
                               
                                clearSelection: function() {
                                        this.set("activeRow", null);
                                        this.set("selectedRows", null);
                                },

                               
                                onDeleteAccept: function() {
                                        var selectedRows = this.getSelectedItems();
                                        var batch = this.Ext.create("Terrasoft.BatchQuery");
                                        Terrasoft.each(selectedRows, function(recordId) {
                                                this.deleteItem(recordId, batch, this);
                                        }, this);
                                        if (batch.queries.length > 0) {
                                                batch.execute(this.onDeleted, this);
                                        }
                                },

                               
                                onDeleted: function(response) {
                                        if (response && response.success) {
                                                this.clearSelection();
                                        } else {
                                                this.showConfirmationDialog(
                                                        this.get("Resources.Strings.OnDeleteError"));
                                        }
                                },

                               
                                deleteItem: function(recordId, batch, scope) {
                                        var grid = scope.getGridData();
                                        var toDelete = new Terrasoft.Collection();
                                        grid.each(function(item) {
                                                var parent = item.get("SuParent");
                                                if (parent && parent.value === recordId) {
                                                        toDelete.add(item);
                                                }
                                        }, grid);

                                        Terrasoft.each(toDelete.getItems(), function(item) {
                                                this.deleteItem(item.get("Id"), batch, this);
                                        }, scope);
                                        if (grid.find(recordId)) {
                                                var selfDelete = grid.get(recordId);
                                                grid.remove(selfDelete);
                                                var query = this.Ext.create("Terrasoft.DeleteQuery", {
                                                        rootSchema: scope.entitySchema
                                                });
                                                var filter = Terrasoft.createColumnFilterWithParameter(
                                                        Terrasoft.ComparisonType.EQUAL, "Id", recordId);
                                                query.filters.addItem(filter);
                                                batch.add(query);
                                        }
                                }
                               
                },
                diff: /**SCHEMA_DIFF*/[
                                {
                                   "operation": "merge",
                                   "name": "DataGrid",
                                   "values": {
                                          "type": "listed",
               
                                                  //включает иерархичность реестра детали
                                      "hierarchical": true,
                                      "hierarchicalColumnName": "SuParent"
                                                }                          
                                },
                                {
                                        "operation": "merge",
                                        "name": "AddRecordButton",
                                        "values": {
                                                visible: false
                                        }
                                },
                                {
                                        "operation": "insert",
                                        "name": "AddRecord",
                                        "parentName": "Detail",
                                        "propertyName": "tools",
                                        "index": 1,
                                        "values": {
                                                itemType: Terrasoft.ViewItemType.BUTTON,
                                                menu: [],
                                                "imageConfig": {"bindTo": "Resources.Images.AddButtonImage"},
                                        //      "caption": {"bindTo": "Resources.Strings.AddButtonCaption"},
                                                "visible": {"bindTo": "getToolsVisible"}
                                        }
                                },
                                {
                                        "operation": "insert",
                                        "name": "AddParentRecordButton",
                                        "parentName": "AddRecord",
                                        "propertyName": "menu",
                                        "values": {
                                                "caption": {"bindTo": "Resources.Strings.AddRootElementButtonCaption"},
                                                "click": {"bindTo": "addRecord"}
                                        }
                                },
                                {
                                        "operation": "insert",
                                        "name": "AddChildElementButton",
                                        "parentName": "AddRecord",
                                        "propertyName": "menu",
                                        "values": {
                                                "caption": {"bindTo": "Resources.Strings.AddChildElementButtonCaption"},
                                                "click": {"bindTo": "addChildElementRecord"},
                                                "enabled": {"bindTo": "getAddChildElementButtonEnabled"}
                                        }
                                },
                                {
                                        "operation": "remove",
                                        "name": "FiltersContainer"
                                }
                ]/**SCHEMA_DIFF*/
       
        };
});

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

В чем может быть проблема? Заранее благодарен

Нравится

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

Проблема решилась

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

Здравствуйте. Мне нужно создать древовидный реестр (как структура в проектах). Пробовал сделать по примеру структуры в проектах, но не получилось. Объект я наследовал от базового иерархического справочника, далее я добавил поле типа справочник Parent, которое ссылается на этот же объект. В свойстве "Родитель в иерархии" объекта указал поле Parent. Создал новый справочник, в нем иерархия работает. Далее создал страницу реестра и сделал ее по примеру страницы детали Структуры. В итоге у меня данная деталь отображается, в ней есть данные (не пишет "Нет данных", а отображаются названия колонок), но эти данные не отображаются.
Опишите, пожалуйста, поэтапно процесс созданий детали такого типа. Может я что-то упускаю.

Нравится

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

Добрый день!

В данный момент формируем для Вас инструкцию. Предоставим в ближайшее время.

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

Минимально необходимый код для иерархической детали (основано на детали «Структура проекта» из XRM):

define("HierarchyDeatilV2", [],
       function () {
             return {
                    entitySchemaName: "Project",
                    attributes: {
                           /**
                           * Отвечает за загруженные уровни иерархии
                           */
                           "expandedElements": {
                                  dataValueType: Terrasoft.DataValueType.CUSTOM_OBJECT,
                                  type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                           },
                           /**
                           * Отвечает за список развернутых элементов,
                           * хранит массив уникальных идентификаторов записей
                           */
                           "expandHierarchyLevels": {
                                  dataValueType: Terrasoft.DataValueType.CUSTOM_OBJECT,
                                  type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                           },
 
                           /**
                           * Отвечает за хранение разворачиваемого элемента иерархии
                           */
                           "ExpandItemId": {
                                  dataValueType: Terrasoft.DataValueType.GUID,
                                  type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                           }
                    },
                    methods: {
                           /**
                           * @overridden
                           */
                           disableGridSorting: Ext.emptyFn,
 
                           /**
                           * @overridden
                           */
                           sortColumn: Ext.emptyFn,
 
                           /**
                           * Инициализирует параметры детали
                           * @protected
                           * @overridden
                           */
                           initData: function () {
                                  this.callParent(arguments);
                                  this.set("expandedElements", {});
                                  this.set("expandHierarchyLevels", []);
                           },
 
                           /**
                           * Очищает информацию о загруженных и развернутых уровнях
                           * @protected
                           * @virtual
                           */
                           clearExpandHierarchyLevels: function () {
                                  this.set("expandedElements", {});
                                  this.set("expandHierarchyLevels", []);
                           },
 
                           /**
                           * Убирает информацию о том, что элемент развернут из системных параметров
                           * @protected
                           * @virtual
                           * @param {String} itemId Уникальный идентификатор записи
                           */
                           removeExpandHierarchyLevel: function (itemId) {
                                  var expandHierarchyLevels = this.get("expandHierarchyLevels");
                                  this.set("expandHierarchyLevels", Terrasoft.without(expandHierarchyLevels, itemId));
                           },
 
                           /**
                           * Добавляет в экземпляр запроса колонки:
                           * Родительский проект, Позиция, вычисляемую колонку количества дочерних элементов
                           * @protected
                           * @overridden
                           * @param {Terrasoft.EntitySchemaQuery} esq Запрос, в который будут добавлены колонки по умолчанию
                           */
                           addGridDataColumns: function (esq) {
                                  this.callParent(arguments);
                                  this.putParentColumn(esq);
                                  this.putNestingColumn(esq);
                           },
 
                           /**
                           * Добавляет колонку родительского проекта, если идет иерархический запрос
                           * @protected
                           * @virtual
                           * @param {Terrasoft.EntitySchemaQuery} esq Запрос,
                           * в который будет добавлена колонка родительского проекта
                           */
                           putParentColumn: function (esq) {
                                  var parentItem = this.get("ExpandItemId");
                                  if (parentItem && !esq.columns.contains("ParentId")) {
                                        esq.addColumn("ParentProject.Id", "ParentId");
                                  }
                           },
 
                           /**
                           * Добавляет агрегирующую колонку количества дочерних элементов для записи
                           * @protected
                           * @virtual
                           * @param {Terrasoft.EntitySchemaQuery} esq Запрос,
                           * в который будет добавлена агрегирующая колонка
                           */
                           putNestingColumn: function (esq) {
                                  var aggregationColumn = this.Ext.create("Terrasoft.AggregationQueryColumn", {
                                        aggregationType: Terrasoft.AggregationType.COUNT,
                                        columnPath: "[Project:ParentProject].Id"
                                  });
                                  if (!esq.columns.contains("HasNesting")) {
                                        esq.addColumn(aggregationColumn, "HasNesting");
                                  }
                           },
 
                           /**
                           * Возвращает объект со списком загруженных уровней
                           * @protected
                           * @virtual
                           * @return {Object} Возвращает объект со списком загруженных уровней
                           */
                           getExpandedItems: function () {
                                  return this.get("expandedElements");
                           },
 
                           /**
                           * Вносит информацию о новом загруженном уровне
                           * @protected
                           * @virtual
                           * @param primaryColumnValue Уникальный идентификатор записи
                           */
                           setExpandedItem: function (primaryColumnValue) {
                                  (this.getExpandedItems()[primaryColumnValue]) = { "page": 0 };
                           },
 
                           /**
                           * Проверяет, были ли загружены дочерние элементы выбранной записи
                           * @protected
                           * @virtual
                           * @param primaryColumnValue Уникальный идентификатор записи
                           * @return {boolean}
                           */
                           isItemExpanded: function (primaryColumnValue) {
                                  return !!(this.getExpandedItems()[primaryColumnValue]);
                           },
 
                           /**
                           * Обрабатывает загрузку данных в коллекцию, добавляя загрузку новых уровней в иерархию списка
                           * @protected
                           * @overridden
                           * @param {Terrasoft.Collection} dataCollection коллекция новых элементов
                           * @param {Object} options Объект конфигурации загрузки данных
                           */
                           addItemsToGridData: function (dataCollection, options) {
                                  if (dataCollection.isEmpty()) {
                                        return;
                                  }
                                  var firstItem = dataCollection.getByIndex(0);
                                  var parentId = firstItem.get("ParentId");
                                  if (parentId) {
                                        options = {
                                               mode: "child",
                                               target: parentId
                                        };
                                        var gridData = this.getGridData();
                                        var parentObj = gridData.get(parentId);
                                        if (parentObj) {
                                               parentObj.set("HasNesting", 1);
                                        }
                                        if (!this.isItemExpanded(parentId)) {
                                               return;
                                        }
                                  } else {
                                        this.set("LastRecord", dataCollection.getByIndex(dataCollection.getCount() - 1));
                                  }
                                  this.callParent([dataCollection, options]);
                                  if (options && (options.mode === "child" || options.mode === "top")) {
                                        var gridDataChild = this.getGridData();
                                        var tempCollection = this.Ext.create("Terrasoft.Collection");
                                        tempCollection.loadAll(gridDataChild);
                                        gridDataChild.clear();
                                        gridDataChild.loadAll(tempCollection);
                                  }
                                  this.set("ExpandItemId", null);
                           },
 
                           /**
                           * Обработчик загрузки дочерних элементов. Осуществляет проверку загружености
                           * дочерних элементов выбранной записи. Запускает загрузку нового уровня.
                           * @protected
                           * @virtual
                           * @param {String} primaryColumnValue Уникальный идентификатор записи
                           * @param {Boolean} isExpanded Признак того, разворачивает или сворачивает пользователь дочерние элементы
                           * true - если разворачивает, false в обратном случае
                           */
                           onExpandHierarchyLevels: function (primaryColumnValue, isExpanded) {
                                  if (!isExpanded || this.isItemExpanded(primaryColumnValue)) {
                                        return;
                                  }
                                  this.setExpandedItem(primaryColumnValue);
                                  this.set("ExpandItemId", primaryColumnValue);
                                  this.loadGridData();
                           },
 
                           /**
                           * Удаляет логику постраничности если загружаются дочерние объекты
                           * @protected
                           * @overridden
                           */
                           initQueryOptions: function () {
                                  var parentItem = this.get("ExpandItemId");
                                  if (!parentItem) {
                                        var isClearGridData = this.get("IsClearGridData");
                                        if (isClearGridData) {
                                               this.clearExpandHierarchyLevels();
                                        }
                                        this.callParent(arguments);
                                  }
                           },
 
                           /**
                           * Удаляет логику постраничности если загружаются дочерние объекты
                           * @protected
                           * @overridden
                           */
                           initCanLoadMoreData: function () {
                                  var parentItem = this.get("ExpandItemId");
                                  if (!parentItem) {
                                        this.callParent(arguments);
                                  }
                           },
 
                           /**
                           * Обновляет фильтры в зависимости от того, загружается ли записи в корень или в новый уровень
                           * @protected
                           * @overridden
                           * @return {Terrasoft.FilterGroup} Примененные в данной схеме фильтры
                           */
                           getFilters: function () {
                                  var parentItem = this.get("ExpandItemId");
                                  if (parentItem) {
                                        var parentProjectFilterGroup = this.Terrasoft.createFilterGroup();
                                         parentProjectFilterGroup.addItem(this.Terrasoft.createColumnFilterWithParameter(
                                               this.Terrasoft.ComparisonType.EQUAL,
                                               "ParentProject",
                                               parentItem,
                                               Terrasoft.DataValueType.GUID
                                        ));
                                        return parentProjectFilterGroup;
                                  } else {
                                        var filters = this.callParent(arguments);
                                        if (this.get("DetailColumnName") !== "ParentProject") {
                                               var group = this.Terrasoft.createFilterGroup();
                                               group.addItem(filters);
                                               group.addItem(
 
                           Terrasoft.createColumnIsNullFilter(this.entitySchema.hierarchicalColumnName)
                                               );
                                               filters = group;
                                        }
                                        return filters;
                                  }
                           }
                    },
                    diff: /**SCHEMA_DIFF*/[
                           {
                                  "operation": "merge",
                                  "name": "DataGrid",
                                  "values": {
                                        "type": "listed",
                                        "hierarchical": true,
                                        "sortColumnDirection": { "bindTo": "disableGridSorting" },
                                        "hierarchicalColumnName": "ParentId",
                                        "updateExpandHierarchyLevels": {
                                               "bindTo": "onExpandHierarchyLevels"
                                        },
                                        "expandHierarchyLevels": {
                                               "bindTo": "expandHierarchyLevels"
                                        }
                                  }
                           }
                    ]/**SCHEMA_DIFF*/
             };
       }
);
Показать все комментарии