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

 attributes: {
                "Order": {
                    lookupListConfig: {
                        columns: [
                            "Account.SxNAVCode", "SxShippingType.Code",
                            "Owner.SxNAVCode","SxContract.SxNAVCode",
                            "Date","Account.SxCFO.Code","Account.Id","Account.SxTradeChain.SxNAVCode", "Account.SxTradeChain.SxCFO.Code"
                            ,"Account.SxSalesOutletType","SxPaymentFormula","SxPaymentFormula.SxPaymentDelay","SxWarehouse.SxCode"
                        ]
                    }
                },

.........................................
//в секции rules
 "SxDesiredDiscount": {
                    "BindParameterEnabledToPaymentDelay": {
                        "ruleType": BusinessRuleModule.enums.RuleType.BINDPARAMETER,
                        "property": BusinessRuleModule.enums.Property.ENABLED,
                        "conditions": [
                            {
                                "leftExpression": {
                                    "type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
                                    "attribute": "Order.SxPaymentFormula.SxPaymentDelay"
                                    attributePath:""
                                },
                                "comparisonType": Terrasoft.ComparisonType.LESS,
                                "rightExpression": {
                                    "type": BusinessRuleModule.enums.ValueType.CONSTANT,
                                    "value": 45
                                }
                            }
                        ]
                    }
                },

в детали также добавлены колонки

getGridDataColumns: function() {
                var config = this.callParent(arguments);
                config["Order.Account"]= { path: "Order.Account" };
                config["Order.Date"]= { path: "Order.Date" };
                config["Order.SxPaymentFormula"]= { path: "Order.SxPaymentFormula" };
                config["Order.SxPaymentFormula.SxPaymentDelay"]= { path: "Order.SxPaymentFormula.SxPaymentDelay" };
                config["Order.Account.SxSalesOutletType"]= { path: "Order.Account.SxSalesOutletType" };
                return config;
            }

Проблема в том, что при добавлении требуемое значение при добавлении можно получить как:
this.get("Order")["SxPaymentFormula.SxPaymentDelay"]
а при изменении:
this.get("Order.SxPaymentFormula.SxPaymentDelay"));

Следовательно есть разница в работе правил.

Подскажите пожалуйста, как решить данную проблему? Как верно сформировать конфиг, чтоб он всегда был одинаковым?

Нравится

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

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

Попробуйте в leftExpression указать параметры attribute и attributePath так:

"attribute": "Order",
"attributePath":"SxPaymentFormula.SxPaymentDelay"

Я таким образом сразу пробовал. Не помогло. Все равно работает или при добавлении или при изменении.

Александр, самый простой способ - устанавливать значение атрибута в методе initEntity карточки детали. Примерно так:

initEntity: function(callback, scope) {
	this.callParent([function() {
		if (!this.get("Order.SxPaymentFormula.SxPaymentDelay")) {
			this.set("Order.SxPaymentFormula.SxPaymentDelay",
				this.get("Order") && this.get("Order")["SxPaymentFormula.SxPaymentDelay"]);
		}
		callback.call(scope || this);
	}, this]);
}

В бизнес-правиле в этом случае необходимо использовать только "attribute": "Order.SxPaymentFormula.SxPaymentDelay".

Олег, работает.
Спасибо за помощь!

Подскажите пожалуйста, пытаюсь добавить фильтрацию, одного поля по значению другого, в редактируемом реестре. - http://www.community.terrasoft.ru/forum/topic/15497

Тут рассматриваеться BINDPARAMETER, возможна ли работа правила FILTRATION?

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

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

подскажите, пожалуйста, как фильтровать значение поля детали по значению поля объекта, в котором деталь. У меня в продажах есть деталь Доп.соглашения,в которой есть поле-ссылка на Договор. Мне нужно фильтровать договора по полю Контрагент - показывать только те договора, которые принадлежат контрагенту текущей продажи.
Я создала карточку редактирования, прописала в ней бизнес правило со ссылкой на атрибут AccountId. Но не могу определить, когда заполнять этот атрибут. в момент, когда срабатывает initEntity в самой сущности Доп.соглашение еще не заполнено поле Продажа. а методы init, onEntityInizialized не срабатывают
Есть какой-то вариант, как я могу получить id текущей сущности(продажи), в которой находится деталь, из карточки редактирования детали (не из схемы детали, а из карточки)?

Добрый день, Любовь.

Насколько я понял Ваш кейс, вы пытаетесь добавить деталь, объект которой - Договор. Достаточно будет связать данную деталь с карточкой следующим образом - объект детали AccountId = объекта карточки AccountId.
Если же Вы пытаетесь добавить деталь, объект которой кастомный, и в нем просто присутствует поле Договор, то реализовать такую логику не получится. Действительно, init/onEntityInizialized при загрузке детали не срабатывают, они отработают только если Вы откроете объект детали на редактирование.

