Как запустить бизнес процесс только по выделенной записи в реестре?

Нравится

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

http://www.community.terrasoft.ru/forum/topic/10554

Как пример можно посмотреть запуск процесса LeadManagement из реестра Лидов запускается по ИД (файл LeadSectionV2 пакета CoreLead)

/**
* Выполняет запуск процесса квалификации с точки его последней активности.
*/
executeQualificationProcess: function() {
var activeRow = this.getActiveRow();
var qualificationProcessId = activeRow.get("QualificationProcessId");
if (qualificationProcessId) {
ProcessModuleUtilities.continueExecuting(qualificationProcessId, this);
} else {
ProcessModuleUtilities.executeProcess({
"sysProcessName": "LeadManagement",
"parameters": {
"LeadId": this.getPrimaryColumnValue(),
"ManualLaunch": true
}
});
}},

Попытался создать, но почему-то не запускается, где я ошибаюсь?

{
    "operation": "insert",
    "name": "runActiveSaleButton",
    "parentName": "DataGrid",
    "propertyName": "activeRowActions",
    "values": {
        "className": "Terrasoft.Button",
        "style": Terrasoft.controls.ButtonEnums.style.GREEN,
        "classes": {"textClass": "actions-button-margin-right"},
        "click": {"bindTo": "runActiveSale"},
        "caption": "Активная продажа"
    }
}
runActiveSale: function() {
    //var AccountId = this.get('Id');
    var AccountId = this.getPrimaryColumnValue();
    var processArgs = {
        sysProcessName: 'ActiveSale',
        parameters: {
            AccountId: AccountId
        }
    };
    this.runProcess(processArgs.sysProcessName, processArgs.parameters, this);
}

Я так понял, что с версии 7.3 идет не click,а tag (у нас 7.5)
Даже добавил ProcessModuleUtilities
Но все равно не получается:

{
    "operation": "insert",
    "name": "runActiveSaleButton",
    "parentName": "DataGrid",
    "propertyName": "activeRowActions",
    "values": {
        "className": "Terrasoft.Button",
        "style": Terrasoft.controls.ButtonEnums.style.GREEN,
        "caption": "Активная продажа",
        "tag": "runActiveSale"
    }
}
runActiveSale: function() {
    //var AccountId = this.get('Id');
    var AccountId = this.getPrimaryColumnValue();
    var processArgs = {
        sysProcessName: 'ActiveSale',
        parameters: {
            AccountId: AccountId
        }
    };
    ProcessModuleUtilities.runProcess(processArgs.sysProcessName, processArgs.parameters, this);
}

Александр, пример реализации кнопки запуска процесса по активной записи в разделе Контакты (змещающая схема ContactSectionV2)

define("ContactSectionV2", ["ProcessModuleUtilities"], function(ProcessModuleUtilities) {
		return {
			entitySchemaName: "Contact",
			methods: {
				runProcess: function() {
					var activeRow = this.get("ActiveRow");
					var config = {
						sysProcessName: "MyProcess",
						parameters: {
							RecordId: activeRow
						}
					};
					ProcessModuleUtilities.executeProcess(config);
				},
				onActiveRowAction: function(buttonTag) {
					if (buttonTag === "runProcess") {
						this.runProcess();
					} else {
						this.callParent(arguments);
					}
				}
			},
			diff: /**SCHEMA_DIFF*/[{
				"operation": "insert",
				"name": "DataGridActiveRowQualificationProcessAction",
				"parentName": "DataGrid",
				"propertyName": "activeRowActions",
				"values": {
					"className": "Terrasoft.Button",
					"style": Terrasoft.controls.ButtonEnums.style.GREEN,
					"caption": "Run process",
					"tag": "runProcess"
				}
			}]/**SCHEMA_DIFF*/
		};
	}
);
Показать все комментарии

Здраствуйте! Подскажите пожалуйста как можно заместить базовый исходного код, например SearchDuplicatesService. Если указать в нем мой пакет Custom и публиковать, выдает ошибку "Для заданного локального пути не указан путь к хранилищу". На базе которая не подключена к SVN работало и опубликовало в Custom пакете.

Нравится

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

