Деталь
фильтр
фильтрация на детали
Технические вопросы
7.x

Уважаемые форумчане.
Вопрос по версии 7.6
Не получается сделать фильтрацию на детали.
Создал деталь активностей связанных контрагентов Activity на странице контрагента. Она похожа на деталь
Ативности в контрагенте, только она должна выдавать перечень активностей не текущего контрагента,
а активности контрагентов, которые связаны с текущим контрагентом. Связи контрагентов хранятся во
вьюхе VwAccountRelationship. В ней есть колонки AccountId и RelatedAccountId.
Сделал запрос

 SELECT * FROM Activity
INNER JOIN VwAccountRelationship ON Activity.AccountId = VwAccountRelationship.RelatedAccountId
WHERE VwAccountRelationship.AccountId = 'a40cfdfb-cd46-4c63-9448-44110861c12c'

a40cfdfb-cd46-4c63-9448-44110861c12c - Id текущего контрагента.
Этот запрос выдает верный результат. Там всего одна запись.
Но сделать с помощью фильтра на js не получается.
Пробовал следующий код, но он выдает кучу ненужных записей.
"Activity": {
                "schemaName": "SuSchema1Detail",
                "entitySchemaName": "Activity",
                "filter": {
                        "detailColumn": "Account",
                        "masterColumn": "Id"           
                },
                filterMethod: "activityFilter"
        }
methods: {
                        activityFilter: function() {
                                var currentAccount = this.get("Id");
                                var filterGroup = Ext.create("Terrasoft.FilterGroup");
                                filterGroup.add("CurrentAccountRelatedAccounts", Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
                                        "=[VwAccountRelationship:RelatedAccount:Account].Account", currentAccount));
                                return filterGroup;
                        }                              
                }

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

Нравится

1 комментарий
Деталь
множественный выбор
реестр
справочник
Технические вопросы
7.x

Добрый день.

Создала деталь с выбором из справочника [ConfigItemModel] (создавала на основе примера: создание детали...)
Для детали был создан объект [UsrModelCIInSupplies].
Возникли ошибки при вызове окна справочника

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

2 ошибка. Вы выборе данных, они не вставляются в объект [UsrModelCIInSupplies].
изображение 2

Сам код детали

define("UsrSchema5Detail", ["ConfigurationEnums"],
        function(enums) {
        return {
                entitySchemaName: "UsrModelCIInSupplies",
                attributes: {},
                messages: {},
                methods: {
                        //колонки выбираемые запросом
                        getGridDataColumns: function() {
                                return {
                                        "Id": {path: "Id"},
                                        "UsrConfigItemModel": {path: "UsrConfigItemModel"},
                                        "UsrConfigItemModel.Name": {path: "UsrConfigItemModel.Name"}
                                };
                        },
                        //конфигурирует и отображает модальное окно справочника
                        openUsrConfigItemModelLookup: function() {
                                //конфигурирует объект
                                var config = {
                        //название схемы объекта, записи которого будут отображены в справочнике
                                        entitySchemaName: "ConfigItemModel",
                                        //множественный выбор
                                        multiSelect: true,
                                        //колонки, которые будут отображены в справочнике
                                        columns: ["Name"]
                                };
                                var UsrConsumablesId = this.get("MasterRecordId");
                                if (this.Ext.isEmpty(UsrConsumablesId)) {
                                        return;
                                }
                                //экземпляр класса [EntitySchemaQuery]
                                var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                                        //установка корневой схемы
                                        rootShemaName: this.entitySchemaName
                                });
                                //добовление колонки [Id]
                                esq.addColumn("Id");
                                //добавление колонки [id] из схемы [UsrConfigItemModel]
                                esq.addColumn("UsrConfigItemModel.Id", "UsrConfigItemModelId");
                                //Создание и добаление фильтров в коллекцию запроса
                                esq.filters.add("filterUsrConsumables",
                                this.Terrasoft.createColumnFilterWithParameter(
                                        this.Terrasoft.ComparisonType.EQUAL, "UsrConsumables", UsrConsumablesId));
                // Получение всей коллекции записей и отображение ее в модальном окне справочника.
                                esq.getEntityCollection(function(result) {
                                        var existsUsrConfigItemModelCollection = [];
                                        if (result.success) {
                                                result.collection.each(function(item) {
                                                        existsUsrConfigItemModelCollection.push(item.get("UsrConfigItemModelId"));
                                                });
                                        }
                                        // Добавление фильтра в конфигурационный объект.
                                        if (existsUsrConfigItemModelCollection.length > 0) {
                                                var existsFilter = this.Terrasoft.createColumnInFilterWithParameters("Id",
                                                        existsUsrConfigItemModelCollection);
                                                existsFilter.comparisonType = this.Terrasoft.ComparisonType.NOT_EQUAL;
                                                existsFilter.Name = "existsFilter";
                                                config.filters = existsFilter;
                                        }
                                        // Вызов модального окна справочника
                                        this.openLookup(config, this.addCallBack, this);
                                }, this);
                        },
                        //обработчик события сохранения страницы редактирвоания
                        onCardSaved: function() {
                                this.openUsrConfigItemModelLookup();
                        },
//открывает справочник МКЕ в случае если странца была редактирвоания РМ была ранее сохранена
                        addRecord: function() {
                                var masterCardState = this.sandbox.publish("GetCardState", null, [this.sandbox.id]);
                                var isNewRecord = (masterCardState.state === enums.CardStateV2.ADD ||
                                masterCardState.state === enums.CardStateV2.COPY);
                                if (isNewRecord === true) {
                                        var args = {
                                                isSilent: true,
                                                messageTags: [this.sandbox.id]
                                        };
                                        this.sandbox.publish("SaveRecord", args, [this.sandbox.id]);
                                        return;
                                }
                                this.openUsrConfigItemModelLookup();
                        },
                        //добавление выбранных продуктов
                        addCallBack: function(args) {
                                //экземпляр класса пакетного запроса BatchQuery
                                var bq = this.Ext.create("Terrasoft.BatchQuery");
                                var UsrConsumablesId = this.get("MasterRecordId");
                                //коллекция выбранных в справочнике данных
                                this.selectedRows = args.selectedRows.getItems();
                                //колекция, передаваемая в запрос
                                this.selectedItems = [];
                                // Копирование необходимых данных.
                                this.selectedRows.forEach(function(item) {
                                        item.UsrConsumablesId = UsrConsumablesId;
                                        item.UsrConfigItemModelId = item.values;
                                        bq.add(this.getUsrConfigItemModelInsertQuery(item));
                                        this.selectedItems.push(item.values);
                                }, this);
                                //выполнение пакетного запроса, если он не пустой
                                if (bq.queries.length) {
                                        this.showBodyMask.call(this);
                                        bq.execute(this.onUsrConfigItemModelInsert, this);
                                }
                        },
                        //возвращает запрос на добавление текущего объекта
                        getUsrConfigItemModelInsertQuery: function(item) {
                                var insert = Ext.create("Terrasoft.InsertQuery", {
                                        rootShemaName: this.entitySchemaName
                                });
                                insert.setParameterValue("UsrConsumables", item.UsrConsumablesId,
                                this.Terrasoft.DataValueType.GUID);
                                insert.setParameterValue("ConfigItemModel", item.UsrConfigItemModelId,
                                this.Terrasoft.DataValueType.GUID);
                                return insert;
                        },
                        //метод, вызываемый при добавлении записей в реестр детали
                        onUsrConfigItemModelInsert: function(response) {
                                this.hideBodyMask.call(this);
                                this.beforeLoadGridData();
                                var filterCollection = [];
                                response.queryResults.forEach(function(item) {
                                        filterCollection.push(item.id);
                                });
                                var esq = Ext.cteate("Terrasoft.EntitySchemaQuery", {
                                        rootShemaName: this.entitySchemaName
                                });
                                this.initQueryColumns(esq);
                                esq.filters.add("recordId",
                                Terrasoft.createColumnInFilterWithParameters("Id", filterCollection));
                                esq.getEntityCollection(function(response) {
                                        this.afterLoadGridData();
                                        if (response.success) {
                                                var responseCollection = response.collection;
                                                this.prepareResponseCollection(responseCollection);
                                                this.getGridData().loadAll(responseCollection);
                                        }
                                }, this);
                        },
                        //метод, вызываемый при удалении выбранных записей детали
                        deleteRecords: function() {
                                var selectedRows = this.getSelectedItems();
                                if (selectedRows.length > 0) {
                                        this.set("SelectedRows", selectedRows);
                                        this.callParent(arguments);
                                }
                        },
                        //скрыть пункт меню [Копировать]
                        getCopyRecordMenuItem: Terrasoft.emptyFn,
                        //скрыть пункт меню [Изменить]
                        getEditRecordMenuItem: Terrasoft.emptyFn,
                        //возвращает имя колонки по умолчанию для фильтра
                        getFilterDefaultColumnName: function() {
                                return "UsrConfigItemModel";
                        }
                },
                        // Массив модификаций.
                diff: /**SCHEMA_DIFF*/[
                                {
                                        // Тип операции — слияние.
                                        "operation": "merge",
                                        // Название элемента схемы, над которым производится действие.
                                        "name": "DataGrid",
                                // Объект, свойства которого будут объединены со свойствами элемента схемы.
                                        "values": {
                                                "rowDataItemMarkerColumnName": "UsrConfigItemModel"
                                        }
                                },
                                {
                                        // Тип операции — слияние.
                                        "operation": "merge",
                                        // Название элемента схемы, над которым производится действие.
                                        "name": "AddRecordButton",
                                // Объект, свойства которого будут объединены со свойствами элемента схемы.
                                        "values": {
                                                "visible": {"bindTo": "getToolsVisible"}
                                        }
                                }
                        ]/**SCHEMA_DIFF*/
                };
});