"Мотков Илья" написал:Если же Вы пытаетесь добавить деталь, объект которой кастомный, и в нем просто присутствует поле Договор, то реализовать такую логику не получится. Действительно, init/onEntityInizialized при загрузке детали не срабатывают, они отработают только если Вы откроете объект детали на редактирование.

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

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

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

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

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

Подскажите пожалуйста как узнать входит ли пользователь в определенную функциональную или организационную роль на клиенте и сервере.

Нравится

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

Здравствуйте.
В базе данных есть таблица SysUserInRole. Там содержится развязка вхождения пользователей в роли (поля SysUserID, SysRoleID). Сами пользователи и роли находятся в таблице SysAdminUnit.

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

attributes: {
    "Owner": {
        dataValueType: Terrasoft.DataValueType.LOOKUP,
	lookupListConfig: { filters: [ function() {
		var filterGroup = Ext.create("Terrasoft.FilterGroup");
		filterGroup.add("IsPurchasingDepartment",
		Terrasoft.createColumnFilterWithParameter(
			Terrasoft.ComparisonType.EQUAL,
			"[SysUserInRole:SysUser:[SysAdminUnit:Contact].Id].SysRole",
			"eb2644b7-9647-440c-9a05-6318d8d9e3b2")); 
		return filterGroup;
		}]}
	}
}

При открытие появляется ошибка "Элемент коллекции с именем Id] не найден", насколько понял неправильно написано "[SysUserInRole:SysUser:[SysAdminUnit:Contact].Id].SysRole" использовал пример из SDK "Построение путей к колонкам относительно корневой схемы. 3) Колонка схемы по произвольному внешнему ключу"
с одной связью понятно, но для двух примера нет, подскажите как правильно построить путь, не получилось разобраться.

Такой уровень вложенности вероятно не получится сделать.
Попробуйте написать esq к таблице «SysAdminUnit» по условию «SysUserInRole» (join), и выберите из него Id этой самой «SysAdminUnit», прямо в функции фильтрации.
А полученный массив Id уже передайте через «createColumnInFilterWithParameters» как-то так:

define("AccountPageV2", ["AccountPageV2Resources", "GeneralDetails"],
function(resources, GeneralDetails) {
	return {
		entitySchemaName: "Account",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		attributes: {
			"Owner": {
				dataValueType: Terrasoft.DataValueType.LOOKUP,
				lookupListConfig: {
					filter: function() {
 
						// массив айди из SysAdminUnit, где-то тут напишите esq вместо него
						var idList = ["5CE92315-6128-44BE-A175-238EC6E3609F", "85C1DE5F-DD7E-4F8D-8F97-D3D8630A2C2F"];
 
						var filterGroup = new Terrasoft.createFilterGroup();
						var filterById = Terrasoft.createColumnInFilterWithParameters("[SysAdminUnit:Contact:Id].Id", idList);
						filterById.comparisonType = Terrasoft.ComparisonType.EQUAL;
						filterGroup.add("filterById", filterById);
 
						return filterGroup;
					}
				}
			}
		},
		methods: {},
		rules: {},
		userCode: {}
	};
});

Только вместо idList разумеется, будет результат esq.

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

Желаемый уровень вложенности невозможен. А асинхронность можно побороть пользуясь колбеками. Примеры использования колбеков в esq есть в типовых схемах.

Максим Шевченко пишет:

Желаемый уровень вложенности невозможен

То есть, никак не узнать, входит ли пользователь в функциональную роль опосредованно (наример, является руководителем сотрудника, у которого есть данная функциональная роль)?  

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

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

Подскажите как в замещающей схеме удалить бизнес правила на примере раздела активности.
Есть две предустановленные схемы Document.ActivityPageV2 и DocumentInOpportunity.ActivityPageV2 (замещают UIv2.ActivityPageV2) в них содержаться бизнес правила фильтрации по контрагенту, контакту и продаже.
Эти правила нужно убрать, вернее оставить только фильтрацию по контрагенту. Пока мои попытки ничего не дали, пробовал в своей замещающей схеме добавить бизнес правило с существующем названием и другим фильтром, но оно просто добавилось к остальным.

Нравится

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

Попробуйте заместить бизнес-правило, которое хотите отключить и проставить свойство enabled: false.

"Мотков Илья" написал:

Попробуйте заместить бизнес-правило, которое хотите отключить и проставить свойство enabled: false.

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

