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

 

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

 

1) Остановить процесс, внести изменения, запустить процесс - но в таком случае при остановке процесса будут сбиты процессы эскалации по текущим обращениям.

 

2) Не останавливая процесс, внести изменения, сохранить и опубликовать запрашиваемые системой параметры - но при таком способе тестовая система наглухо зависала во время "публикации" минуты на 3.

 

Как будет правильнее вносить изменения в БП на продуктивной среде?

Нравится

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

Руслан, это два разных вопроса:

 

1. В системе есть версионность процессов. Если вносятся изменения, старые запущенные экземпляры процессов доработают в старой версии. А новые будут уже с учётом исправлений.

 

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

 

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

Зверев Александр,  в данный момент в продуктивной системе 1485 обращений по которым эскалация либо уже идёт, либо теоретически может начаться. Поэтому сложно предугадать момент когда БП точно не будут отрабатывать. По 1-му пункту не знал, спасибо. Буду делать в нерабочее время с сохранением новой версии процессов.

В любом случае сервер когда-то останавливается на некоторое время: для обновления версии системы, каких-то работ на серверах IIS и БД и др. Если есть доступ к базе, увидеть, что происходит в системе на сервере, можно при помощи запросов на свежие записи в таблицах SysUserSession, SysProcessLog и SysProcessElementLog.

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

Использую для запуска БП ProcessModuleUtilities.executeProcess

Нужно подавить уведомление об успешном запуске.

Каким штатным образом это можно сделать? Параметр передать?

Нравится

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

Эта функция выглядит так:

/**
 * Launches business process by identifier or name.
 * @param {Object} config Configuration object.
 * @param {String} [config.sysProcessName] Name of the process schema.
 * @param {String} [config.sysProcessId] Unique identifier of the process schema.
 * @param {Object} [config.parameters] Process parameters.
 * @param {Function} [config.callback] Callback function.
 * @param {Object} [config.scope] Callback scope.
 */
executeProcess: function(config) {
	const callback = config.callback || this._executeProcessCallback.bind(this, config);
	const scope = config.scope || this;
	if (config.sysProcessName) {
		this._executeProcessByName(config, callback, scope);
	} else {
		this._executeProcessById(config, callback, scope);
	}
},

Она вызывает вторую, которая и показывает сообщение:

/**
 * @private
 */
_executeProcessCallback: function(config, request, success, response) {
	if (!this.responseCallback(request, success, response)) {
		this.loadSchemaCaptionByName(config.sysProcessName, function(caption) {
	this._showSuccessfullyRunProcessPopup(caption);
		}, this);
	}
},

Насколько понимаю, в первой вызов второй со стандартным обработчиком включается только если не передан свой.

То есть можно попробовать передать в параметре callback пустую функцию или с какими-то своими действиями. 

Пример вызова процесса с добавлением обработчика есть в схеме SystemDesigner, где он выглядит: 

/**
 * Starts OpportunityManagement actualization process.
 * @private
 */
runActualizeOpportunityManagementProcess: function(callback) {
	var processUtils = this.getProcessModuleUtilities();
	this.showBodyMask();
	processUtils.executeProcess({
		sysProcessName: "ActualizeOpportunityManagement",
		callback: function() {
			this.hideBodyMask();
			callback.call(this);
		},
		scope: this
	});
},

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

Эта функция выглядит так:

/**
 * Launches business process by identifier or name.
 * @param {Object} config Configuration object.
 * @param {String} [config.sysProcessName] Name of the process schema.
 * @param {String} [config.sysProcessId] Unique identifier of the process schema.
 * @param {Object} [config.parameters] Process parameters.
 * @param {Function} [config.callback] Callback function.
 * @param {Object} [config.scope] Callback scope.
 */
executeProcess: function(config) {
	const callback = config.callback || this._executeProcessCallback.bind(this, config);
	const scope = config.scope || this;
	if (config.sysProcessName) {
		this._executeProcessByName(config, callback, scope);
	} else {
		this._executeProcessById(config, callback, scope);
	}
},