Добрый день, Владимир!

Прошу уточнить версию приложения, и четкий кейс действий. Так как, судя по тексту (если мы правильно поняли), Вы пытаетесь перенести схему из одного пакета, который под SVN в другой (Custom) который не под SVN. Это делать нельзя.

Версия 7.5.0.1122 entherprise. Тогда как можно грамотно переопределить метод getDuplicates() класса SearchDuplicatesService? Наследовать этот класс и переопределить метод getDuplicates() я не могу так как он не виртуальный.

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

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

Добрый день!
Версия Сервис-Деск Transitions 7.5.0.1138
Есть базовый календарь - время работы с понедельника по пятницу с 9.00 до 18.00
(обед с 13.00 до 14.00)
Создан сервисный договор по умолчанию, привязанный к базовому календарю.
В него добавлены сервисы.
Сроки разрешения и реакции всех сервисов указаны в рабочих часах,днях

При создании обращения время реакции и время разрешения рассчитываются БЕЗ учета базового календаря, без учета рабочих часов,дней.

Пример(см. вложение):
Сервис: время реакции - 4 рабочих часа, время разрешения - 2 рабочих дня

При создании обращения 27 мая в 16.07
план. реакция ставится 27 мая 21:00 и план. разрешение 29.05.2015 21:00
Хотя это не рабочее время по календарю.

С чем это может быть связано?

Нравится

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

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

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

Данная информация поможет нам предоставить Вам консультацию по этому вопросу.

Спасибо.

В базовом календаре указан пояс "GMT(время в формате)" (см. вложение)
Я нахожусь в часовом поясе, совпадающем с московским.

Добрый день, Дарья.
Вам необходимо установить часовой пояс, который соответствует вашему расположению, а именно GMT+3. После установки вашего пояса сроки должны считаться корректно, обратите внимание что проверять надо на новом обращении.
Скриншот с правильным поясом прилагаю.

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

Добрый день!

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

Сейчас знаю только реализацию через callback, например:

qetCity : function (stringValue, callback) {
        var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName : "Account"});
        esq.addColumn("Id");
        esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Id", account.value));
        esq.getEntityCollection(function (result) {
                if (result.success) {
                        var items = result.collection.getItems();
                        var City = [];
                        this.Terrasoft.each(items, function (item) {
                                City.push(item.get("Id"));
                        }, this);
                        callback.call(this, City);
                }
        }, this);
},
showCity : function () {
        this.qetCity("ASP; C++; C#", function (City) {
                var City = this.getIds("ASP; C++; C#", function (City);
        });
}

Нравится

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

Если речь про карточку или реестр (на основе базовых), то есть способы). А в общем случае, как я понимаю, нельзя - т.к. запрос-ответ, асинхронность и все такое.
Но если можно, тоже было бы интересно узнать, как.

"Андросов Дмитрий" написал:

Если речь про карточку или реестр (на основе базовых), то есть способы). А в общем случае, как я понимаю, нельзя - т.к. запрос-ответ, асинхронность и все такое.

Но если можно, тоже было бы интересно узнать, как.

А если о карточке, то какие есть способы?

Если это поле из текущего объекта (в карточке Контакта - Контакт)

this.get("КодПоля");

Если это справочное поле (в карточке Контакта - Контрагент)

//в атрибутах добавить/изменить атрибут этого справочника
"Account": {
	lookupListConfig:{
		//вроде бы влияет на данные, подтягиваемые из справочника при выборе
		columns: ["Country", "Owner"]
	},
	//вроде бы влияет на данные, подтягиваемые из справочника при открытии ранее сохраненной записи
	columns: ["Country", "Owner"]
}
 
// в методах получить можно будет так
var Account = this.get("Account");
if (Account && Account.value) {
	var Country = Account.Country;
	var Owner = Account.Owner;
}

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

"Андросов Дмитрий" написал:

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

Но, может, лучше разобраться с колбэками?

У меня итак уже один callback вложенный в другой. Еще одно вложение делать делать пока не очень хотелось бы...
Вариант с атрибутами тоже не подходит.

Возможно вам подойдет вариант через Entity

var AccountId = "..."; //GUID контрагента