"Document": {
	"FiltrationDocumentByAccount": {
		"ruleType": BusinessRuleModule.enums.RuleType.FILTRATION,
		"autocomplete": true,
		"autoClean": true,
		"baseAttributePatch": "Account",
		"comparisonType": Terrasoft.ComparisonType.EQUAL,
		"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		"attribute": "Account"
	},
	"FiltrationDocumentByContact": {
		"ruleType": BusinessRuleModule.enums.RuleType.FILTRATION,
		"autocomplete": true,
		"autoClean": true,
		"baseAttributePatch": "Account",
		"comparisonType": Terrasoft.ComparisonType.EQUAL,
		"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		"attribute": "Account"
	},
	"FiltrationDocumentByOpportunity": {
		"ruleType": BusinessRuleModule.enums.RuleType.FILTRATION,
		"autocomplete": true,
		"autoClean": true,
		"baseAttributePatch": "Account",
		"comparisonType": Terrasoft.ComparisonType.EQUAL,
		"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		"attribute": "Account"
	}
}

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

А если вместо правила надо вписать attributes с lookupListConfig, то у бизнес-правила всё равно приоритет выше :(
Как удалить бизнес-правило, чтобы срабатывал attributes?

Здравствуйте, Владимир!

Попробуйте следующий вариант:

getFilters: function() {
       var filters = this.callParent(arguments);
       filters.removeByKey("FiltrationDocumentByOpportunity");
       return filters;
}

спасибо, работает!

Кстати, только мне кажется нелогичным то, что в bpm есть отличная деталь ContactCareer, а повсюду Контакт фильтруется не по записям этой детали, а по полю Контрагент?

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

ContactCareer - развязочная таблица. У одного контакта может быть несколько работ. По этой причине не совсем логично фильтровать именно по этой таблице.

"Демьяник Алексей" написал:ContactCareer - развязочная таблица. У одного контакта может быть несколько работ. По этой причине не совсем логично фильтровать именно по этой таблице.

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

"Владимир Соколов" написал:

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

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

В таком случае, можно отключить базовые правила:smile:

"Демьяник Алексей" написал:Попробуйте следующий вариант:
getFilters: function() {
       var filters = this.callParent(arguments);
       filters.removeByKey("FiltrationDocumentByOpportunity");
       return filters;
}

знаете, как-то я поспешил... не работает это. поставил debugger - вижу, что функция getFilters совсем не вызывается

Здравствуйте, Владимир!

"Владимир Соколов" написал:

знаете, как-то я поспешил... не работает это. поставил debugger - вижу, что функция getFilters совсем не вызывается

Вы добавили данный код код в секцию methods: {}?

"Демьяник Алексей" написал:Вы добавили данный код код в секцию methods: {}?

Да. Он должен срабатывать при открытии карточки?

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

onEntityInitialized: function() {
   this.callParent(arguments);
   delete this.rules.Document.FiltrationDocumentByOpportunity;
   delete this.rules.Document.FiltrationDocumentByAccount;
   delete this.rules.Document.FiltrationDocumentByContact;
},

"Щиголь Максим" написал:delete this.rules.Document.FiltrationDocumentByOpportunity;

Как я понимаю, Document - это название поля.

В моём случае
this.callParent(arguments);
delete this.rules.Contact.FiltrationContactByAccount;

ошибок никаких не получил, но и правило не деактивизировалось...

Здравствуйте, Владимир! Попробуйте способ:

 

"#название правила#": {
    "ruleType": 999
}

 

"Демьяник Алексей" написал:Попробуйте способ, описанный в этом комментарии.

Да, так правило отключается. Вроде, всё работает правильно :)

Можно заносить в Knowledge base

Владимир Соколов пишет:

Да, так правило отключается. Вроде, всё работает правильно :)Можно заносить в Knowledge base

Можно где то увидеть решение?  Ссылка на комментарий по которому автор узнал решение не работает. В данной теме решение из комментария не продублировано.

Вот эта тема.

Добавить комментарий

Evgi1980 пишет:

Можно где то увидеть решение?  Ссылка на комментарий по которому автор узнал решение не работает. В данной теме решение из комментария не продублировано.

 

//Удаление\отключение бизнес правил:
"#название правила#": {
    "ruleType": 999
}
//Пример:
"Opportunity":{
   "FiltrationOpportunityByContact": {
       "ruleType": 999
   }
}

 

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

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

Создал деталь: Объект унаследован от базового (2 поля: связь с разделом, поле справочник), схема детали унаследована от "Базовая схема детали с реестром ( NUI )". Зарегестрировал ее в SysDetail, через мастер разделал добавил в раздел. Все работает.
Целью было создать деталь с редактируемым реестром, реализацию и зависимости смотрел в детали "Продукт в заказе", деталь отображается как обычная, видимо что то упустил.

Что нужно сделать что бы создать деталь с редактируемым реестром?

Нравится

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