Задача стоит, сделать деталь такой же как, например: деталь [ConfItemUserDetail] в КЕ.

Версия продукта: service enterprise 7.8.2

Нравится

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

Где и как правильно поправить код?

Добрый вечер, Алеся.

Исходя из ошибки - у Вас неправильно строится запрос к базе данных в методе openUsrConfigItemModelLookup. На первом скриншоте явно видно, что запрос не был построен корректно. Проверьте правильность имен колонок, а также правильность связей. SDK.

Ошибка на втором скриншоте результат первой ошибки. Метод addCallBack получил не правильный параметр args и затем у несуществующего свойства selectedRows попытался вызвать метод forEach.

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

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

// Получение всей коллекции записей и отображение ее в модальном окне справочника.
				esq.getEntityCollection(function(result) {
					var existsUsrConfigItemModelsCollection = [];
					if (result.success) {
						result.collection.each(function(item) {
							existsUsrConfigItemModelsCollection.push(item.get("UsrConfigItemModelId"));
						});
					}

изображение 1

Показать все комментарии
Деталь
Деталь с полями редактирования
Технические вопросы
7.x

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

Нравится

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

Нам программисты из Softex реализовали довольно универсальную родительскую страницу детали. Правда, на 7.8 пока не перевелись (на 7.5 работает), но думаю, что они смогут и на 7.8 сделать

К чему ваш комментарий, Владимир?

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

Инструкции по созданию такой детали нет, но Вы можете взять за основу существующую деталь "Средства связи контакта" (ContactCommunicationDetailV2) и сделать по аналогии свою.

"Олег Кречетов" написал:К чему ваш комментарий, Владимир?

К тому, что я знаю, кто знает, как её сделать :) И с вами поделился

Показать все комментарии
Деталь
Деталь в виде иерархии
иерархия
Технические вопросы
Разработка

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

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

Создал свой объект 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 комментарий
Деталь
порядок деталей
расположение деталей
Технические вопросы
7.x

Здравствуйте!
Работаю в версии 7.7. Столкнулся со следующей проблемой:
мастером на странице редактирования Лида в истории добавил свою деталь. Она располагается в самом низу. Мне нужно её вверх поднять, расположить её между первой и второй базовыми деталями. Мастером не получается это сделать. Как сделать вручную. Где настройки расположения изменить?

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

Нравится

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

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

Как изменить порядок деталей используя Мастер разделов, Вы можете увидеть на прикрепленном скриншоте. Для изменения порядка напрямую в схеме, необходимо использовать операцию "move" и менять значение свойства "index".

Пример перемещения детали вниз:

define('ContactPageV2', ['ContactPageV2Resources', 'GeneralDetails'],
function(resources, GeneralDetails) {
	return {
		entitySchemaName: 'Contact',
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
	{
		"operation": "move",
		"name": "ContactCommunication",
		"parentName": "GeneralInfoTab",
		"propertyName": "items",
 
		"index": 4
	}
]/**SCHEMA_DIFF*/,
		attributes: {},
		methods: {},
		rules: {},
		userCode: {}
	};
});

Показать все комментарии
дерево
Деталь
копирование
раздел
Скрипты
Разработка

Доброго дня!
Столкнулся со след. задачей:
Имеется 2 раздела: "Заказы" и "Инженерная спецификация"
Оба раздела имеют свою древовидную деталь "Продукты"
Мне необходимо скопировать выделенные продукты из раздела "Инженерная спецификация" в раздел "Заказы". Копироваться должны только определенные поля.
Подскажите пожалуйста, как это можно реализовать?

Нравится

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

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

У каждого грида есть свойство SelectedIDs - возвращаемое массив идентификаторов выделенных записей. Зная идентификатор записи, можете выполнить обновление продуктов в древовидном реестре другого реестре. Обновление можно реализовать несколькими способами:

  1. 1. Используя датасет
  2. 2. Используя запрос на обновление
  3. 3. Используя хранимую процедуру

Рекомендую использовать первый способ, выполнить обновление через датасет.
Как за пример, можете взять логику обновления данных детали [Средства связи] раздела [Контрагент] реализованной в функции ActualizeCommunication сервиса scr_Account.

Cпасибо, сейчас попробую!

Можно еще посмотреть реализацию копирования дерева продуктов в scr_DocumentUtils...
Функция CopyOfferingInItemDetail. И далее из нее вызовы...

Показать все комментарии
Деталь
Технические вопросы
7.x

Создали делать2 в детали1.
Деталь2 самописная.

в Карточки схемы детали1

details: /**SCHEMA_DETAILS*/{
                        "UsrContragentOperation": {
                                "schemaName": "UsrContragentOperationDetailV2",
                                "entitySchemaName": "UsrContragentOperation",
                                filter: {
                                                masterColumn: "Id",
                                                detailColumn: "UsrTranspPlanLine"   //деталь2
                                                }
                        }

Но при добавлении записи в деталь2 Id пуст.
Т.е. получается что мы передаем id.
Что не так?
Как отловить в отладчике это значение?

Нравится

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

Здравствуйте,
При объявлении второй детали в детали, пишите "useRelationship": true

"UsrDetail2": {
				"schemaName": "UsrSchema2Detail",
				"entitySchemaName": "UsrDetail2",
				"filter": {
					"detailColumn": "UsrDetail1",
					"masterColumn": "Id"
				},
				"useRelationship": true
			}

В колонку связи второй детали, ту которая указана в «detailColumn», установится значение из карточки родителя (первой детали), из колонки что указана в «masterColumn», именно поэтому типы этих колонок должны совпадать.
И да, не забудьте во второй детали настроить колонки, по умолчанию в детали в детали, не будет выведена ни одна колонка.

Пример всей реализации, деталь в контрагентах. А в ней вторая деталь:

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

define("UsrUsrDetail11Page", [], function() {
	return {
		entitySchemaName: "UsrDetail1",
		details: /**SCHEMA_DETAILS*/{
			"UsrDetail2": {
				"schemaName": "UsrSchema2Detail",
				"entitySchemaName": "UsrDetail2",
				"filter": {
					"detailColumn": "UsrDetail1",
					"masterColumn": "Id"
				},
				"useRelationship": true
			}
		}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "UsrString",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 0,
						"layoutName": "Header"
					},
					"bindTo": "UsrString"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "UsrAccount",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 0,
						"layoutName": "Header"
					},
					"bindTo": "UsrAccount"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 1
			},
			{
				"operation": "insert",
				"name": "Detail1GeneralTabContainer",
				"parentName": "Tabs",
				"propertyName": "tabs",
				"values": {
					"caption": "Tab",
					"items": []
				}
			},
			{
				"operation": "insert",
				"name": "UsrDetail2",
				"values": {
					"itemType": Terrasoft.ViewItemType.DETAIL
				},
				"parentName": "Detail1GeneralTabContainer",
				"propertyName": "items"
			}
		]/**SCHEMA_DIFF*/,
		methods: {},
		rules: {}
	};
});