var select = Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "Account"
});
select.addColumn('City.Name', 'CityName');
select.filters.add(select.createColumnFilterWithParameter(
Terrasoft.ComparisonType.EQUAL, "Id", AccountId, Terrasoft.DataValueType.TEXT));
select.getEntityCollection(function(result) {
if (result.success) {
var collection = result.collection;
collection.each(function(item) {
console.log(item.get("CityName")); !!! Ваши города
}, this);
}
}, this);

"Вильшанский Дмитрий" написал:вариант через Entity

хаха точно

"Вильшанский Дмитрий" написал:

Возможно вам подойдет вариант через Entity

var AccountId = "..."; //GUID контрагента

var select = Ext.create("Terrasoft.EntitySchemaQuery", {

rootSchemaName: "Account"

});

select.addColumn('City.Name', 'CityName');

select.filters.add(select.createColumnFilterWithParameter(

Terrasoft.ComparisonType.EQUAL, "Id", AccountId, Terrasoft.DataValueType.TEXT));

select.getEntityCollection(function(result) {

if (result.success) {

var collection = result.collection;

collection.each(function(item) {

console.log(item.get("CityName")); !!! Ваши города

}, this);

}

}, this);

Дмитрий, но в этом случае select.getEntityCollection(function(result) разве не является callback?

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

"Вильшанский Дмитрий" написал:

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

Понятно. Спасибо за информацию.

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

Как сделать агрегатирующий EntityShemaQuery запрос join по двум таблицам на клиенте (JavaScript)?

Нравится

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

Пример который выводит в консоль количество типов для контрагентов, имя которых содержит “111”

var select = Ext.create("Terrasoft.EntitySchemaQuery", {
                rootSchemaName: "Account"   
});
select.addColumn("Name");
select.addAggregationSchemaColumn("Type.Id", Terrasoft.AggregationType.COUNT, "Count");
select.filters.add(select.createColumnFilterWithParameter(
                Terrasoft.ComparisonType.CONTAIN, "Name", "111", Terrasoft.DataValueType.TEXT));
select.getEntityCollection(function(result) {
                if (result.success) {
                               var collection = result.collection;
                               collection.each(function(item) {
console.log(item.get("Name"));
                                               console.log(item.get("Count"));
                               }, this);
                }
}, this);

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

Скажите, это правильное поведение, что агрегирующий MAX запрос возвращает более одной записи?

Объясню бизнес-логику. Есть раздел "Vacancies", на ней есть деталь "Vacancy candidates", куда можно добавить 0 или более кандидатов на эту вакансию. У каждого кандидата есть лукап "Candidate status". В процессе работы с кандидатом он проходит определённые стадии в определённом порядке, поэтому каждая запись из соответствующей таблицы UsrCandStat содержит целочисленную колонку "Value", где хранится число, определяющее эту стадию, и "StatusName". Допустим, 10 стадий, 0 - нашли кандидата, 1 - связались с ним, 2 - кандидат послал своё резюме, ..., 9 - кандидат успешно прошел интервью с заказчиком, 10 - кандидат взят на работу. В разделе "Vacancies" есть вычисляемое виртуальное поле, которое автоматически должно заполнятся "StatusName" того кандидата из списка кандидатов детали "Vacancy candidates", который прошел в своём нелёгком пути наиболее далеко, т.е. с максимальным значением "Value".

Допустим, в детали добавили 3 кандидата и у ВСЕХ заполнили поле "Candidate status". В этом случае всё более менее работает - возвращаются 3 записи, отсортированные по максимальному значению Value, т.е. можно взять элемент с индексом 0 и это и будет максимум. Хотя, опять же вопрос - почему 3, а не одна максимальная?

Ситуация похуже. В детали 3 кандидата, у 2х заполнили "Candidate status", а у третьего оставили пустым, допустим, поле необязательное. В итоге возвращаются 3 записи, при этом под индексом 0 будет запись с Value равным 0 и пустым "StatusName". Это корректное поведение? Как мне теперь найти запись с максимальным индексом? Искать Макс среди того, что вернул Макс?

Записал видео это всего:
youtube video

setUsrMostFarthestCandStatusVirtualValue: function ()
{
	var vacancyId = this.get("Id");;
	var esqCand = this.Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "UsrVacancyCandidates" });
	esqCand.addAggregationSchemaColumn("UsrCandStat.Value", Terrasoft.AggregationType.MAX, "Value");
	esqCand.addColumn("UsrCandStat.Name", "CandidateStatusName");
	esqCand.filters.add("ByUsrVacanciesFilter", this.Terrasoft.createColumnInFilterWithParameters("UsrVacancies", [ vacancyId ]));
	esqCand.getEntityCollection(function(response)
	{
		if (response.success)
		{
			var recruitmentStageNameWithMaxValue = "";
			var collection = response.collection;
			if (collection && collection.getCount() > 0)
			{
				Terrasoft.each(collection.getItems(), function(item) {
					console.log(item.get("CandidateStatusName") + ': ' + item.get("Value"));
				}, this);
				var recruitmentStageNameWithMaxValue = collection.getByIndex(0).get("CandidateStatusName");
			}
			this.set("UsrMostFarthestCandStatusVirtual", recruitmentStageNameWithMaxValue);
		}
	}, this);
},

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