"Продукт в заказе" (ContractProductDetailV2) обычная деталь с реестром и парой дополнительных методов для пересчета суммы, в которой возможность редактировать объект детали реализована в отдельной, ее собственной карточке, по нажатию кнопки "изменить", как собственно и в большинстве деталей.

Деталь с редактируемым реестром это сложная разработка примером которой является деталь "Деталь графика поставок и оплат" (SupplyPaymentDetailV2), и ее вспомогательные схемы в пакете "Passport".

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

P.S.
Всю информацию по использованию мастеров и дизайнеров вы можете найти в SDK
http://academy.terrasoft.ru/documents/?product=SDK&ver=7.6.0

Нет, вопрос в том "Как создать деталь с редактируемым реестром?" с обычными деталями проблем нет и про изменить я ничего не писал, страницу регестрировал что бы проверить работает ли сама деталь, потом ее удалил (и из БД) так как нужна именно деталь с редактируемым реестром.
Так подскажите как создать деталь с редактируемым реестром? На примере детали "Продукт в заказе" (смотрел в omnichanel) не разобрался.

С версии продукта и стоило начинать, да, в omnichanel эту деталь сделали редактируемой.
Для того, чтобы сделать реестр детали редактируемым, в соответствующей схеме необходимо:
- добавить зависимости от модулей ConfigurationGrid (Конфигурационный реестр), ConfigurationGridGenerator, ConfigurationGridUtilities,
- подключить "миксин" ConfigurationGridUtilites,
- установить аттрибут IsEditable в значение true
- базовому реестру указать свойства:
className: "Terrasoft.ConfigurationGrid",
generator: "ConfigurationGridGenerator.generatePartial",
generateControlsConfig: {bindTo: "generateActiveRowControlsConfig"},
changeRow: {bindTo: "changeRow"},
unSelectRow: {bindTo: "unSelectRow"},
onGridClick: {bindTo: "onGridClick"},
initActiveRowKeyMap: {bindTo: "initActiveRowKeyMap"},
для добавления действий активной записи добавить:
activeRowActions: [...],
activeRowAction: {bindTo: "onActiveRowAction"}

Зависимости нужно указать не только параметром requirejs но и в настройках схемы, в конфигураторе.
Итоговый код простейшей редактируемой детали будет выглядеть следующим образом:

define("UsrSchema1Detail", ["ConfigurationGrid", "ConfigurationGridGenerator",
		"ConfigurationGridUtilities"], function() {
	return {
		entitySchemaName: "Contact",
		attributes: {
			"IsEditable": {
				dataValueType: Terrasoft.DataValueType.BOOLEAN,
				type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				value: true
			}
		},
		details: {},
		diff: [
				{
					"operation": "merge",
					"name": "DataGrid",
					"values": {
						"className": "Terrasoft.ConfigurationGrid",
						"generator": "ConfigurationGridGenerator.generatePartial",
						"generateControlsConfig": {"bindTo": "generatActiveRowControlsConfig"},
						"changeRow": {"bindTo": "changeRow"},
						"unSelectRow": {"bindTo": "unSelectRow"},
						"onGridClick": {"bindTo": "onGridClick"},
						"activeRowActions": [
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "save",
								"markerValue": "save",
								"imageConfig": {"bindTo": "Resources.Images.SaveIcon"}
							},
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "cancel",
								"markerValue": "cancel",
								"imageConfig": {"bindTo": "Resources.Images.CancelIcon"}
							},
							{
								"className": "Terrasoft.Button",
								"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
								"tag": "remove",
								"markerValue": "remove",
								"imageConfig": {"bindTo": "Resources.Images.RemoveIcon"}
							}
						],
						"initActiveRowKeyMap": {"bindTo": "initActiveRowKeyMap"},
						"activeRowAction": {"bindTo": "onActiveRowAction"},
						"multiSelect": false
					}
				}
			],
		mixins: {
			ConfigurationGridUtilites: "Terrasoft.ConfigurationGridUtilities",
			OrderUtilities: "Terrasoft.OrderUtilities"
		},
		methods: {}
	};
});

Максим, спасибо, получилось.

"Щиголь Максим" написал:

Здравствуйте, Максим. Подскажите пожалуйста в процессе к детали нужно просто вписать код и всё она заработает, конечно изменив при этом версию схемы детали? Просто в программировании не разбираюсь, пока что. Создал деталь и у неё реестр должен быть редактированным. По возможности схожим с деталью график поставок и оплаты.
Версия bpm'online sales enterprise 7.6

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

В общем, да, алгоритм достаточно прост, но знания по разработке в bpm'online все же понадобятся. Хотя бы на уровне реализации более простых кейсов из академии. Если в процессе реализации у вас возникнут другие вопросы, пишите, постараемся ответить.

"Щиголь Максим" написал:

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

