Добрый день.

Например имеется объект UsrEntity. Хочу открыть справочник для добавления элемента на деталь с возможностью выбора из списка этого объекта. Но, чтобы в списке НЕ БЫЛО тех элементов, которые удовлетворяют условию UsrEntity.UsrA in existedA && UsrEntity.UsrB in existedB && UsrEntity.UsrC in existedC. Пока вижу только один путь это создать представление в SQL и открывать это представление. А возможно ли сделать подобный фильтр на фронте? Может быть есть возможность сделать кастомный фильтр и вставить в конфиг при открытии справочника?

Нравится

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

Решил задачу. Можно же просто UsrEntity.UsrA not in existedA || UsrEntity.UsrB not in existedB || UsrEntity.UsrC not in existedC.

Но так как по колонке A, я уже фильтровал, достаточно было только B и C. А ещё засунул в группу фильтров, другую группу фильтров. Не знал, что так можно

addRecord: function () {
					let activeRowId = this.get("ActiveRow");
					if (!activeRowId) {
						return;
					}
 
					const gridData = this.getGridData();
					let rowData = gridData.get(activeRowId).values;
					if (rowData.IDSBParent){
						activeRowId = rowData.IDSBParent.value;
						rowData = gridData.get(activeRowId).values;
					}
 
					let filterCollection = Terrasoft.createFilterGroup();
					const productFilter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
						"IDSBProductId", rowData.IDSBProduct.value);
					filterCollection.add("productFilter", productFilter);					
 
					let existed = [];
					gridData.collection.items.forEach(function(item){
						if (!item.values.IDSBParent){
							return;
						}
 
						if (item.values.IDSBParent.value !== activeRowId){
							return;
						}
 
						existed.push(item.values);
					}, this);
 
					let notExistedFilterCollection = Terrasoft.createFilterGroup();
					notExistedFilterCollection.logicalComparisonTypes = Terrasoft.LogicalOperatorType.OR;
 
					let existsWarehouseFilter = Terrasoft.createColumnInFilterWithParameters("IDSBWarehouseId", existed.map(item => item.IDSBWarehouse.value));
					existsWarehouseFilter.comparisonType = Terrasoft.ComparisonType.NOT_EQUAL;
					notExistedFilterCollection.add(existsWarehouseFilter);
 
					let existsPercentFilter = Terrasoft.createColumnInFilterWithParameters("IDSBPercent", existed.map(item => item.IDSBPercent));
					existsPercentFilter.comparisonType = Terrasoft.ComparisonType.NOT_EQUAL;
					notExistedFilterCollection.add(existsPercentFilter);
 
					filterCollection.add("notExistedFilterCollection", notExistedFilterCollection);
 
					const config = {
						entitySchemaName: "IDSBVwExpiredRemaining",
						multiSelect: true,
						columns: ["IDSBWarehouseId", "IDSBProductId", "IDSBPercent"],
						filters: filterCollection
					};
 
					this.openLookup(config, this.IDSBAddSelectedProducts, this);
				},

 

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

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

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

Нравится

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

в diff

{

                "operation": "merge",

                "name": "AddTypedRecordButton",

                "parentName": "Detail",

                "propertyName": "tools",

                "values": {

                    "itemType": Terrasoft.ViewItemType.BUTTON,

                    "controlConfig": {

                        "menu": {

                            "items": {"bindTo": "addMenuItems"}

                        }

                    },

                "visible": true,

                "enabled": true

                }

            },

methods

init: function() {

                this.callParent(arguments);

                this.initAddMenuItems();

            },

            initAddMenuItems: function() {

                var addMenuItems = Ext.create("Terrasoft.BaseViewModelCollection");

                addMenuItems.add("addContactItem", this.Ext.create("Terrasoft.BaseViewModel", {

                    values: {

                        "Caption": {"bindTo": "Resources.Strings.AddContactCaption"},

                        "Click": {"bindTo": "addRecipient"},

                        "Tag": "addContact"

                    }

                }));

                addMenuItems.add("addbytemplateItem", this.Ext.create("Terrasoft.BaseViewModel", {

                    values: {

                        "Caption": {"bindTo": "Resources.Strings.AddByTemplate"},

                        "Click": {"bindTo": "addRecipient"},

                        "Tag": "addbytemplate"

                    }

                }));

                this.set("addMenuItems", addMenuItems);

            },

 

в diff

{

                "operation": "merge",

                "name": "AddTypedRecordButton",

                "parentName": "Detail",

                "propertyName": "tools",

                "values": {

                    "itemType": Terrasoft.ViewItemType.BUTTON,

                    "controlConfig": {

                        "menu": {

                            "items": {"bindTo": "addMenuItems"}

                        }

                    },

                "visible": true,

                "enabled": true

                }

            },