Она вызывает вторую, которая и показывает сообщение:

/**
 * @private
 */
_executeProcessCallback: function(config, request, success, response) {
	if (!this.responseCallback(request, success, response)) {
		this.loadSchemaCaptionByName(config.sysProcessName, function(caption) {
	this._showSuccessfullyRunProcessPopup(caption);
		}, this);
	}
},

Насколько понимаю, в первой вызов второй со стандартным обработчиком включается только если не передан свой.

То есть можно попробовать передать в параметре callback пустую функцию или с какими-то своими действиями. 

Пример вызова процесса с добавлением обработчика есть в схеме SystemDesigner, где он выглядит: 

/**
 * Starts OpportunityManagement actualization process.
 * @private
 */
runActualizeOpportunityManagementProcess: function(callback) {
	var processUtils = this.getProcessModuleUtilities();
	this.showBodyMask();
	processUtils.executeProcess({
		sysProcessName: "ActualizeOpportunityManagement",
		callback: function() {
			this.hideBodyMask();
			callback.call(this);
		},
		scope: this
	});
},

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

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

Добрый день. В результате изучения моб. приложения. Столкнулись с рядом проблем. 

1) Можно, ли расставить сигналы таким образом?

https://i.imgur.com/nKBk78M.png.

2) Дело в том, что данный бизнес процесс связан с кейсом. А если запускается по сигналу, то можно увидеть что связь с кейсом пропадает. Как быть быть в данной ситуации???

https://i.imgur.com/oeQA186.png

3) Если такая модель бизнес-процесса подходит, то как избавиться от ошибок. Дело в том что бизнес процесс запускается на сайте. А дальше продолжение по сигналу через приложение. 

https://i.imgur.com/HMQYg7N.png

Первый процесс это продолжение через моб. версию. (Диаграмма выполнения: https://i.imgur.com/9ZxIBnH.png)

А второй с ошибкой это запуск через сайт. (Диаграмма выполнения: https://i.imgur.com/V2Ck5iR.png)

Нравится

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

Не совсем понимаю, что Вы хотите сделать в БП и причём тут мобильное приложение.

Само по себе мобильное не выполняет процессы, они запускаются на сайте, если происходят изменения в записи объекта, для которых в БП настроен сигнал. Если мобильное приложение работает оффлайн, то данные в основной системе добавятся или изменятся в момент синхронизации. 

Узнать больше о том, как выполнялись элементы БП и какие в этот момент были значения параметров, можно, включив трассировку.

Да спасибо я уже понял. Дело в том что  в мобильном приложении вносятся изменения в карточку способом: просто редактированием поля(без какого-либо подтверждения оно автоматически сохраняется, in-place редактирование). По этой причине некоторые бизнес-процессы не работали. Изменил немного логику

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

Привет коллеги!
 
Иногда требуется отловить плавающий кейс в работе процесса или "отладить" процесс без использования VisualStudio. Большинство проблем можно решить с помощью трассировки процесса. Но если проблема в коде написанном в скриптаске или методах процесса, то самый простой способ - это добавить логирование.

Для этого необходимо:
1) в Using добавить

global::Common.Logging

2) в коде использовать

var _log = LogManager.GetLogger("BusinessProcess");
var processName = "MyProcess"; //Название процесса для простого поиска логов
_log.DebugFormat(@"{0}: Process was started", processName); //Уровень логирования Debug
_log.InfoFormat(@"{0}: Process was started", processName); //Уровень логирования Info
_log.WarnFormat(@"{0}: Process was started", processName); //Уровень логирования Warn
_log.ErrorFormat(@"{0}: Process was started", processName); //Уровень логирования Error

Если сайт развернут в облаке (cloud), то логи можно получить обратившись в техническую поддержку.
Если же сайт размещен на своих серверах (on-site), то логи необходимо искать по пути C:\Windows\TEMP\Creatio\SiteName\0\Log (этот путь может быть изменен в файле nlog.targets.config, параметр LogDir).