Как минимум на строчке

entitySchemaName: "Contact",

вместо контакта, вам нужно будет указать ваш объект, на основе которого сделана схема вашей детали.

В общем, да, алгоритм достаточно прост, но знания по разработке в bpm'online все же понадобятся. Хотя бы на уровне реализации более простых кейсов из академии. Если в процессе реализации у вас возникнут другие вопросы, пишите, постараемся ответить.


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

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

define("LeadProductDetailV2", ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities", "configurationEnums"],
function(configurationEnums, ConfigurationGrid, ConfigurationGridGenerator, ConfigurationGridUtilities) {
return {
entitySchemaName: "LeadProduct",
attributes: {
"IsEditable": {
dataValueType: Terrasoft.DataValueType.BOOLEAN,
type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
value: true
}
},
details: {},
diff: [
{
"operation": "merge",
"name": "DataGrid",
"values": {
"className": "Terrasoft.ConfigurationGrid",
"generator": "ConfigurationGridGenerator.generatePartial",
"generateControlsConfig": {"bindTo": "generatActiveRowControlsConfig"},
"changeRow": {"bindTo": "changeRow"},
"unSelectRow": {"bindTo": "unSelectRow"},
"onGridClick": {"bindTo": "onGridClick"},
"activeRowActions": [
{
"className": "Terrasoft.Button",
"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
"tag": "save",
"markerValue": "save",
"imageConfig": {"bindTo": "Resources.Images.SaveIcon"}
},
{
"className": "Terrasoft.Button",
"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
"tag": "cancel",
"markerValue": "cancel",
"imageConfig": {"bindTo": "Resources.Images.CancelIcon"}
},
{
"className": "Terrasoft.Button",
"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
"tag": "remove",
"markerValue": "remove",
"imageConfig": {"bindTo": "Resources.Images.RemoveIcon"}
}
],
"initActiveRowKeyMap": {"bindTo": "initActiveRowKeyMap"},
"activeRowAction": {"bindTo": "onActiveRowAction"},
"multiSelect": false
}
}
],
mixins: {
ConfigurationGridUtilites: "Terrasoft.ConfigurationGridUtilities",
OrderUtilities: "Terrasoft.OrderUtilities"
},
//данный кусочек был добавлен:smile:
methods: {
/**
* Возвращает колонки, которые всегда выбираются запросом
* @return {Object} Возвращает массив объектов-конфигураций колонок
*/
getGridDataColumns: function() {
return {
"Id": {path: "Id"},
"Product": {path: "Product"},
"Product.Name": {path: "Product.Name"}
};
},

/**
* Открывает справочник продуктов
* @private
*/
openProductLookup: function() {
var config = {
entitySchemaName: "Product",
multiSelect: true,
columns: ["Name", "Price", "Currency"]
};
var leadId = this.get("MasterRecordId");
if (this.Ext.isEmpty(leadId)) {
return;
}
var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: this.entitySchemaName
});
esq.addColumn("Id");
esq.addColumn("Product.Id", "ProductId");
esq.filters.add("filterLead", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL, "Lead", leadId));
esq.getEntityCollection(function(result) {
var existsProductsCollection = [];
if (result.success) {
result.collection.each(function(item) {
existsProductsCollection.push(item.get("ProductId"));
});
}
if (existsProductsCollection.length > 0) {
var existsFilter = this.Terrasoft.createColumnInFilterWithParameters("Id",
existsProductsCollection);
existsFilter.comparisonType = this.Terrasoft.ComparisonType.NOT_EQUAL;
existsFilter.Name = "existsFilter";
config.filters = existsFilter;
}
this.openLookup(config, this.addCallBack, this);
}, this);
},

/**
* @overridden
*/
onCardSaved: function() {
this.openProductLookup();
},

/*
* Открывает справочник продуктов в случае если карточка лида была ранее сохранена
* @overridden
* */
addRecord: function() {
var masterCardState = this.sandbox.publish("GetCardState", null, [this.sandbox.id]);
var isNewRecord = (masterCardState.state === configurationEnums.CardStateV2.ADD ||
masterCardState.state === configurationEnums.CardStateV2.COPY);
if (isNewRecord === true) {
var args = {
isSilent: true,
messageTags: [this.sandbox.id]
};
this.sandbox.publish("SaveRecord", args, [this.sandbox.id]);
return;
}
this.openProductLookup();
},

/*
* Добавление выбраных продуктов
* @private
* */
addCallBack: function(args) {
var bq = this.Ext.create("Terrasoft.BatchQuery");
var leadId = this.get("MasterRecordId");
this.selectedRows = args.selectedRows.getItems();
this.selectedItems = [];
this.selectedRows.forEach(function(item) {
item.LeadId = leadId;
item.ProductId = item.value;
bq.add(this.getProductInsertQuery(item));
this.selectedItems.push(item.value);
}, this);
if (bq.queries.length) {
this.showBodyMask.call(this);
bq.execute(this.onProductInsert, this);
}
},

/*
* Возвращает запрос на добавление продукта
* @param item {Object} идентификатор лида и выбранный в справочнике продукт {LeadId, value}
* @private
* */
getProductInsertQuery: function(item) {
var insert = Ext.create("Terrasoft.InsertQuery", {
rootSchemaName: this.entitySchemaName
});
insert.setParameterValue("Lead", item.LeadId, this.Terrasoft.DataValueType.GUID);
insert.setParameterValue("Product", item.ProductId, this.Terrasoft.DataValueType.GUID);
return insert;
},

/*
* Загрузка добавленых продуктов в реестр
* @private
* */
onProductInsert: function(response) {
this.hideBodyMask.call(this);
this.beforeLoadGridData();
var filterCollection = [];
response.queryResults.forEach(function(item) {
filterCollection.push(item.id);
});
var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: 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);
},