Потому, что Вы формируете неправильный агрегированный запрос.
У Вас получается в итоге что-то на подобии этого:

Select MAX(Value), CandidateStatusName from 

А надо просто Select MAX(Value) from

Спасибо, Вы правы, протупил. Еще вопросы:
1. Если у Кандидата не выбран статус, то в "Value" (числовой тип) содержится 0, хотя я ожидаю, допустим, null или undefined, а 0 уже используется как индекс определённой стадии. Как это побороть? Хотя, как вариант, можно начинать индексацию стадий с 1, а значение 0 использовать как индикацию, что ничего не выбрано. Но всё же.
2. Почему запрос функция срабатывает несколько раз? Это сказывается на производительности. Как это исправить? Я вызываю её так, как Вы советовали

updateDetail: function(config) {
   config.reloadAll = true;
   this.callParent(arguments);
   this.setUsrMostFarthestCandStatusVirtualValue();
},

3. Я сделал виртуальное поле, куда записываю вычисленное значение. Как мне его сделать readonly?

Добавляю сокращенный код модуля / последовательность действий, пожалуйста, посмотрите, нельзя ли сделать оптимальней:

1. Добавил виртуальную (вычисляемую) колонку. Вопрос - Как сделать её readonly?

attributes:
{
	"UsrMostFarthestCandStatusVirtual":
	{
		type: Terrasoft.ViewModelColumnTypeVIRTUAL_COLUMN,
		referenceSchemaName: "UsrVacancies",
		dataValueType: Terrasoft.DataValueTypeTEXT,
		customConfig:
		{
			readonly: true // не работает
		},
	}
}

2. Связал с diff (разметка?). Вопрос - Как сделать её readonly? Кстати, колонка отобразилась в визуальном редакторе страницы на нужном месте, но, когда выделяешь её, пропадает кнопка "Edit". Так и надо?

{
	"operation": "insert",
	"name": "UsrMostFarthestCandStatusVirtual",
	"values":
	{
		"layout":
		{
			"column": 0,
			"row": 0,
			"colSpan": 12,
			"rowSpan": 1
		},
		"bindTo": "UsrMostFarthestCandStatusVirtual",
		"caption":
		{
			"bindTo": "Resources.Strings.UsrMostFarthestCandStatusVirtualCaption"
		},
		"textSize": 0,
		"contentType": 3,
		"labelConfig":
		{
			"visible": true
		},
		"enabled": true
	},
	"parentName": "group_gridLayout",
	"propertyName": "items",
	"index": 0
}

3. Создал функцию, которая вычисляет значение виртуальной колонки. Пришлось делать 2 EntitySchemaQuery запроса. Один - для получения макс значения Value, второй - для получения Name по уже известному макс значению Value. Вопросы - можно ли обойтись 1-м запросом? Почему метод вызывается несколько раз (см ниже)? Между переходом к другой вакансии и появлением значения в поле виртуальной колонки приходит около 2 секунд, что много.