Для уровня логирования Debug и Info логи запишутся в файл Common.log, а для уровня Error - в файл Error.log
По умолчанию минимальный уровень логирования в on-site для логера "Common" указан Info. Изменить его можно в файле ..\Terrasoft.WebApp\nlog.config

<logger name="*" writeTo="commonAppender" minlevel="Info" maxlevel="Warn" />

 

Нравится

Поделиться

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

Добрый день,

 

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

 

Имеется "Автогенерируемая страница", в которой 4 поля (Отправитель, Получатель, Дата начала, Дата завершения). 

  1. Отправитель - сотрудник, уходящий в отпуск
  2. Получатель - заместитель
  3. Дата начала - с какого дня начинают передачу активностей на заместителя
  4. Дата завершения - когда закончить передачу и завершить бизнес-процесс.

 

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

Нравится

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

Может быть проще использовать уже готовый бизнес-процесс по делегированию прав или модифицировать его? https://marketplace.terrasoft.ru/template/delegirovanie-prav-dostupa-na…

Сигнал не нужен, ведь данный БП запускается вручную.
После автогенерируемой страницы читаем первую запись Activity с нужными параметрами (от-до, где Ответственный = Сотрудник, ну и задача еще не завершена).
Если такая запись найдена (Id!=Guid.Empty), то модифицируем Activity, устанавливая Ответственный = Заместитель.
И снова возвращаемся к чтению записи Activity.

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

И, возможно, подумать, а как возвращать ещё не выполненные задачи после отпуска

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

 

Спасибо за ваши ответы.

 

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

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

_KSL_,

 

В таком случае Вам нужно следующее.

1. В срм хранить информацию об отпусках сотрудников, например, реализовать деталь в разделе 'Сотрудники'. Структура её может быть следующей - сотрудник, дата начала отпуска, дата завершения отпуска, кому делегировать задачи. Для избежания путаницы я бы не давала сотрудникам самостоятельно вносить эту инфрмацию. Логично, что это должен делать либо ответственный за отпуска, либо HR-менеджер, либо бухгалтер.

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

Алла Савельева,

Спасибо за ответ 

 

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

_KSL_,

А что мешает в том случае, если даты отпуска изменятся, откорректировать их в срм?

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

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

Алла Савельева,

 

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

 

Сотрудник, который уходит в отпуск, должен запустить данный процесс. При запуске открывается "Автогенерируемая страница", в который имеется 4 поля (Отправитель - сотрудник, уходящий в отпуск, Получатель - кому будем переназначать активность, Дата начала и Дата завершения - с какого и до какого чисел будем переназначать).

 

Далее происходит чтение данных с объекта "Активность" и изменение данных "Активность" на основании условий, т.е. Ответственный = Отправитель, Дата завершения>Дата создания >= Дата начала. 

 

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

 

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

 

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

 

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

 

Если Вы хотите обработать один раз существующие задачи сотрудника, то данные об отпуске хранить не надо. А если же хотите передавать и новые задачи, которых ещё нет, то без хранения не обойтись.

 

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

Зверев Александр,

 

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

 

Правильно ли я понял, что я должен хранить к примеру в справочнике данные по отпускам(Сотрудник, Заместитель, Дата начала отпуска, Дата завершения).

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

 

Но тогда не совсем понимаю как нужно будет организовать процесс.

Как Вы можете переназначит новые, их же ещё нет?

Если делаете логику на моменте создания или регулярно по планировщику, то нужно где-то брать информацию, у кого, на кого и с какого по какое отпуск.

Зверев Александр,

 

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

 

Из полей Автогенерируемой страницу данные переходили в чтение данных, как условия (Ответственный=у кого, Завершения>Дата создания>=Начало). Далее шло изменение данных с такими же условиями, но меняли Ответственный=кому. Далее шел условный поток, в  котором сравнивалась текущая дата с завершением. Если текущая дата < Завершения, то возвращается к чтению.

 

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

 