methods

init: function() {

                this.callParent(arguments);

                this.initAddMenuItems();

            },

            initAddMenuItems: function() {

                var addMenuItems = Ext.create("Terrasoft.BaseViewModelCollection");

                addMenuItems.add("addContactItem", this.Ext.create("Terrasoft.BaseViewModel", {

                    values: {

                        "Caption": {"bindTo": "Resources.Strings.AddContactCaption"},

                        "Click": {"bindTo": "addRecipient"},

                        "Tag": "addContact"

                    }

                }));

                addMenuItems.add("addbytemplateItem", this.Ext.create("Terrasoft.BaseViewModel", {

                    values: {

                        "Caption": {"bindTo": "Resources.Strings.AddByTemplate"},

                        "Click": {"bindTo": "addRecipient"},

                        "Tag": "addbytemplate"

                    }

                }));

                this.set("addMenuItems", addMenuItems);

            },

 

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

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

При добавлении участник не появляется в детали.Изображение удалено.

Нравится

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

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

 

эта деталь отображает участников встречи. Заполните поле Встреча в протоколе и на детали автоматически отобразятся ее участники. Соответственно рекомендую как и ранее добавлять участников в разделе Активности.

 

Если такой вариант не удобен, уточните ваш кейс.

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

Добрый день!

Я создал свою деталь на основе статьи из wiki https://academy.terrasoft.ru/documents/technic-sdk/7-15/detal-s-redaktiruemym-reestrom 

Возникла проблема с регистрацией детали.

Выполнил скрипт добавления в таблицу [SysDetail]

 

DECLARE 

    -- Название схемы представления создаваемой миникарточки.

    @ClientUnitSchemaName NVARCHAR(100) = 'UsrTariffsForAddDetail',

    -- Название схемы объекта, к которому привязывается миникарточка.

    @EntitySchemaName NVARCHAR(100) = 'UsrAdduser',

    -- Название детали.

    @DetailCaption NVARCHAR(100) = 'Услуги.'

INSERT INTO SysDetail(Caption, DetailSchemaUId, EntitySchemaUId)

VALUES(@DetailCaption,

     (SELECT TOP 1 UId

      from SysSchema

      WHERE Name = @ClientUnitSchemaName),

      (SELECT TOP 1 UId

      from SysSchema

      WHERE Name = @EntitySchemaName))



В таблице добавилась запись. Но в разделе все так же отображается, что деталь не зарегистрирована.

Прошу помочь, в чем может быть проблема? Изображение удалено.

Нравится

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

Сделайте полную компиляцию, очистите Redis. Но если честно, то советовал бы Вам создавать через мастер деталей, а потом просто в Detail модуле прописать код для редактирования в реестре. Это избавит вас от регестрации через базу, да и от колег слышал что у них бывало что проблемы в с использованием потом (хотя думаю они что-то просто забыли), но все же так экономине время и все точно работает так как мастер еще и кеш чистит потом. Только не забудьте переименовать модели созданные мастером и если будет после переименования ругаться по перекомпилируйте тоже

Александр Тыра,

Добрый день! полная компиляция и очистка кэша не помогла.

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

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

Всем добрый день!

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

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

Нравится

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

Это ещё реализовано и в Средствах связи

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

В средствах связи, схеме ContactCommunicationDetailV2 добавленные и удалённые складываются в две коллекции Collection и DeletedItems и при сохранении из них извлекаются и идут на сервер одним составным запросом:

deleteItem: function(item) {
	var deletedItems = this.get("DeletedItems");
	var collection = this.get("Collection");
	collection.removeByKey(item.get("Id"));
	deletedItems.addItem(item);
},
 
addItem: function(tag) {
	if (this.get("IsDetailCollapsed")) {
		return;
	}
	var communicationTypes = this.get("CommunicationTypes");
	var communicationType = communicationTypes.get(tag);
	var newItem = this.Ext.create("Terrasoft.BaseCommunicationViewModel", {
		entitySchema: this.entitySchema,
		columns: this.columns
	});
	newItem.set("CommunicationTypes", communicationTypes);
	newItem.sandbox = this.sandbox;
	newItem.setDefaultValues(function() {
		newItem.set("CommunicationType", {
			value: communicationType.get("Id"),
			displayValue: communicationType.get("Name")
		});
		newItem.set("Contact", {
			value: this.get("MasterRecordId")
		});
		var itemKey = newItem.get("Id");
		var collection = this.get("Collection");
		collection.add(itemKey, newItem);
		this.changeCardPageButtonsVisibility(true);
	}, this);
	return newItem;
},
 
...
 