setUsrMostFarthestCandStatusVirtualValue: function()
{
	var vacancyId = this.get("Id");;
	var esqCand = this.Ext.create("Terrasoft.EntitySchemaQuery",
	{
		rootSchemaName: "UsrVacancyCandidates"
	});
	esqCand.addAggregationSchemaColumn("UsrCandStat.Value", Terrasoft.AggregationType.MAX, "Value");
	esqCand.filters.add("ByUsrVacanciesFilter", this.Terrasoft.createColumnInFilterWithParameters("UsrVacancies", [vacancyId]));
	esqCand.getEntityCollection(function(response)
	{
		if (response.success)
		{
			var collection = response.collection;
			if (collection && collection.getCount() > 0)
			{
				var maxStageValue = collection.getByIndex(0).get("Value");
				if (maxStageValue === 0)
				{
					this.set("UsrMostFarthestCandStatusVirtual", "");
					return;
				}
				var esqCandStatName = this.Ext.create("Terrasoft.EntitySchemaQuery",
				{
					rootSchemaName: "UsrCandStat"
				});
				esqCandStatName.addColumn("Name", "StatusName");
				esqCandStatName.filters.add("ByValueFilter", this.Terrasoft.createColumnInFilterWithParameters("Value", [maxStageValue]));
				esqCandStatName.getEntityCollection(function(responseCandStatus)
				{
					var recruitmentStageNameWithMaxValue = "";
					if (responseCandStatus.success)
					{
						var candStatCollection = responseCandStatus.collection;
						if (candStatCollection && candStatCollection.getCount() > 0)
						{
							recruitmentStageNameWithMaxValue = candStatCollection.getByIndex(0).get("StatusName");
						}
						this.set("UsrMostFarthestCandStatusVirtual", recruitmentStageNameWithMaxValue);
					}
				}, this)
			}
		}
	}, this);
}

4. Дёргаю функцию на updateDetail событие, как вы и советовали. Почему-то она дергается несколько раз. Я вижу это в дебагере и в закладке Network инспектора. Как исправить?

updateDetail: function(config)
{
	config.reloadAll = true;
	this.callParent(arguments);
	this.setUsrMostFarthestCandStatusVirtualValue();
},

2. мастер разделов (если вы об этом) не рассчитан на редактирование нестандартных полей и не умеет это делать.
запрет редактирования поля

{
        "operation": "insert",
        "name": "UsrMostFarthestCandStatusVirtual",
        "values":
        {
                ...
                "enabled": false
        }
...

3. Т.к. вам важна скорость обновления значения (а основное время уходит не на SQL-запрос, а на общение между браузером, сервером и ядром) то рекомендую минимизировать запрос, для этого лучше всего имхо подойдет представление в БД (с Id вакансии и теми колонками, что вам нужны - я так понимаю это Имя кандидата) с использованием (на вскидку) cross join

Спасибо, звучит разумно. Правда нет ответа на вопрос, почему функция дёргается несколько раз, и нормально ли это.

"trickbz" написал:функция дёргается несколько раз, и нормально ли это.

с помощью метода updateDetail обновляются все детали (если не ошибаюсь, то в т.ч. и при их инициализации):

this.updateDetail({detail: "Название детали из блока details, например, Files"});

таким образом вам надо сделать так:

updateDetail: function(config) {
	if (config.detail && config.detail === "VacancyCandidates") { //проверьте имя
		config.reloadAll = true;
		this.callParent(arguments);
		this.setUsrMostFarthestCandStatusVirtualValue();
	} else {
		this.callParent(arguments);
	}
}

Спасибо большое за наводку, проверю! Мог бы сам догадаться добавить параметр в функцию и проинспектировать, или arguments в консоле написатЬ, но как то мозги отключаются по началу знакомства с BPM :)

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

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

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

Вам необходимо добавить обработчик ниже приведенного сообщения на вашей странице.

/**
* @message DetailChanged
* Срабатывает когда изменились данные на детали
*/
"DetailChanged": {
mode: this.Terrasoft.MessageMode.PTP,
direction: this.Terrasoft.MessageDirectionType.SUBSCRIBE
},

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

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