Если мы получаем данные из "Автогенерируемой страницы", есть ли необходимость хранить данные об отпусках отдельно в срм.

Сначала попытайтесь понять, что вы вообще хотите сделать. Если задач ещё не существует, то Вы их не вычитаете и не измените.

 Если текущая дата < Завершения, то возвращается к чтению

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

_KSL_,

Если у Вас версия on-site Вы можете запустить SQL profiler и отследить запрос, который идет в базу, и понять, почему происходит зацикливание.

 

Покажите код, каким образом Вы реализовали, установку ответственных в задачах в Вашем бизнес-процессе.

Алла, он просто нарисовал в БП цикл, надеясь, что он будет постоянно до даты конца отпуска крутиться и обрабатывать появляющиеся задачи. Но так нельзя, количество повторений ограничено, а до того всё зависнет.

Зверев Александр,

Ясно. Ну, ты же, знаешь, есть старая привычка докопаться до сути вопроса)))

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

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

Добрый день!

Руководствуясь статьей "Формулы" на Академии, пытаюсь создать в БП условный поток с проверкой заполненности поля, но при сохранении выдает ошибку:

________________________________________________________________________________________

Нравится

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

Вы пытаетесь сравнить Дату с Guid. Поэтому формула и выдает вам ошибку. Вам нужно сравнивать с DateTime.MinValue

Вы пытаетесь сравнить Дату с Guid. Поэтому формула и выдает вам ошибку. Вам нужно сравнивать с DateTime.MinValue

Сидоров Александр Валерьевич,

 благодарю, разобрался.

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

Обновил систему до 7.14.0, помимо решаемых проблем появилась одна нерешаемая, ТП морозится уже 1.5 недели, поэтому пытаюсь задать вопрос коммьюнити.

Итак, проблема с запуском БП, которые должны стартовать по таймеру.  Если запускать их вручную, они тупо не запускаются. В журнале появляется в статусе "Выполняется", но реально ничего не выполняется и просто "висит". Это баг, или фича новой версии?

В логах приложения ошибок нет. По таймеру запускаются и работают.

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

Кто-нибудь сталкивался? Куда можно поковырять?

Нравится

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

У нас возникало из-за переполнения очереди заданий в Quartz. Оказывается, что таймер в БП не приостанавливает процесс, а ставит его в очередь выполнения в определенное время. И если эта очередь переполнена, то и процесс по таймеру дальше не идет. Скорее всего у вас та же проблема. Если есть доступ к журналу Quartz - посмотрите там. 
Как вариант - вместо таймера поставьте скрипт-таск с Thread.Sleep.

Ксензов Егор,

а это какая таблица?

Алексей-Карягин,

Добрый день! Вот скрипт на выборку данных из таблицы Quartz

SELECT [SCHED_NAME],
[TRIGGER_NAME]
,[TRIGGER_GROUP]
,[JOB_NAME]
,[JOB_GROUP]
,[DESCRIPTION]
,[dbo].[fn_QuartzTimeToDateTime]([NEXT_FIRE_TIME]) [NEXT_FIRE_TIME]
,[dbo].[fn_QuartzTimeToDateTime]([PREV_FIRE_TIME]) [PREV_FIRE_TIME]
,[PRIORITY]
,[TRIGGER_STATE]
,[TRIGGER_TYPE]
,[dbo].[fn_QuartzTimeToDateTime]([START_TIME]) [START_TIME]
,[dbo].[fn_QuartzTimeToDateTime]([END_TIME]) [END_TIME]
,[CALENDAR_NAME]
,[MISFIRE_INSTR]
,[JOB_DATA]
FROM [QRTZ_TRIGGERS]

 

Нигрескул Алексей,

у меня 27 записей. Не похоже, чтобы было какое-то переполнение.