getDeleteItemsQueries: function() {
	var deletedItems = this.get("DeletedItems");
	var deleteQueries = [];
	deletedItems.each(function(item) {
		var primaryColumnValue = item.get(item.primaryColumnName);
		var deleteQuery = item.getDeleteQuery();
		deleteQuery.enablePrimaryColumnFilter(primaryColumnValue);
		deleteQueries.push(deleteQuery);
	}, this);
	return deleteQueries;
},
 
getSaveItemsQueries: function() {
	var collection = this.get("Collection");
	var saveQueries = [];
	collection.each(function(item) {
		if (item.isChanged() && item.validate()) {
			saveQueries.push(item.getSaveQuery());
		}
	}, this);
	return saveQueries;
},
 
...
 
save: function() {
	var restrictionsQuery = this.getSaveRestrictionsQuery();
	var queries = restrictionsQuery ? [restrictionsQuery] : [];
	var saveQueries = this.getSaveItemsQueries();
	queries = queries.concat(saveQueries);
	var deleteQueries = this.getDeleteItemsQueries();
	queries = queries.concat(deleteQueries);
	if (Ext.isEmpty(queries)) {
		this.publishSaveResponse({
			success: true
		});
		return true;
	}
	var batchQuery = Ext.create("Terrasoft.BatchQuery");
	Terrasoft.each(queries, function(query) {
		batchQuery.add(query);
	}, this);
	batchQuery.execute(this.onSaved, this);
	return true;
},
 
onSaved: function(response) {
	var message = response.ResponseStatus && response.ResponseStatus.Message;
	if (response.success && !message) {
		var deletedItems = this.get("DeletedItems");
		var collection = this.get("Collection");
		collection.each(function(item) {
			item.isNew = false;
			item.changedValues = null;
		}, this);
		deletedItems.clear();
		this.publishSaveResponse(response);
	} else {
		this.publishSaveResponse({
			success: false,
			message: this.getValidationMessage(message)
		});
	}
},

 

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

Подскажите, есть ли возможность заблокировать деталь со страницей редактирования?

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

Нравится

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

Зверев Александр пишет:

Тогда механизм прав Вам не поможет, он регулирует доступность вне зависимости от раздела, где на детали видна запись.

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

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

А возможность сохранения регулировали правами на объект или запись

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

 тогда как решить такую задачу механизмом прав - есть продажа, у на последнем этапе у нее блокируются все поля и детали? При этом детали есть общие для раздела "Договоры" (сделаны как в заказе с продуктами) и деталь "Контакты", есть детали что в контрагенте. При этом наследовать права от продажи нельзя так как доступы в контрагентах другие и если запретить редактирование в детали то через контрагента добавить не сможем.

Можно раздавать права через бизнес-процесс для каждой записи в детали, но если мы меняем этам нам нужно снова запускать процесс по всему списку. К тому же на странице редактирования записи детали нет управления доступом и потому изменить доступ можно снова через бизнес-процесс. Так образом мы увеличиваем нагрузку увеличившимся количеством процессов и можем поучить еще и опасность зависание процесса.

Думаю удобнее сделать наследование блокировки как это реализовано для детали с редактируемым реестром но в открывающейся странице (удобно потому что полей много бывает и просто для просмотра надо бы открывать как сейчас реализовано)

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

 

И тогда вопрос - доступы раздела можно посмотреть в таблице "Sys + название схемы + Right", а вот где смотреть доступы для деталей? К примеру нужно скопировать все доступы из раздела в деталь, как это можно сделать?

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

Тогда механизм прав Вам не поможет, он регулирует доступность вне зависимости от раздела, где на детали видна запись.

 И тогда вопрос - доступы раздела можно посмотреть в таблице "Sys + название схемы + Right", а вот где смотреть доступы для деталей?

Так же само. 

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

Если разово, то проще всего написать SQL-запрос. Если постоянно, то выдавать можно БП. Но если хотите завязаться на событие именно выдачи прав в самом объекте, то такого события вроде бы нет, разве что SQL-триггером. 

Зверев Александр пишет:

Тогда механизм прав Вам не поможет, он регулирует доступность вне зависимости от раздела, где на детали видна запись.

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

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

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

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

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

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

Может есть другой способ, так как

onDetailChanged: function() {
	this.callParent(arguments);
	this.sameFun();
},

не работает в разделе продажи

Нравится

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

Коновалов Игорь,

 сделал через бизнеспроцес в объекте наблицы, подписался на изменения записей и отправляю об этом сообщения, на фронте сделал на них подписку

В кл. схеме OpportunityPage

в блоке details переопределите деталь:

"Название детали":{

               schemaName: "<Название схемы детали>",

               entitySchemaName: "<Название объекта детали>",

               subscriber: {

                      methodName: "<Название метода, отрабатывающего при                        изменении детали>"},

}

Очистите кэш.