Результат:

Показать все комментарии
Деталь
Технические вопросы
7.x

Добрый день, коллеги!
Подскажите, в продукте версии 7.8 есть деталь "Структура" , в разделе "Проекты".
Хочу сделать со своей кастомной деталью тоже самое, иерархию.

Пока что добавил вот такой код, к старнице детали:

define("UsrReportingDetailV2", ["ConfigurationEnums", "css!ProjectCSSModule"], function(enums) {
        return {
                entitySchemaName: "UsrReporting",
                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,

                        /**
                         * Обнавляет страницы редактирования проекта
                         * @overridden
                         * @private
                         */

                        initEditPages: function() {
                                this.callParent(arguments);
                                debugger;
                                var editPages = this.get("EditPages");
                                var workPage = editPages.collection.items[0];
                                workPage.set("Click", {"bindTo": "addToRootRecord"});
                                workPage.set("Caption", "Super");
                                workPage.set("Visible", true);
                                var childItemId = Terrasoft.utils.generateGUID();
                                var config = {
                                        "Id": childItemId,
                                        "Caption": "Sub",
                                        "Click": {"bindTo": "addToChildRecord"},
                                        "Enabled": {"bindTo": "isSingleSelected"},
                                        "Tag": childItemId,
                                        "SchemaName": "UsrReportingPageV2"
                                };
                                var addToChildMenuItem = this.getActionsMenuItem(config);
                                editPages.add(childItemId, addToChildMenuItem);
                        },
                        /**
                         * Открывает страницу Работы для добавления элемента дочернего элемента выбранной записи
                         * @protected
                         * @virtual
                         */

                        addToChildRecord: function() {
                                var scope = this;
                                var selectedItems = this.getSelectedItems();
                                this.set("ExpandItemId", selectedItems[0]);
                                this.replaceDefaultValue("UsrParent", selectedItems[0]);
                                var masterRecordId = this.get("MasterRecordId");
                                this.addRecord();
                        },
                        /**
                         * Устанавливает значение по умолчанию для параметра страницы редактировани новой записи
                         * @protected
                         * @virtual
                         * @param {String} key Имя параметра
                         * @param {*} value значение параметра
                         */

                        replaceDefaultValue: function(key, value) {
                                var defaultValues = this.get("DefaultValues");
                                var oldValue = defaultValues.filter(function(item) {
                                        return item.name === key;
                                });
                                if (Ext.isEmpty(oldValue)) {
                                        defaultValues.push({
                                                name: key,
                                                value: value
                                        });
                                } else {
                                        Terrasoft.each(oldValue, function(item) {
                                                item.value = value;
                                        });
                                }
                        },
                        /**
                         * Открывает страницу Проекта или Работы для добавления элемента в текущий уровань иерархии
                         * @protected
                         * @virtual
                         * @param {String} typeUId Уникальный идентификатор типа записи проекта
                         */

                        addToRootRecord: function(typeUId) {
                                var masterRecordId = this.Terrasoft.GUID_EMPTY;
                                this.replaceDefaultValue("UsrParent", masterRecordId);
                                this.addRecord();
                        },
                        /**
                         * Обработчик загрузки дочерних элементов. Осуществляет проверку загружености
                         * дочерних элеметов выбранной записи. Запускает загрузку нового уровня.
                         * @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);
                                }

                                this.get("expandedElements")["EB64FD9A-DF42-4275-8F1B-0A32ABB68AD5"] = {
                                        page: 0
                                };
                        },
                        /**
                         * Инициализирует параметры детали
                         * @protected
                         * @overridden
                         */

                        initData: function() {
                                this.callParent(arguments);
                                this.set("expandedElements", {});
                                this.set("expandHierarchyLevels", []);
                        },
                },
                diff: /**SCHEMA_DIFF*/[
                        {
                                "operation": "merge",
                                "name": "DataGrid",
                                "values": {
                                        "type": "listed",
                                        "hierarchical": true,
                                        "sortColumnDirection": {"bindTo": "disableGridSorting"},
                                        "hierarchicalColumnName": "ParentId",
                                        "updateExpandHierarchyLevels": {
                                                "bindTo": "onExpandHierarchyLevels"
                                        },
                                        expandHierarchyLevels: {
                                                "bindTo": "expandHierarchyLevels"
                                        },
                                        "listedConfig": {
                                                "name": "DataGridListedConfig",
                                                "items": [
                                                        {
                                                                "name": "UsrFileNameListedGridColumn",
                                                                "bindTo": "UsrFileName",
                                                                "position": {
                                                                        "column": 1,
                                                                        "colSpan": 12
                                                                }
                                                        },
                                                        {
                                                                "name": "UsrDisplayPortalListedGridColumn",
                                                                "bindTo": "UsrDisplayPortal",
                                                                "position": {
                                                                        "column": 21,
                                                                        "colSpan": 4
                                                                }
                                                        }
                                                ]
                                        },
                                        "tiledConfig": {
                                                "name": "DataGridTiledConfig",
                                                "grid": {
                                                        "columns": 24,
                                                        "rows": 3
                                                },
                                                "items": [
                                                        {
                                                                "name": "UsrFileNameTiledGridColumn",
                                                                "bindTo": "UsrFileName",
                                                                "position": {
                                                                        "row": 1,
                                                                        "column": 1,
                                                                        "colSpan": 12
                                                                }
                                                        },
                                                        {
                                                                "name": "UsrDisplayPortalTiledGridColumn",
                                                                "bindTo": "UsrDisplayPortal",
                                                                "position": {
                                                                        "row": 1,
                                                                        "column": 21,
                                                                        "colSpan": 4
                                                                }
                                                        }
                                                ]
                                        }
                                }
                        },
                        {
                                "operation": "insert",
                                "name": "UpButton",
                                "parentName": "Detail",
                                "propertyName": "tools",
                                "index": 0,
                                "values": {
                                        "itemType": Terrasoft.ViewItemType.BUTTON,
                                        "tag": -1,
                                        "imageConfig": {
                                                "bindTo": "Resources.Images.UpImage"
                                        },
                                        "click": {"bindTo": "changePosition"},
                                        "visible": {"bindTo": "getToolsVisible"},
                                        "enabled": {"bindTo": "canChangeSelectedItemPosition"},
                                        "hint": {"bindTo": "Resources.Strings.ChangePositionUpButtonCaption"}
                                }
                        },
                        {
                                "operation": "insert",
                                "name": "DownButton",
                                "parentName": "Detail",
                                "propertyName": "tools",
                                "index": 1,
                                "values": {
                                        "itemType": Terrasoft.ViewItemType.BUTTON,
                                        "tag": 1,
                                        "imageConfig": {
                                                "bindTo": "Resources.Images.DownImage"
                                        },
                                        "click": {"bindTo": "changePosition"},
                                        "visible": {"bindTo": "getToolsVisible"},
                                        "enabled": {"bindTo": "canChangeSelectedItemPosition"},
                                        "hint": {"bindTo": "Resources.Strings.ChangePositionDownButtonCaption"}
                                }
                        },
                        {
                                "operation": "remove",
                                "name": "ViewSortMenu",
                                "parentName": "ViewButton",
                                "propertyName": "menu"
                        }
                ]/**SCHEMA_DIFF*/
        };
});

Результат, кнопка добавить записи ("+") появилась новая, но с двумья кнопками, я старую убрал пока что. Отступ появился перед записей , там есть какое-то простарнство видимо для открывающегося списка, но плюсик там не появился. Я хочу сделать обычную деталь, и обычные дочерние записи, без всех проверок и сложной логики. На сколько я понимаю, она вообще не сложная, если сделать простую, главное корректно сохранять связь между родителями. Вопрос, где хранятся признаки что у записи есть дочерние, или нет, видимо я их где то не сечу, где не могу понять ...