А какие сигналы старты у процесса? Обычно ставят 2 - таймер и ручной запуск

Просто таймер. На 7.11 это прекрасно работало.

С версии  7.12.3 менялся движок процессов, они стали интерпретируемыми. Соответственно, не всё, что работало в 7.11, полностью совместимо с нынешним, нужно тестировать. Возможно, решение от Владимира как раз поможет.

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

Добрый день!

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

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

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

Может у кого есть опыт как можно увеличить тайм аут выполнения БП? Базовых методов не нашли.

Благодарю!

 

Нравится

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

Добрый день!
Скорее всего вы запускаете БП через стандартное действие "Запуск процесса". Если это так, то там вызывается метод _runProcess утилиты ProcessModuleUtilities, который наверняка вызывает метод _runProcessOld. В этом методе вызывается сервис ProcessEngineService.svc с передачей параметров. Но таймаут не передается.
Что можно сделать: реализовать отдельное действие запуска вашего БП (кнопку в каком-нибудь разделе, дизайнере), в котором будет вызываться сервис ProcessEngineService.svc с передачей таймаута.

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

Это не только уберёт зависание, но и ослабит нагрузку на сервер приложений и базу данных.

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

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

Сидоров Александр В.,

Александр, ваша идея нам очень очень помогла! Спасибо! будем еще тестировать).

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

При сохранении правок существующего бизнес-процесса возникает ошибка:

 

Суть корректировок - нужно сделать так чтобы после прохождения 1-го уровня эскалации в обращении перед переходом на 2-ой уровень эскалации происходила проверка не находится ли обращение в состоянии паузы (OnHold), проще говоря нужно приостанавливать эскалацию в случае OnHold'а:


 

Нравится

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

Видимо, речь о том, что из элемента «Исключающее “ИЛИ” по событиям» (жёлтый ромб слева сверху) нельзя непосредственно вызывать другие элементы, помимо получения событий (различных сообщенийсигналов либо таймеров), а Вы добавили ветку вниз, начинающуюся со чтения. Также нижний жёлтый ромб «Исключающее “ИЛИ”» с одним входом и одним выходом выглядит странно и непонятно его предназначение.

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

Всем доброго времени суток! 

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

Нравится

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

Этот механизм реализован в схеме DesktopPopupNotification, функция из которой вместе с параметрами сообщения вызывается в том месте системы, где хотим что-то сообщить. Например, в SectionMergeHelper:

/**
 * Show popup message with the merge info.
 * @param {Number} mergeRecordsCount Count of records to merge.
 */
showMergePopup: function(mergeRecordsCount) {
	var config = this.getMergePopupConfig(mergeRecordsCount);
	DesktopPopupNotification.showNotification(config);
},
 
/**
 * Returns the config of the popup notification.
 * @param {Number} mergeRecordsCount Count of records to merge.
 * @return {Object} Config of the popup notification.
 */
getMergePopupConfig: function(mergeRecordsCount) {
	var bodyTemplate = this.getMergePopupBodyTemplate();
	return {
		id: this.Terrasoft.generateGUID(),
		title: resources.localizableStrings.MergeNotificationTitleTemplate,
		body: this.Ext.String.format(bodyTemplate, mergeRecordsCount),
		icon: this.getMergePopupIconUrl(),
		onShow: this.onShowPopup,
		ignorePageVisibility: true
	};
},

Соответственно, если хотите, чтобы в одних разделах что-то показывалось, а в других — нет, нужно в ненужных переопределить логику, закомментировав вызов showNotification.

Александр, спасибо за развёрнутый ответ! В частности интересуют уведомления об успешном запуске процессов, например при опубликовании обращения или очистки кэша Redis, в схемах процессов вызов данной функции не обнаружил

Похоже на функцию _showSuccessfullyRunProcessPopup в схеме ProcessModuleUtilities.

Зверев Александр,

 Большое спасибо за помощь :3

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