Пытаюсь использовать поле IsDefault для собственного раздела "Размещения" (Store). Это поле должно принимать значение true только для одной записи из таблицы Store. Естественно возникает вопрос где такую функциональность можно реализовать.
На вскидку у меня 3-и варианта:
1. Триггеры на уровне ms sql server
2. События объекта
3. События карточки редактирования

1 пункт мне не нравится :). 3 пункт на мой взгляд не реализуем.
Остается п. 2.
При реализации функциональности у меня возникло множество проблемы :).

1. Не очень хорошо понимаю как работать с результатами коллекции GetEntityCollection(UserConnection). В частности непонятно как получить значение любого поля из каждого экземпляра в коллекции. В отладчике вот такой вариант почему-то в столбце "Value" выдает ошибку:

entitys[0].GetTypedColumnValueGuid>("Id")

2. Каким образом я могу сделать Update для конкретной записи с фильтром по полю Id?
Заодно хотелось бы увидеть примеры использования и операций Insert и Delete (на будущее).

3. Есть ощущение, что я создам бесконечный цикл, если в объекте для события обновления записи выполню код по обновлению записи для этого же объекта. Как быть в этом случае?

4. Работая с отладчиком серверного кода я не вижу методы объектов. С чем это связано и как можно их отобразить в том объеме в котором они есть в sdk.

5. Где я могу найти класс Entity? Судя по sdk GetEntity() возвращает объект именно этого типа/класс. В sdk такого класса в Terrasoft.Core.Entitys нету (по крайней мере в версии 7.5.0).

6. У меня что-то с браузером? Я использую хром и в ветке "Библиотека классов ядра платформы" у меня постоянно какие-то зависания при раскрытии структуры. Кроме этого, я не понимаю как пользоваться поиском. Результаты его запросов всегда выполняют редирект не на конкретную страничку, а на главную страничку sdk. Так же заметил 2-а неприятных эффекта. Во-первых, при раскрытии структуры sdk размер левой части не подбирается под содержим, что в отдельных случаях не позволяет видеть полное название класс, перечисления и прочих полезных "штучек". Во-вторых контент "прыгает" в буквальном смысле и при раскрытии структуры и очень часто возникает ситуация когда нужно мотать вверх и вниз для того чтобы определить свое местоположение.

Нравится

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

Есть другое решение - создать системный параметр (System settings) DefaultStore, в который выбирать тот самый Store по умолчанию. Тогда не нужны проверки

Владимир, спасибо!

Очень помогли. Действительно перенос в системную переменную очень все упрощает.

Тем не менее все 6 вопросов актуальны.

1. После выполнения метода entitySchemaQuery.GetEntityCollection(UserConnection) формируется запрос к БД, возвращается коллекция объектов, которая содержит только те колонки, которые были заданы для entitySchemaQuery с помощью метода AddColumn(). Пример: entitySchemaQuery.AddColumn(entitySchema.PrimaryColumn.Name). Данный пример показывает, как добавить в запрос первичную колонку для entitySchema. Эквивалент - entitySchemaQuery.AddColumn("Id"), но запись entitySchema.PrimaryColumn.Name - корректней.

2.
Чтобы добавить запись, необходимо:
2.1 Получить менеджер

var entitySchemaManager = UserConnection.EntitySchemaManager;

2.2 Получить схему объекта

var entitySchema = entitySchemaManager.GetInstanceByName("Contact");

или

Guid entitySchemaUId = "0bff4bc9-1a80-42f8-aa43-628a031dc6c0";
var entitySchema = entitySchemaManager.GetInstanceByUId(entitySchemaUId);

2.3 Создать экзмепляр объекта

var entity = entitySchema.CreateEntity(UserConnection);

2.4 Заполнить колонки по умолчанию

entity.SetDefColumnValues();

2.5 Заполнить необходимые колонки (обычно это первичная колонка и первичная для отображения колонка)

entity.SetColumnValue(entitySchema.PrimaryColumn.Name, Guid.NewGuid());
entity.SetColumnValue(entitySchema.PrimaryDisplayColumn.Name, "New entity");

2.6 Вызвать сохранение записи

entity.Save();