Нравится

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

Может кто то делал подобное

Или как и когда , правильно добавлять в эти объекты ('expandHierarchyLevels', 'expandedElements') Id дочерних записей ?

Роман, все вычисляется напрямую запросом к колонкам UsrPosition и UsrParent.

Пример кода рабочей пользовательской детали:

define("UsrSchema2Detail", ["XRMConstants", "terrasoft", "css!ProjectCSSModule"], function(XRMConstants, Terrasoft) {
	return {
		entitySchemaName: "UsrTestTest",
		messages: {
			"CardModuleEntityInfo": {
				"mode": Terrasoft.MessageMode.PTP,
				"direction": Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
		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
			}
		},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
				{
					"operation": "merge",
					"name": "DataGrid",
					"values": {
						"type": "listed",
						"hierarchical": true,
						"sortColumnDirection": {"bindTo": "disableGridSorting"},
						"hierarchicalColumnName": "ParentId",
						"updateExpandHierarchyLevels": {
							"bindTo": "onExpandHierarchyLevels"
						},
						expandHierarchyLevels: {
							"bindTo": "expandHierarchyLevels"
						}
					}
				},
				{
					"operation": "insert",
					"name": "UpButton",
					"parentName": "Detail",
					"propertyName": "tools",
					"index": 0,
					"values": {
						"itemType": Terrasoft.ViewItemType.BUTTON,
						"tag": -1,
						"imageConfig": {
							"bindTo": "Resources.Images.UpImage"
						},
						"click": {"bindTo": "changePosition"},
						"visible": {"bindTo": "getToolsVisible"},
						"enabled": {"bindTo": "canChangeSelectedItemPosition"},
						"hint": {"bindTo": "Resources.Strings.ChangePositionUpButtonCaption"}
					}
				},
				{
					"operation": "insert",
					"name": "DownButton",
					"parentName": "Detail",
					"propertyName": "tools",
					"index": 1,
					"values": {
						"itemType": Terrasoft.ViewItemType.BUTTON,
						"tag": 1,
						"imageConfig": {
							"bindTo": "Resources.Images.DownImage"
						},
						"click": {"bindTo": "changePosition"},
						"visible": {"bindTo": "getToolsVisible"},
						"enabled": {"bindTo": "canChangeSelectedItemPosition"},
						"hint": {"bindTo": "Resources.Strings.ChangePositionDownButtonCaption"}
					}
				},
				{
					"operation": "remove",
					"name": "ViewSortMenu",
					"parentName": "ViewButton",
					"propertyName": "menu"
				}
		]/**SCHEMA_DIFF*/,
		methods: {
				disableGridSorting: Ext.emptyFn,
				sortColumn: Ext.emptyFn,
				init: function() {
					this.callParent(arguments);
				},
				initData: function() {
					this.callParent(arguments);
					this.set("expandedElements", {});
					this.set("expandHierarchyLevels", []);
				},
				onDeleted: function(result) {
					this.callParent(arguments);
					if (result.Success) {
						this.reloadGridData();
					}
				},
				clearExpandHierarchyLevels: function() {
					this.set("expandedElements", {});
					this.set("expandHierarchyLevels", []);
					var grid = Ext.getCmp("ProjectDetailV2DataGridGrid");
					if (grid) {
						grid.expandHierarchyLevels = [];
					}
				},
				removeExpandHierarchyLevel: function(itemId) {
					var expandHierarchyLevels = this.get("expandHierarchyLevels");
					this.set("expandHierarchyLevels", Terrasoft.without(expandHierarchyLevels, itemId));
					var grid = Ext.getCmp("ProjectDetailV2DataGridGrid");
					if (grid) {
						grid.expandHierarchyLevels = Terrasoft.without(grid.expandHierarchyLevels, itemId);
					}
				},
				addGridDataColumns: function(esq) {
					this.callParent(arguments);
					this.putParentColumn(esq);
					this.putNestingColumn(esq);
					this.putPositionColumn(esq);
				},
				putParentColumn: function(esq) {
					var parentItem = this.get("ExpandItemId");
					if (parentItem && !esq.columns.contains("ParentId")) {
						esq.addColumn("UsrParent.Id", "ParentId");
					}
				},
				putPositionColumn: function(esq) {
					if (!esq.columns.contains("UsrPosition")) {
						esq.addColumn("UsrPosition");
					}
				},
				putNestingColumn: function(esq) {
					var aggregationColumn = this.Ext.create("Terrasoft.AggregationQueryColumn", {
						aggregationType: Terrasoft.AggregationType.COUNT,
						columnPath: "[UsrTestTest:UsrParent].Id"
					});
					if (!esq.columns.contains("HasNesting")) {
						esq.addColumn(aggregationColumn, "HasNesting");
					}
				},
				getParents: function(primaryValues) {
					var parentPrimaryValues = [];
					var gridData = this.getGridData();
					if (Ext.isEmpty(primaryValues)) {
						return parentPrimaryValues;
					}
					primaryValues.forEach(function(primaryColumnValue) {
						var project = gridData.get(primaryColumnValue);
						var parentPrimaryColumnValue = project.get("ParentId");
						if (parentPrimaryColumnValue) {
							parentPrimaryValues.push(parentPrimaryColumnValue);
						}
					});
					return parentPrimaryValues;
				},
				removeGridRecords: function(primaryColumnValues) {
					var updateNestingCollection = this.getParents(primaryColumnValues);
					this.callParent(arguments);
					var gridData = this.getGridData();
					Terrasoft.each(updateNestingCollection, function(projectId) {
						var count = gridData.filterByFn(function(item) {
							return item.get("ParentId") === projectId;
						}, this).getCount();
						if (gridData.contains(projectId)) {
							this.removeExpandHierarchyLevel(projectId);
							var parent = gridData.get(projectId);
							parent.set("HasNesting", count);
						}
					}, this);
				},
				getExpandedItems: function() {
					return this.get("expandedElements");
				},
				setExpandedItem: function(primaryColumnValue) {
					(this.getExpandedItems()[primaryColumnValue]) = {"page": 0};
				},
				isItemExpanded: function(primaryColumnValue) {
					return Boolean(this.getExpandedItems()[primaryColumnValue]);
				},
				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);
						this.sortCollection(tempCollection);
						gridDataChild.clear();
						gridDataChild.loadAll(tempCollection);
					}
					this.set("ExpandItemId", null);
				},
				onExpandHierarchyLevels: function(primaryColumnValue, isExpanded) {
					if (!isExpanded || this.isItemExpanded(primaryColumnValue)) {
						return;
					}
					this.setExpandedItem(primaryColumnValue);
					this.set("ExpandItemId", primaryColumnValue);
					this.loadGridData();
				},
				initQueryOptions: function() {
					var parentItem = this.get("ExpandItemId");
					if (!parentItem) {
						var isClearGridData = this.get("IsClearGridData");
						if (isClearGridData) {
							this.clearExpandHierarchyLevels();
						}
						this.callParent(arguments);
					}
				},
				initCanLoadMoreData: function() {
					var parentItem = this.get("ExpandItemId");
					if (!parentItem) {
						this.callParent(arguments);
					}
				},
				changeSorting: function() {
					this.clearExpandHierarchyLevels();
					this.callParent(arguments);
				},
				initQuerySorting: function(esq) {
					var sortedColumn = esq.columns.get("UsrPosition");
					sortedColumn.orderPosition = 0;
					sortedColumn.orderDirection = Terrasoft.OrderDirection.ASC;
				},
				getFilters: function() {
					var parentItem = this.get("ExpandItemId");
					if (parentItem) {
						var parentProjectFilterGroup = this.Terrasoft.createFilterGroup();
						parentProjectFilterGroup.addItem(this.Terrasoft.createColumnFilterWithParameter(
							this.Terrasoft.ComparisonType.EQUAL,
							"UsrParent",
							parentItem,
							Terrasoft.DataValueType.GUID
						));
						return parentProjectFilterGroup;
					} else {
						var filters = this.callParent(arguments);
						if (this.get("DetailColumnName") !== "UsrParent") {
							var group = this.Terrasoft.createFilterGroup();
							group.addItem(filters);
							group.addItem(
								Terrasoft.createColumnIsNullFilter(this.entitySchema.hierarchicalColumnName)
							);
							filters = group;
						}
						return filters;
					}
				},
				isProjectsInRoot: function() {
					return (this.get("DetailColumnName") !== "UsrParent");
				},
				isWorkInRoot: function() {
					return !this.isProjectsInRoot();
				},
				initEditPages: function() {
					this.callParent(arguments);
					var editPages = this.get("EditPages");
					var workPage = editPages.collection.items[0];
					workPage.set("Click", {"bindTo": "addToRootRecord"});
					workPage.set("Caption", "Add");
					workPage.set("Visible", true);
					var childItemId = editPages.collection.items[0].imstanceId;
					var config = {
						"Id": childItemId,
						"Caption": "New",
						"Click": {"bindTo": "addToChildRecord"},
						"Enabled": {"bindTo": "isSingleSelected"},
						"Tag": childItemId,
						"SchemaName": "UsrTestTest1Page"
					};
					var addToChildMenuItem = this.getActionsMenuItem(config);
					editPages.add(childItemId, addToChildMenuItem);
				},
				replaceDefaultValue: function(key, value) {
					var defaultValues = this.get("DefaultValues");
					var oldValue = defaultValues.filter(function(item) {
						return item.name === key;
					});
					if (Ext.isEmpty(oldValue)) {
						defaultValues.push({
							name: key,
							value: value
						});
					} else {
						Terrasoft.each(oldValue, function(item) {
							item.value = value;
						});
					}
				},
				getDetailInfo: function() {
					var detailInfo = this.sandbox.publish("GetDetailInfo", null, [this.sandbox.id]) || {};
					var defaultValues = this.get("DefaultValues");
					detailInfo.defaultValues = defaultValues;
					return detailInfo;
				},
				addToRootRecord: function(typeUId) {
					var masterRecordId = (typeUId === XRMConstants.Project.EntryType.Project)
						? this.Terrasoft.GUID_EMPTY
						: this.get("MasterRecordId");
					this.replaceDefaultValue("UsrParent", masterRecordId);
					this.addRecord(typeUId);
				},
				addToChildRecord: function() {
					var scope = this;
					var selectedItems = this.getSelectedItems();
					this.set("ExpandItemId", selectedItems[0]);
					this.replaceDefaultValue("UsrParent", selectedItems[0]);
					var masterRecordId = this.get("MasterRecordId");
					if (masterRecordId !== null) {
						var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "UsrTestTest"});
						var filter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
							"Id", masterRecordId, Terrasoft.DataValueType.GUID);
						esq.filters.add("filter", filter);
						esq.getEntityCollection(function(response) {
							if (!response || !response.success) {
								return;
							}
							var result = response.collection;
							result.each(function(resultItem) {
								scope.addRecord('c485c4e3-c0a1-4008-a8fe-054f167d5068');
							});
						}, this);
					} else {
						this.addRecord('c485c4e3-c0a1-4008-a8fe-054f167d5068');
					}
				},
				canChangeSelectedItemPosition: function() {
					var selectedItems = this.getSelectedItems();
					return (!Ext.isEmpty(selectedItems) && (selectedItems.length <= 1));
				},
				changePosition: function() {
					var shift = arguments[3];
					var activeRow = this.getActiveRow();
					var projectId = activeRow.get("Id");
					this.updateProjectPosition(projectId, shift, this.onPositionChanged, this);
				},
				onPositionChanged: function(result) {
					if (!result) {
						return;
					}
					var activeRow = this.getActiveRow();
					var parentId = activeRow.get("ParentId");
					if (!parentId) {
						parentId = this.get("MasterRecordId");
					}
					var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchema: this.entitySchema});
					esq.addColumn("UsrPosition");
					var filter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
						"UsrParent", parentId, Terrasoft.DataValueType.GUID);
					esq.filters.add("filter", filter);
					esq.getEntityCollection(function(response) {
						if (!response || !response.success) {
							return;
						}
						var gridData = this.getGridData();
						var result = response.collection;
						result.each(function(resultItem) {
							var resultItemId = resultItem.get("Id");
							var newPosition = resultItem.get("UsrPosition");
							var gridRecord = gridData.get(resultItemId);
							gridRecord.set("UsrPosition", newPosition);
						});
						var tempCollection = this.Ext.create("Terrasoft.Collection");
						tempCollection.loadAll(gridData);
						this.sortCollection(tempCollection);
						gridData.clear();
						gridData.loadAll(tempCollection);
					}, this);
				},
				sortCollection: function(collection) {
					collection.sortByFn(function(a, b) {
						var positionA = a.get("UsrPosition");
						var positionB = b.get("UsrPosition");
						var q = positionA - positionB;
						return q === 0 ? 0 : (q) / Math.abs(q);
					});
				},
		}
	};
});