/*
* Удаление выбранных записей
* @overridden
* */
deleteRecords: function() {
var selectedRows = this.getSelectedItems();
if (selectedRows.length > 0) {
this.set("SelectedRows", selectedRows);
this.callParent(arguments);
}
},

/**
* @inheritdoc Terrasoft.BaseGridDetailV2#getCopyRecordMenuItem
* @overridden
*/
getCopyRecordMenuItem: Terrasoft.emptyFn,

/**
* @inheritdoc Terrasoft.BaseGridDetailV2#getEditRecordMenuItem
* @overridden
*/
getEditRecordMenuItem: Terrasoft.emptyFn,

/**
* @inheritdoc Terrasoft.GridUtilitiesV2#getFilterDefaultColumnName
* @overridden
*/
getFilterDefaultColumnName: function() {
return "Product";
}
},
diff: /**SCHEMA_DIFF*/[
{
"operation": "merge",
"name": "DataGrid",
"values": {
"rowDataItemMarkerColumnName": "Product"
}
},
{
"operation": "merge",
"name": "AddRecordButton",
"values": {
"visible": {"bindTo": "getToolsVisible"}
}
}
]/**SCHEMA_DIFF*/
};
}
);

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

Во вторых миксин OrderUtilities: "Terrasoft.OrderUtilities" тут наверно лишний.
Вот у меня получилось в лидах сделать эту деталь редактируемой, почитайте:

define("LeadProductDetailV2", ["ConfigurationEnums", "ConfigurationGrid", "ConfigurationGridGenerator",
		"ConfigurationGridUtilities"],
	function(configurationEnums) {
		return {
			entitySchemaName: "LeadProduct",
			methods: {
			},
			mixins: {
				ConfigurationGridUtilites: "Terrasoft.ConfigurationGridUtilities"
			},
			attributes: {
         		"IsEditable": {
            	dataValueType: Terrasoft.DataValueType.BOOLEAN,
            	type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            	value: true
         		}
      		},
			diff: /**SCHEMA_DIFF*/[
		{
            "operation": "merge",
            "name": "DataGrid",
            "values": {
               "className": "Terrasoft.ConfigurationGrid",
               "generator": "ConfigurationGridGenerator.generatePartial",
               "generateControlsConfig": {"bindTo": "generatActiveRowControlsConfig"},
               "changeRow": {"bindTo": "changeRow"},
               "unSelectRow": {"bindTo": "unSelectRow"},
               "onGridClick": {"bindTo": "onGridClick"},
               "activeRowActions": [
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "save",
                     "markerValue": "save",
                     "imageConfig": {"bindTo": "Resources.Images.SaveIcon"}
                  },
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "cancel",
                     "markerValue": "cancel",
                     "imageConfig": {"bindTo": "Resources.Images.CancelIcon"}
                  },
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "remove",
                     "markerValue": "remove",
                     "imageConfig": {"bindTo": "Resources.Images.RemoveIcon"}
                  }
               ],
               "initActiveRowKeyMap": {"bindTo": "initActiveRowKeyMap"},
               "activeRowAction": {"bindTo": "onActiveRowAction"},
               "multiSelect": false
            }
         }
			]/**SCHEMA_DIFF*/
		};
	}
);

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

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

Вам необходимо корректно связать деталь с разделом:
В Вашем случае, необходимо, что бы в значении "Колонка детали" была выбрана колонка справочного типа "Контакт"

подробнее про добавление детали по ссылке:
http://academy.terrasoft.ru/documents/docs/product/bpm'online%20sales/t…

создание детали:
http://academy.terrasoft.ru/documents/docs/product/bpm'online%20sales/t…