Чтобы удалить запись, необходимо:
- Вызвать метод Delete()

entity.Delete();

Чтобы изменить запись, необходимо:
- Вызвать метод FetchFromDB()
Guid entityId = "0bff4bc9-1a80-42f8-aa43-628a031dc6c0";
entity.FetchFromDB(entityId);
- Если метод вернет true, то запись присутствует в БД и в entity запишиться вся информация из записи.

3. В таком случае нужно выполнить обновление только необходимых полей объекта.

4. Если Вы имеете ввиду отладчик в Visual Studio и серверный код в конфигурации, то причина в том, что такой серверный код является автогенерируемый и не входит не в один проект.

5. SDK находится в процессе разработки. Спасибо, что обратили внимание на отсутствия класса Entity. Он будет добавлен в ближайшее время.

6. SDK находится в процессе разработки и постоянно развивается поэтому могут возникнут сложности при работе.

Немного добавлю

"Березкин Геннадий" написал:В частности непонятно как получить значение любого поля из каждого экземпляра в коллекции.

  EntitySchema schema = UserConnection.EntitySchemaManager.GetInstanceByName("Contact");
    EntitySchemaQuery esq = new EntitySchemaQuery(schema);
    esq.AddAllSchemaColumns();
//Фильтр для таблицы
    esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Name", "FilterName"));
    EntityCollection entities = esq.GetEntityCollection(UserConnection);
//перебираем все записи коллекции, полученной в запросе
    foreach (Entity entity in entities)
    {
        //установить значение
        entity.SetColumnValue("Name", "NewName");
        //получить значение колонки Name
        entity.GetTypedColumnValue<string>("Name");
        //Сохраняем, при необходимости
        entity.Save();
    }

Спасибо за помощь.

Я не совсем понял с

entity.FetchFromDB(entityId);

Save() и Delete() помечают, что запись подлежат либо обновлению, либо удалению соответственно? FetchFromDB(entityId) - это запуск соответствующего запроса?
И еще вопрос. Как в entitys добавить запись?

entity.FetchFromDB(entityId) Возвращает true, если запись с указанным Id найдена в БД. В entity приходит вся информация из записи БД. Если пришло false, значит запись с таким Id не найдена.

Save() - сразу сохраняет entity в БД.
Delete() - сразу удаляет entity из БД.

В общем случае запись добавляется по указанной EntitySchema. Чтобы добавить запись достаточно получить EntitySchema этого объекта. Затем необходимо создать entity.
var entity = entitySchema.CreateEntity(UserConnection);
Для entity вызвать метод Save.
entity.Save();

Если необходимо просто добавить экземпляр в коллекцию, то можно воспользоваться методом AddLast для entityCollection. В него передать entity

Спасибо за помощь. Разобрался!

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

Добрый день!
Возникла следующая проблема:
При переходе на активность из напоминания не отображаются результаты активности из БП, только при выборе данной активности из раздела.



Так же не отображается вопрос пользователю, только сама активность.




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

Нравится

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

Данное поведение встречается на сборке 7.3.0.2567. Для исправления необходимо обновление на более позднюю сборку.

Добрый день!

Перенесли конфигурацию на последнюю сборку 7.3.0.3856, изменений нет -
"Результатов активности" из напоминания нет.

В чем, как вы думаете, заключается данная проблема, если не в сборке?

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

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

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

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

Нравится

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

Дарья, добрый день.
Функционал запрашиваемый вами реализован в схеме BaseProductDetailPageV2, в методе SetTotalAmount.
Спасибо.

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

Дарья, добрый день.
Данная схема находится в пакете UIv2.
Спасибо.

спасибо, такой метод в схеме, которая находится в пакете UIv2, увидела. Посмотрю

Добрый день! Это не совсем то.
Насколько я поняла, этот метод считает сумму конкретного продукта в счете на основании цены, налога и т.п.
Я имела в виду другое:
В стандартной версии при добавлении продукта в счет и изменения его цены, кол-ва и т.п. происходит автоматический пересчет общей суммы счета. ( не продукта в счета, а самой суммы счета).
Где это реализовано - в каких схемах,пакетах?

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