Доброго времени суток.
Недавно столкнулся с такой же задачкой. Вот примерный алгоритм:
1) Отрубить в системных настройках ненавистный префикс "Usr" (необяз. пункт).
2) Создать Объект (род. объект - Базовый объект), заполнить его нужными полями, сохранить, опубликовать.
3) Еще раз открыть объект на редактирование и создать там справочник Parent, род. объект - ставим ссылку на только что созданный объект. В свойствах объекта (справа кнопка списка-свойства-все) в графе "Родитель в иерархии" ставим поле Parent. Сохраняем, Публикуем.
4) Когда заполнять таблицу - решаете сами. Либо в схеме (через InsertQuery), либо через хранимку, либо через С# код. Без разницы (в крайнем случае - this.reloadGridData()). Главное у нужных записей заполнять поле Parent айдишником записи-родителя (тем самым формируя иерархию)
5) Теперь сама схема. Создаем схему. Род. объект - Базовая схема детали с реестром. Код приложу. Там надо поменять название схемы в define, ссылку на entitySchemaName (объект, который мы создали ранее) и ссылку на колонку объекта в putNestingColumn.
6) Все. Теперь добавляем деталь на страницу (из кода. в дизайнере не отобразится, т.к. не зарегистрирована). Если все сделано правильно и карточка загрузилась без ошибок, последний шаг - настроить вывод информации в гриде. Это можно сделать через ToolButton прямо в карточке.

[quote="Мотков Илья"]

Роман, все вычисляется напрямую запросом к колонкам UsrPosition и UsrParent.

Спасибо вам большое, вы мне очень помогли. Но теперь такая проблема, во первых не сохраняется ID записи, родителя, если это нормально, то я переделаю просто save на карточке и все. Во-вторых не открывается одновременно две записи с дочерними записями, пишет в консоли

 message: Uncaught Terrasoft.ItemNotFoundException: Item with key f5695207-a45d-4975-a484-92384cb438d1 Does not exist 

Виртуальный обьект и коллекцию, проверил, все корректно добавляет и удаляет. Уже несколько раз сравниваю с разделом "Проекты" , не могу найти разницу ...
Код схемы:

define("UsrReportingDetailV2", ["XRMConstants","ConfigurationGrid", "ConfigurationGridGenerator", "ProcessModuleUtilities", "ConfigurationGridUtilities", "ConfigurationEnums"], 
	function(XRMConstants, ProcessModuleUtilities, ConfigurationGridUtilities, enums) {
	return {
		entitySchemaName: "UsrReporting",
		messages: {
			"CardModuleEntityInfo": {
				"mode": Terrasoft.MessageMode.PTP,
				"direction": Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
		attributes: {
			"isPortal": {
				"dataValueType": Terrasoft.DataValueType.BOOLEAN,
				"value":  false
			},
			"isCRM": {
				"dataValueType": Terrasoft.DataValueType.BOOLEAN,
				"value":  true
			},
			/**
			 * Отвечает за загруженные уровни иерархии
			 */
			"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
			}
		},
		mixins: {
			ConfigurationGridUtilites: "Terrasoft.ConfigurationGridUtilities"
		},
		methods: {
			disableGridSorting: Ext.emptyFn,
			sortColumn: Ext.emptyFn,
			init: function() {
				this.callParent(arguments);
			},
			initData: function() {
				this.callParent(arguments);
				this.set("expandedElements", {});
				this.set("expandHierarchyLevels", []);
			},
			onDeleted: function(result) {
				this.callParent(arguments);
				if (result.Success) {
					this.reloadGridData();
				}
			},
			clearExpandHierarchyLevels: function() {
				this.set("expandedElements", {});
				this.set("expandHierarchyLevels", []);
				var grid = Ext.getCmp("ProjectDetailV2DataGridGrid");
				if (grid) {
					grid.expandHierarchyLevels = [];
				}
			},
			removeExpandHierarchyLevel: function(itemId) {
				var expandHierarchyLevels = this.get("expandHierarchyLevels");
				this.set("expandHierarchyLevels", Terrasoft.without(expandHierarchyLevels, itemId));
				var grid = Ext.getCmp("ProjectDetailV2DataGridGrid");
				if (grid) {
					grid.expandHierarchyLevels = Terrasoft.without(grid.expandHierarchyLevels, itemId);
				}
			},
			addGridDataColumns: function(esq) {
				this.callParent(arguments);
				this.putParentColumn(esq);
				this.putNestingColumn(esq);
				this.putPositionColumn(esq);
			},
			putParentColumn: function(esq) {
				var parentItem = this.get("ExpandItemId");
				if (parentItem && !esq.columns.contains("ParentId")) {
				esq.addColumn("UsrParent.Id", "ParentId");
				}
			},
			putPositionColumn: function(esq) {
				if (!esq.columns.contains("UsrPosition")) {
					esq.addColumn("UsrPosition");
				}
			},
			putNestingColumn: function(esq) {
				var aggregationColumn = this.Ext.create("Terrasoft.AggregationQueryColumn", {
				aggregationType: Terrasoft.AggregationType.COUNT,
					columnPath: "[UsrReporting:UsrParent].Id"
				});
				if (!esq.columns.contains("HasNesting")) {
					esq.addColumn(aggregationColumn, "HasNesting");
				}
			},
			getParents: function(primaryValues) {
				var parentPrimaryValues = [];
				var gridData = this.getGridData();
				if (Ext.isEmpty(primaryValues)) {
					return parentPrimaryValues;
				}
				primaryValues.forEach(function(primaryColumnValue) {
					var project = gridData.get(primaryColumnValue);
					var parentPrimaryColumnValue = project.get("ParentId");
					if (parentPrimaryColumnValue) {
						parentPrimaryValues.push(parentPrimaryColumnValue);
					}
				});
				return parentPrimaryValues;
			},
			removeGridRecords: function(primaryColumnValues) {
				var updateNestingCollection = this.getParents(primaryColumnValues);
				this.callParent(arguments);
				var gridData = this.getGridData();
				Terrasoft.each(updateNestingCollection, function(projectId) {
				var count = gridData.filterByFn(function(item) {
				return item.get("ParentId") === projectId;
				}, this).getCount();
				if (gridData.contains(projectId)) {
				this.removeExpandHierarchyLevel(projectId);
				var parent = gridData.get(projectId);
				parent.set("HasNesting", count);
				}
				}, this);
			},
			getExpandedItems: function() {
				return this.get("expandedElements");
			},
			setExpandedItem: function(primaryColumnValue) {
				(this.getExpandedItems()[primaryColumnValue]) = {"page": 0};
			},
			isItemExpanded: function(primaryColumnValue) {
				return Boolean(this.getExpandedItems()[primaryColumnValue]);
			},
			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);
					this.sortCollection(tempCollection);
					gridDataChild.clear();
					gridDataChild.loadAll(tempCollection);
				}
				this.set("ExpandItemId", null);
			},
			onExpandHierarchyLevels: function(primaryColumnValue, isExpanded) {
				if (!isExpanded || this.isItemExpanded(primaryColumnValue)) {
					return;
				}
				this.setExpandedItem(primaryColumnValue);
				this.set("ExpandItemId", primaryColumnValue);
				this.loadGridData();
			},
			initQueryOptions: function() {
				var parentItem = this.get("ExpandItemId");
				if (!parentItem) {
					var isClearGridData = this.get("IsClearGridData");
					if (isClearGridData) {
						this.clearExpandHierarchyLevels();
					}
					this.callParent(arguments);
				}
			},
			initCanLoadMoreData: function() {
				var parentItem = this.get("ExpandItemId");
				if (!parentItem) {
					this.callParent(arguments);
				}
			},
			changeSorting: function() {
				this.clearExpandHierarchyLevels();
				this.callParent(arguments);
			},
			initQuerySorting: function(esq) {
				var sortedColumn = esq.columns.get("UsrPosition");
				sortedColumn.orderPosition = 0;
				sortedColumn.orderDirection = Terrasoft.OrderDirection.ASC;
			},
			getFilters: function() {
				var parentItem = this.get("ExpandItemId");
				if (parentItem) {
					var parentProjectFilterGroup = this.Terrasoft.createFilterGroup();
					parentProjectFilterGroup.addItem(this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL, "UsrParent", parentItem, Terrasoft.DataValueType.GUID));
					return parentProjectFilterGroup;
				} else {
					var filters = this.callParent(arguments);
					if (this.get("DetailColumnName") !== "UsrParent") {
						var group = this.Terrasoft.createFilterGroup();
						group.addItem(filters);
						group.addItem(Terrasoft.createColumnIsNullFilter(this.entitySchema.hierarchicalColumnName));
						filters = group;
					}
					return filters;
				}
			},
			isProjectsInRoot: function() {
				return (this.get("DetailColumnName") !== "UsrParent");
			},
			isWorkInRoot: function() {
				return !this.isProjectsInRoot();
			},
			initEditPages: function() {
				this.callParent(arguments);
				var editPages = this.get("EditPages");
				var workPage = editPages.collection.items[0];
				workPage.set("Click", {"bindTo": "addToRootRecord"});
				workPage.set("Caption", "Add");
				workPage.set("Visible", true);
				var childItemId = editPages.collection.items[0].instanceId;
				var config = {
					"Id": childItemId,
					"Caption": "New",
					"Click": {"bindTo": "addToChildRecord"},
					"Enabled": {"bindTo": "isSingleSelected"},
					"Tag": childItemId,
					"SchemaName": "UsrReportingPageV2"
				};
				var addToChildMenuItem = this.getActionsMenuItem(config);
				editPages.add(childItemId, addToChildMenuItem);
			},
			replaceDefaultValue: function(key, value) {
				var defaultValues = this.get("DefaultValues");
				var oldValue = defaultValues.filter(function(item) {
					return item.name === key;
				});
				if (Ext.isEmpty(oldValue)) {
					defaultValues.push({
						name: key,
						value: value
					});
				} else {
					Terrasoft.each(oldValue, function(item) {
						item.value = value;
					});
				}
			},
			getDetailInfo: function() {
				var detailInfo = this.sandbox.publish("GetDetailInfo", null, [this.sandbox.id]) || {};
				var defaultValues = this.get("DefaultValues");
				detailInfo.defaultValues = defaultValues;
				return detailInfo;
			},
			addToRootRecord: function(typeUId) {
				var masterRecordId = (typeUId === XRMConstants.Project.EntryType.Project)
					? this.Terrasoft.GUID_EMPTY
					: this.get("MasterRecordId");
				this.replaceDefaultValue("UsrParent", masterRecordId);
				this.addRecord(typeUId);
			},
			addToChildRecord: function() {
				var scope = this;
				var selectedItems = this.getSelectedItems();
				this.set("ExpandItemId", selectedItems[0]);
				this.replaceDefaultValue("UsrParent", selectedItems[0]);
				var masterRecordId = this.get("MasterRecordId");
				if (masterRecordId !== null) {
					var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "UsrReporting"});
					var filter = Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL, "UsrAccount", masterRecordId, Terrasoft.DataValueType.GUID);
					esq.filters.add("filter", filter);
					esq.getEntityCollection(function(response) {
						if (!response || !response.success) {
							return;
						}
						var result = response.collection;
						result.each(function(resultItem) {
							scope.addRecord('c485c4e3-c0a1-4008-a8fe-054f167d5068');
						});
					}, this);
				} else {
					this.addRecord('c485c4e3-c0a1-4008-a8fe-054f167d5068');
				}
			},
			canChangeSelectedItemPosition: function() {
				var selectedItems = this.getSelectedItems();
				return (!Ext.isEmpty(selectedItems) && (selectedItems.length <= 1));
			},
			changePosition: function() {
				var shift = arguments[3];
				var activeRow = this.getActiveRow();
				var projectId = activeRow.get("Id");
				this.updateProjectPosition(projectId, shift, this.onPositionChanged, this);
			},
			onPositionChanged: function(result) {
				if (!result) {
					return;
				}
				var activeRow = this.getActiveRow();
				var parentId = activeRow.get("ParentId");
				if (!parentId) {
					parentId = this.get("MasterRecordId");
				}
				var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchema: this.entitySchema});
				esq.addColumn("UsrPosition");
				var filter = Terrasoft.createColumnFilterWithParameter(
					Terrasoft.ComparisonType.EQUAL, "UsrParent", parentId, Terrasoft.DataValueType.GUID);
				esq.filters.add("filter", filter);
				esq.getEntityCollection(function(response) {
					if (!response || !response.success) {
						return;
					}
					var gridData = this.getGridData();
					var result = response.collection;
					result.each(function(resultItem) {
						var resultItemId = resultItem.get("Id");
						var newPosition = resultItem.get("UsrPosition");
						var gridRecord = gridData.get(resultItemId);
							gridRecord.set("UsrPosition", newPosition);
						});
						var tempCollection = this.Ext.create("Terrasoft.Collection");
						tempCollection.loadAll(gridData);
						this.sortCollection(tempCollection);
						gridData.clear();
						gridData.loadAll(tempCollection);
				}, this);
			},
			sortCollection: function(collection) {
				collection.sortByFn(function(a, b) {
					var positionA = a.get("UsrPosition");
					var positionB = b.get("UsrPosition");
					var q = positionA - positionB;
					return q === 0 ? 0 : (q) / Math.abs(q);
				});
			},
		},
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "merge",
				"name": "DataGrid",
				"values": {
					"type": "listed",
					"hierarchical": true,
					"sortColumnDirection": {"bindTo": "disableGridSorting"},
					"hierarchicalColumnName": "ParentId",
					"updateExpandHierarchyLevels": {
						"bindTo": "onExpandHierarchyLevels"
					},
					expandHierarchyLevels: {
						"bindTo": "expandHierarchyLevels"
					}
				}
			},
			{
				"operation": "insert",
				"name": "OpenReportButton",
				"parentName": "Detail",
				"propertyName": "tools",
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"click": {"bindTo": "openReport"},
					"visible": {"bindTo": "isPortal"},
					"enabled": {"bindTo": "isPortal"},
					"caption": "Open"
				},
				"index": 0
			},
			{
				"operation": "remove",
				"name": "AddRecordButton",
				"values": {
					"visible": {"bindTo": "isCRM"}
				}
			},
			{
				"operation": "insert",
				"name": "UpButton",
				"parentName": "Detail",
				"propertyName": "tools",
				"index": 0,
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"tag": -1,
					"imageConfig": {
						"bindTo": "Resources.Images.UpImage"
					},
					"click": {"bindTo": "changePosition"},
					"visible": {"bindTo": "getToolsVisible"},
					"enabled": {"bindTo": "canChangeSelectedItemPosition"},
					"hint": {"bindTo": "Resources.Strings.ChangePositionUpButtonCaption"}
				}
			},
			{
				"operation": "insert",
				"name": "DownButton",
				"parentName": "Detail",
				"propertyName": "tools",
				"index": 1,
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"tag": 1,
					"imageConfig": {
						"bindTo": "Resources.Images.DownImage"
					},
					"click": {"bindTo": "changePosition"},
					"visible": {"bindTo": "getToolsVisible"},
					"enabled": {"bindTo": "canChangeSelectedItemPosition"},
					"hint": {"bindTo": "Resources.Strings.ChangePositionDownButtonCaption"}
				}
			}
		]/**SCHEMA_DIFF*/
	};
});