После этого откройте мастер раздела и внесите любую правку в страницу редактирования.

После этого проверьте не затрётся ли subscriber

Коновалов Игорь,

 пробовал, subscriber не срабатывает на детали визирования так как наследуеться от модуля где нет реализации это поля в

onDetailChanged. А так как onDetailChanged не срабатывает то и если добавить при замещении функции с добавлением этого поля все равно работать отказываеться

 

Коновалов Игорь,

 сделал через бизнеспроцес в объекте наблицы, подписался на изменения записей и отправляю об этом сообщения, на фронте сделал на них подписку

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

Доброго времени суток.



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



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

В случае, если вкладка найдена не была - добавить вкладку с привязкой детали (то есть выполнить процедуру вставки на основе diff)



Есть ли возможность динамически изменить свойство "parentName" у детали? (или как получить объектное представление детали для изменения свойства)

define("SomeModuleName", [], function() {
    return {
    details: {
        "DetailName": {
            "schemaName": "schemaName",
            "entitySchemaName": "entitySchemaName",
            "filter": {
                "detailColumn": "detailColumn",
                "masterColumn": "Id"
            }
        }
    },
    diff: /**SCHEMA_DIFF*/[ 
        {
            "operation": "insert",
            "name": "AddedTabName",
            "values": {
                "items": [],
                "caption": {
                    "bindTo": "Resources.Strings.AddedTabNameCaption"
                },
            },
            "parentName": "Tabs",
            "propertyName": "tabs",
            "index": 1
        },
    {
        "operation": "insert",
        "name": "CardDetail",
        "values": {
            "itemType": this.Terrasoft.ViewItemType.DETAIL,
            "visible": { "bindTo": "CardDetailVisible" }
        },
        "parentName": "AddedTabName",
        "propertyName": "items",
        "index": 0
        },
    ]/**SCHEMA_DIFF*/,
    methods: {
        onEntityInitialized: function() {
            this.callParent(arguments);
            // myMethodToUpdateVisibility();
        },
        }
    };
});

Вкладка (tab) на которую надо перенести деталь также динамически (также из кода клиентского модуля) добавляется сторонним пакетом.



Спасибо

Нравится

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

Добрый день! Возможно, проще добавить 2 детали на разные вкладки, и в зависимости от условий ненужное скрывать, чем динамически вставлять\перемещать

Добрый день! Возможно, проще добавить 2 детали на разные вкладки, и в зависимости от условий ненужное скрывать, чем динамически вставлять\перемещать

Лопатин Константин,

Спасибо за ваш вариант, попробую такой подход.

или как предложил Лопатин Константин или технически есть возможность закидывать и изымать элемент через ext, если вам вдруг не хватает геморроя в вашем проекте)

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

Сценарий:

1. Заходим в раздел (для примера "Контакты")

2. Переходим на вкладку "История"

3. Раскрываем доп. меню у детали "Активности" - выбираем "Выбрать несколько записей"

4. Отмечаем любое количество записей

5. Переходим через гиперссылку-название активности

6. Нажимаем "Закрыть" на открывшейся странице

7. На странице пропала отметка о множественном выборе для отмеченных нами ранее записей



Не страшно, но в некоторых ситуациях может пригодится сохранение состояния выбора для множественного выбора

 

Спасибо.

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

Здравствуйте, Сергей!

 

Передали данное пожелание команде разработки для анализа возможности внедрения такой возможности в будущих версиях продукта.

 

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

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

В данный момент при создании детали мастером автоматически создаётся схема детали с названием [Сист настр.Префикс] + константа [Schema] + [индекс] + [Detail], например, для объекта ContactLevel получится UsrSchema1Detail, а хотелось бы чтобы ContactLevel подставлялся вместо константы [Schema] вот так: UsrContactLevel1Detail.

Так же как это реализовано в алгоритме генерации названия карточки схемы детали, которое формируется аналогично, но [Schema] - не константа, а имя объекта, например,  "UsrSchema1Page".



Кратко: сейчас название схемы детали, созданной мастером, на примере объекта "ContactLevel" сгенерируется = "UsrSchema1Detail", а хотелось бы чтобы было "UsrContactLevel1Detail"

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

Уточните, с какой версией Вы работаете?

Алла Савельева, с 7.11 по 7.15.3 включительно

Здравствуйте, Константин!

 

Передали данное пожелание команде разработки для анализа возможности внедрения такой возможности в будущих версиях продукта.

 

Ранее такую же идею подавали и на англоязычном Community.

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

 

Мотков Илья пишет:

Ранее такую же идею подавали и на англоязычном Community.

 

К слову и не только на англоязычном

https://community.terrasoft.ru/ideas/master-sozdania-detalei-i-normalnoe-naimenovanie-shemy-detali-schemaxdetail 

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