Это мне нужно создать новую деталь? Просто в "Колонка детали" нету "Контакт"...

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

"Липатов Юрий Сергеевич" написал:

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

Не совсем понимаю про какой обьект детали идет речь? Можете написать более детальнее?

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

"Липатов Юрий Сергеевич" написал:

создание детали:

http://academy.terrasoft.ru/documents/docs/product/bpm'online%20sales/team/7.7.0/BPMonlineHelp/chapter_detail_wizard/chapter_detail_wizard.htm

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

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

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

Подскажите пожалуйста как реализовать вышеописанное.

Нравится

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

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

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

Нравится

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

Подскажите какое всплывающее окно вы имеете в виду, по какому действию оно появляется? Желательно со скриншотом.

Скрин в приложении

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

Вам необходимо заместить SimpleTaskAddModule. Но копирование кода - это некорректное замещение.
В замещающем клиентском модуле Вам необходимо через разметку добавить одно поле. Для добавления поля используйте пример с Академии.

Не совсем так, схемы можно расширять или менять логику частично, при замещении же модуля вам необходимо воссоздать всю его логику.
1. Убедитесь чтобы ваш пакет куда вы добавляете замещающий модуль был выше по иерархии зависимости чем пакет UIv2.
2. В замещающем модуле после указания родительского, нужно воссоздать все "сообщения", а так же строки и картинки, строкам и картинкам дав новые названия, к примеру с приставкой "New", а так же поменять старые названия ресурсов на новые в коде модуля.
3. Так же необходимо скопировать стили с закладки LESS, они у этого модуля есть.

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

1

2

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

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

При попытке интеграции с MS Exchange возникла ошибка на этапе настройки синхронизации с почтовым ящиком. При сохранении новой настройки выдает ошибку: "Базовое соединение закрыто: Не удалось установить доверительные отношения для защищенного канала SSL/TLS".

Нравится

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

Здравствуйте, Никита!

Вам необходимо установить в системной настройке "Игнорировать некорректные сертификаты сервера Exchange" признак true и повторно выполнить настройку почтового ящика.

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

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

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

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

В приложение снимок с тем что я подразумеваю под карточкой и реестром.

Нравится

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

По данному вопросу есть статья на SDK - http://academy.terrasoft.ru/documents/docs/technic/SDK/7.6.0/CreateMast…

Также прикрепил пример создание данного справочник
dvuhurovnevyyspravochnik.doc

"Мотков Илья" написал:

По данному вопросу есть статья на SDK - http://academy.terrasoft.ru/documents/docs/technic/SDK/7.6.0/CreateMaste...

Также прикрепил пример создание данного справочник

dvuhurovnevyyspravochnik.doc


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

Добрый день!

Выполните update записи в SysLookup.

Колонка - SysGridPageSchemaUId.

Вы можете взять за пример уже существующий справочник - "Результаты активностей по категориям" и зарегистрировать собственный по аналогии.

"Безродный Андрей" написал:

Добрый день!

Выполните update записи в SysLookup.

Колонка - SysGridPageSchemaUId.

Вы можете взять за пример уже существующий справочник - "Результаты активностей по категориям" и зарегистрировать собственный по аналогии.

Спасибо. Добавил запись в таблицу SysLookup, Id добавленной записи поместил в колонку SysLookupId таблицы Lookup записи справочника зарегестрированного через раздел "Справочники" и все заработало.

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

Здравствуйте. У меня схожая проблема. Нужно сделать справочник в котором есть доп поля. А стандартная страница редактирования позволяет оперировать только полями название и описание.
Вот хотелось бы сделать чтобы при клике на кнопку "открыть наполнение" или на заголовок справочника в списке справочников открывалась типа такой страницы

Страницу(PageSchemaManager) в конфигураторе уже создал. но как сделать чтобы она открывалась в нужном месте?
Кстати. из примера на скрине в свойствах справочника "Стадии продаж" поле Страница реестра пустой:confused:

Здравствуйте.
Нет необходимости изменять PageSchemaManager.
Вам необходимо создать "страницу" справочника и унаследовать её от "Базовая страница справочника" и указать её в свойствах справочника как страницу реестра.

у меня не появляется моя страница в выборе "страница реестра". а сделать так
"Выполните update записи в SysLookup." не могу, так как нет доступа к базе.. что можно сделать?

Дмитрий, здравствуйте.

Есть 2 варианта как это можно сделать:
1) Вы можете сообщить в техническую поддержку какие идентификаторы схем Вам необходимо узнать и, с полученной информацией, выполнить запрос через [SQL Сценарии]

2) Так же, Вы можете запросить анонимизированную копию базы, и самим узнать необходимые Вам данные. А далее, все так же, выполнить запрос через [SQL Сценарии].