Ошибка Uncaught Terrasoft.ItemNotFoundException: Item with key f5695207-a45d-4975-a484-92384cb438d1 Does not exist говорит, что не был найден какой-то элемент.

Уточните, пожалуйста, Вы не удаляли колонки из объекта?

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

Попробуйте заместить метод addItemToGridData следующим образом:

	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.contains(parentId) ? gridData.get(parentId) : undefined;
						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);
						this.sortCollection(tempCollection);
						gridDataChild.clear();
						gridDataChild.loadAll(tempCollection);
					}
					this.set("ExpandItemId", null);
				},

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

define("UsrReportingPageV2", [],
	function() {
		return {
			entitySchemaName: "UsrReporting",
			messages: {},
			attributes: {
				"enabledForPortal": {
					"dataValueType": Terrasoft.DataValueType.BOOLEAN,
					"value":  true
				},
				"visibleEnablePortalBool": {
					"dataValueType": Terrasoft.DataValueType.BOOLEAN,
					"value":  true
				}
			},
			details: /**SCHEMA_DETAILS*/{
				Files: {
					schemaName: "FileDetailV2",
					entitySchemaName: "UsrReportingFile",
					filter: {
						masterColumn: "Id",
						detailColumn: "UsrReporting"
					}
				}
			}/**SCHEMA_DETAILS*/,
 
			mixins: {},
			methods: {
				init: function () {
					var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
						"rootSchemaName": "SysAdminUnit"
					});
					esq.addColumn("Id");
					esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL, "Id", Terrasoft.SysValue.CURRENT_USER.value));
					esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL, "[SysAdminUnitInRole:SysAdminUnit:Id].SysAdminUnitRoleId",
						"720B771C-E7A7-4F31-9CFB-52CD21C3739F"));
					esq.getEntityCollection(function(result) {
						var isPortalUser = result.success && (result.collection.getCount() === 1);
						this.set("enabledForPortal", !isPortalUser);
						this.set("visibleEnablePortalBool", !isPortalUser);
						if (isPortalUser) this.checkEnabled();
					}, this);
					this.callParent(arguments);
				},
				checkEnabled: function () {
					if (this.get("UsrEnablePortal")) {
 
					}
				},
				onSaved: function() {
					if (Terrasoft.configuration.Storage.hasOwnProperty("newChildReport")) {
						var accountID, parentID;
						var defValues = this.get("DefaultValues");
						for (var i = 0; i < defValues.length; i++) {
							switch (defValues[i].name) {
								case "UsrAccount":
									accountID = defValues[i].value;
									break;
								case "UsrParent": 
									parentID = defValues[i].value;
									break;
							}
						}
						var update = Ext.create("Terrasoft.UpdateQuery", {
							rootSchemaName: "UsrReporting"
						});
						update.setParameterValue("UsrAccount", accountID, Terrasoft.DataValueType.GUID);
						update.setParameterValue("UsrParent", parentID, Terrasoft.DataValueType.GUID);
						var filter = update.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Id" , this.get("Id"));
						update.filters.add("FilterId", filter);
 
						update.execute(function(result) {
 
						});
						delete Terrasoft.configuration.Storage.newChildReport;
					}
					this.callParent(arguments);
				}
			},
			diff: /**SCHEMA_DIFF*/[
	{
		"operation": "insert",
		"name": "UsrDisplayPortal",
		"values": {
			"layout": {
				"colSpan": 12,
				"rowSpan": 1,
				"column": 12,
				"row": 1,
				"layoutName": "Header"
			},
			"enabled": {"bindTo": "enabledForPortal"},
			"visible": {"bindTo": "visibleEnablePortalBool"},
			"bindTo": "UsrDisplayPortal"
		},
		"parentName": "Header",
		"propertyName": "items",
		"index": 0
	},
	{
		"operation": "insert",
		"name": "UsrFileName",
		"values": {
			"layout": {
				"colSpan": 12,
				"rowSpan": 1,
				"column": 0,
				"row": 0,
				"layoutName": "Header"
			},
			"bindTo": "UsrFileName",
			"enabled": {"bindTo": "enabledForPortal"},
			"visible": true
		},
		"parentName": "Header",
		"propertyName": "items",
		"index": 1
	},
	{
		"operation": "insert",
		"name": "HistoryTabContainer",
		"values": {
			"caption": {
				"bindTo": "Resources.Strings.HistoryTabCaption"
			},
			"items": []
		},
		"parentName": "Tabs",
		"propertyName": "tabs",
		"index": 0
	},
	{
		"operation": "insert",
		"name": "Files",
		"values": {
			"itemType": 2
		},
		"parentName": "HistoryTabContainer",
		"propertyName": "items",
		"index": 0
	},
	{
		"operation": "remove",
		"name": "ESNTab"
	},
	{
		"operation": "remove",
		"name": "ESNFeedContainer"
	},
	{
		"operation": "remove",
		"name": "ESNFeed"
	}
]/**SCHEMA_DIFF*/
	};
});
Показать все комментарии
Деталь
обновление грида
Обновление детали
Технические вопросы
7.x