Дарья, добрый вечер.
Высылаю код расчета общей суммы счета:

decimal sumTotalAmount = 0;
decimal sumPrimaryTotalAmount = 0;
var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "InvoiceProduct");
var totalAmountColumn = esq.AddColumn("TotalAmount");
var primaryTotalAmountColumn = esq.AddColumn("PrimaryTotalAmount");
var invoiceId = this.Entity.GetTypedColumnValue("InvoiceId");
esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Invoice", invoiceId));
var entityCollection = esq.GetEntityCollection(this.UserConnection);
if (entityCollection.Count > 0) {
foreach(var entity in entityCollection) {
sumTotalAmount += entity.GetTypedColumnValue(totalAmountColumn.Name);
sumPrimaryTotalAmount += entity.GetTypedColumnValue(primaryTotalAmountColumn.Name);
}
}
var update = new Update(context.UserConnection, "Invoice")
.Set("Amount",Column.Parameter(sumTotalAmount))
.Set("PrimaryAmount",Column.Parameter(sumPrimaryTotalAmount))
.Where("Id").IsEqual(Column.Parameter(invoiceId)) as Update;
update.Execute();

Версия 7.5.0.1122 omichannel
А в какой все-таки схеме данный код находится?

Дарья, данный код находится в схеме InvoiceProduct, в пакете Invoice.
Спасибо.

Показать все комментарии
действие
запуск
процесс
Технические вопросы
7.x

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

Реализация - в прикрепленном в файле

Нравится

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

Используемый метод showGrafInfo должен выглядеть следующим образом:

showGrafInfo: function() {
var processArgs = {
sysProcessName: "ProcessGrafShip",
parameters: {
}
};
ProcessModuleUtilities.executeProcess (processArgs);
},

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

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

Активности с типом «E-mail» отображаются в разделе «Активности».
Если у Вас настроена интеграция с почтой и Вы хотите найти входящие письма, рекомендуем воспользоваться возможностями фильтрации в системе.
Рассмотрим пример создания динамической группы, в которой установим необходимые условия фильтрации.
ПРИМЕЧАНИЕ! Вы также можете использовать быстрые фильтры реестра или расширенный блок фильтрации для поиска входящей почты без создания группы.
1. В разделе Активности в преднастроенной группе Email Создайте группу с названием «Входящие»:

2. В данной группе добавьте условие «Тип сообщения = Входящие» и сохраните изменения:

Теперь при выборе данной группы в дереве групп Вы всегда получите быстрый доступ к входящим Email сообщениям.

Нравится

Поделиться

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

Еще бы как-то отметить, по каким письмам не было ответа. И если ответа не было, то указана причина, почему. То есть, признак, что письмо обработанно, а не просто получено и просмотрено

Владимир, можно добавить поле "Обработано" логического типа и автоматически заполнять его при нажатии на кнопку "Ответить".
Затем на основании данного признака настроить динамическую группу для отслеживания статуса обработки писем.

"Бондарь Наталия" написал:автоматически заполнять его при нажатии на кнопку "Ответить".

А можно не при нажатии на кнопку "Ответить", а при отправлении ответного письма? То есть, связывать письма между собой?

Владимир, вы можете добавить новые поля, как предлагала пользователь Бондарь Наталия, заполнять из и затем отфильтровывать.
Функционал, который Вы запрашиваете на данный момент отсутствует. Подобный функционал можно реализовать через добавление детали. Как пример можете посмотреть на деталь «Взаимосвязи» раздела «Контакты».

Также похожий функционал реализован в продукте ITIL при работе с инцидентами.

Добрый день. В нашей версии BPM почему-то есть преднастроенный фильтр email, настроена интеграция с почтой, а письма в разделе Активности не отображаются. Подскажите пожалуйста, почему? Где-то в 7.6 закрыли эту возможность? Но фильтр-то преднастроенный есть.
Письма отображаются только в панели и в деталях (объектов, с которыми они связаны).

"Гриценко Екатерина" написал:Где-то в 7.6 закрыли эту возможность?

Убрали их. Сделали хороший функционал работы со входящими письмами, но убрали хороший функционал по работе с письмами в реестре

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