Теперь. Сделал как сказано выше.

"Дашкевич К." написал:

Спасибо. Добавил запись в таблицу SysLookup, Id добавленной записи поместил в колонку SysLookupId таблицы Lookup записи справочника зарегестрированного через раздел "Справочники" и все заработало.

Страница справочника стала открываться.

Но при нажатии на кнопку добавить открывается новая страница с такой ошибкой.

Exception Message: Object reference not set to an instance of an object.
Exception Type: System.NullReferenceException
Exception Source: Terrasoft.WebApp
 
Exception Stack Trace:
   at Terrasoft.WebApp.ViewPage.get_UId()
   at Terrasoft.UI.WebControls.Page.InitializeProfile(ProfileKeyEventArgs e, Boolean forceInit)
   at Terrasoft.WebApp.ViewPage.OnInitComplete(EventArgs e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
 
SessionID: fgg0y2gegvcer3vclyuuv1fp
Request URL: /0/ViewPage.aspx?Id=00000000000000000000000000000000&recordId=00000000-0000-0000-0000-000000000000&entitySchemaUId=84cf4e7e-4615-4211-ac78-34ff81008182&treeGridId=PageContainer_TreeGrid&SysModuleEditId=00000000-0000-0000-0000-000000000000&folderId=
Request Path: /0/ViewPage.aspx
Request UrlReferrer: https://omega.bpmonline.com/0/ViewPage.aspx?editMode=true&Id=63b42d80-5585-4b6a-9617-f747e4b2f314
Request Type: GET
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0
User Host Address: 213.5.130.62
User: Supervisor
Is Authenticated: True
Authentication Type: Forms
Is Secure Connection: True
 
Application Version: 7.5.0.1007

Попробовал что пишут на форуме. но в моем случае не помогло
http://www.community.terrasoft.ru/forum/topic/12438

Запись, связанная с данным справочником в таблице [SysLookup] выглядит следующим образом

Дмитрий, в схеме реестры нужно добавить событие Init страницы

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

EditPageUId = new Guid("6f58a076-d374-4a27-a451-b29595b05be9");
return true;

Uid нужно взять из метаданных схемы страницы редактирования (Дополнительно - Открыть метаданные).

Спасибо)

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

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

Создал замещающую схему страницы BaseProjectPageV2, ее код ниже. При добавление записи действие работает нормально, но при редактирование записи пропадает подпись и не вызывается функция, в консоле появляется ошибка "Uncaught TypeError: Cannot read property 'apply' of undefined". Пробовал замещать ProjectPageV2, такая же ошибка, в разделе действие добавленное таким способом работает корректно.
В чем может быть проблема?
BPM Sales + Marketing Версия 7.6.0.996

Код замещающей схемы:

define("BaseProjectPageV2", [], function() {
        return {
                entitySchemaName: "Project",
                attributes: {},
                messages: {},
                details: /**SCHEMA_DETAILS*/{}, /**SCHEMA_DETAILS*/
                methods: {
                        getActions: function() {
                                var actionMenuItems = this.callParent(arguments);
                                actionMenuItems.addItem(this.getActionsMenuItem({
                                        "Caption": {"bindTo": "Resources.Strings.ProjectActivityImportCaption"},
                                        "Click": {"bindTo": "openProjectActivityImportSetting"},
                                        "Enabled": true
                                }));
                                return actionMenuItems;
                        },
                        openProjectActivityImportSetting: function() {
                                console.log("click");
                        }
                },
                diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
        };
});

Нравится

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

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

Делаю загрузку из Excel на основе стандартной загрузки, использую схему "Страница". Окно открываю кодом:

var url = this.Terrasoft.workspaceBaseUrl + "/ViewPage.aspx?Id=1ed4a6a8-e552-4678-a4f0-d829cb41d880";
window.open(url, "_blank", "height=" + "150" + ",width=" + "500");

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

Нравится

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

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

Уточните, пожалуйста, что Вы хотите реализовать? Желательно со скриншотами.

Снимок в приложение. Делал на основе стандартного импорта из Excel. С самим импортом проблем нет, выбираешь файл и проект в который нужно импортировать из справочника.
Вместо выбора проекта нужно передать его Id из страницы редактирования проекта. Окно открывается действием.

Мне кажется, можно в переменную url дописать вроде:

+"&ProjectId="+ProjectId;

А в открывшемся окне её вычитать как:

Guid ProjectId = new Guid(Page.Request.QueryString["ProjectId"]);

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

Мне кажется, можно в переменную url дописать вроде:

+"&ProjectId="+ProjectId;

А в открывшемся окне её вычитать как:

Guid ProjectId = new Guid(Page.Request.QueryString["ProjectId"]);

Спасибо, работает.

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