Добрый день.

Проблема с обновлением грида детали после добавления элемента в деталь. Элемент не появляется в гриде сразу после выбора.

1. Выбор элементов в детали реализован с помощью LookupUtilities:

        var lookupConfig = {
                entitySchemaName: "BankingService",
                columnName: "Name",
                columns: ["ClientType"],
                multiSelect: true,
                filters: filters
        };
           
        LookupUtilities.ThrowOpenLookupMessage(
            sandbox,
            lookupConfig,
            this.addBankingServiceItemsCallback,
            this,
            this.getCardModuleSandboxId()
        );

2. Собственно callback-функция для обработки выбора пользователя:

                this.methods.addBankingServiceItemsCallback = function(args) {
                        if (!args || args.selectedRows.getCount() === 0) {
                                return;
                        }
                       
                        var selectedIds = args.selectedRows.getKeys();
                        var synchronizedRule = this.filterValue;
                        var batchQuery = Ext.create('Terrasoft.BatchQuery');
                        Terrasoft.each(selectedIds, function(item) {
                                var insert = Ext.create('Terrasoft.InsertQuery', {
                                        rootSchemaName: this.entitySchema.name
                                });
                                var newGuid = Terrasoft.generateGUID();
                                insert.setParameterValue(
                                        'Id',
                                        newGuid,
                                        Terrasoft.DataValueType.GUID
                                );
                                insert.setParameterValue(
                                        'BankingService',
                                        item,
                                        Terrasoft.DataValueType.GUID
                                );
                                insert.setParameterValue(
                                        'SynchronizedRule',
                                        synchronizedRule,
                                        Terrasoft.DataValueType.GUID
                                );
                                batchQuery.add(insert);
                        }, this);
                        batchQuery.execute();
                        sandbox.publish('DetailChanged', {detailName: this.entitySchema.name}, [this.getSenderSandboxId()]);
                };

3. Обработчик события DetailChanged на странице редактирования объекта с деталью:

                this.methods.detailChangedSubscriber = function(args) {
                        viewModel.reloadDetail(args.detailName + 'Detail');
                };

Однако, после нажатия кнопки "Выбрать", выбранные записи в гриде детали не отображаются. Если нажать "Сохранить" на странице редактирования объекта и потом открыть заново этот объект для редактирования, то в детали выбранные записи видны.

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

Заранее благодарен за помощь!

Нравится

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

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

уточните пожалуйста версию и конфигурацию BPMOnline. Спасибо!!!

"Власов Михаил Викторович" написал:

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

уточните пожалуйста версию и конфигурацию BPMOnline. Спасибо!!!

Михаил, версия 7.2; конфигурация вроде "lending"

Здравствуйте, я не воссоздавал на тестовом примере batchQuery, это не суть вопроса, сразу менял данные детали в базе данных, через sql management studio. Самое главное здесь в вашем вопросе, это вызов «viewModel.reloadDetail(args.detailName + 'Detail');»

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

Во-вторых, почему viewModel? Данный метод же есть прямо в главном скоупе страницы. Я закешировал для теста скоуп страницы в инит методе:

structure.userCode = function() {
   this.methods.init = function() {
      document.scp = this;
   };
};

И вот видно наш метод для обновления детали:

Во вторых, имя, передаваемое как аргумент должно соответствовать именно «name» свойству детали, а не «schemaName». Вот, к примеру, деталь опыта работы контакта:

И вот такой её вызов, отлично обновляет содержимое грида:

document.scp.reloadDetail("contactCareer");

где «document.scp» по сути this скоуп страницы контакта.

Вывод: Отладьте метод, проверьте имена.

Показать все комментарии
Communication options
Деталь
Технические вопросы
7.x

Добрый день!

Бизнес-кейс:
Необходимо у контакта делать пометки к средствам связи. Например, "конкретный телефон - телефон бабушки" или "по этому номеру не звонить после 21.00".

Как возможно добавить комментарий к каждому средству связи в детали communication options стандартным функционалом (не отказываясь от этой детали)?

Спасибо!

Нравится

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

Деталь «Средства связи является» не простой деталью так как она формируется динамически и кардинально отличается от обычных деталей. Мы не рекомендуем вносить исправления в данную деталь, так как Вы можете нарушить логику ее заполнения.
Для внесения изменений в деталь средства связи Вам необходимо будет заместить объект "ContactCommunication" и добавить текстовое поле с произвольным названием. Расширить страницу ContactCommunicationDetailV2, переопределить метод getItemViewConfig.
Ниже, как пример (в случае если новое поле назвать Comment). Изменения выделены комментариями. Можете также попробовать сделать по другому с вызовом родительского метода.

getItemViewConfig: function(itemConfig) {
var itemViewConfig = this.get("itemViewConfig");
if (itemViewConfig) {
itemConfig.config = itemViewConfig;
return;
}
var config = ViewUtilities.getContainerConfig("item-view",
["detail-edit-container-user-class", "control-width-15"]);
var typeMenuItems = [];
var communicationTypes = this.get("CommunicationTypes");
communicationTypes.each(function(item) {
var name = item.get("Name");
var value = item.get("Id");
typeMenuItems.push({
id: value,
caption: name,
tag: value,
click: { bindTo: "typeChanged" }
});
}, this);
var typeButtonConfig = {
id: "type",
className: "Terrasoft.Button",
classes: {
wrapperClass: ["label-wrap", "detail-type-btn-user-class"],
textClass: ["detail-type-btn-inner-user-class"]
},
style: Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
selectors: {wrapEl: "#type"},
caption: {
bindTo: "CommunicationType",
bindConfig: { converter: "typedStringValueConverter" }
},
menu: { items: typeMenuItems }
};
var deleteButtonConfig = {
id: "delete",
className: "Terrasoft.Button",
classes: {
wrapperClass: "detail-delete-btn-user-class",
imageClass: ["detail-delete-btn-image-user-class", "close-button-background-no-repeat"]
},
imageConfig: resources.localizableImages.DeleteIcon,
style: Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
selectors: {wrapEl: "#delete"},
click: {bindTo: "deleteItem"}
};
var editConfig = {
id: "edit",
className: "Terrasoft.TextEdit",
classes: {wrapClass: ["communication-lookup-img-user-class", "detail-edit-user-class"]},
rightIconClasses: ["lookup-edit-right-icon"],
value: { bindTo: "Number" },
readonly: {
bindTo: "CommunicationType",
bindConfig: { converter: "isSocialNetworkType" }
},
enableRightIcon: {
bindTo: "CommunicationType",
bindConfig: { converter: "isSocialNetworkType" }
},
rightIconClick: { bindTo: "onLookUpClick" }
};
//Начало исправления
var commentConfig = {
id: "comment",
className: "Terrasoft.TextEdit",
value: { bindTo: "Comment" },
};
//Завершение исправления
config.items.push(typeButtonConfig, editConfig, deleteButtonConfig, commentConfig); //добавляем commentConfig

itemConfig.config = config;
this.set("itemViewConfig", config);
},

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