Довольно простая задача - прочитать параметр БП который содержит ID или текст. При следующем коде в Задание-сценарий:

Guid activityId = Get<Guid>("Activity11");

String activity1 = Get<String>("ActivityGuid");

 

return true;

Выдает всегда ошибку:  

System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.
   в Terrasoft.Common.ReflectionUtilities.GetPropertyValueByPath(Object source, String propertyPath)
   в Terrasoft.Core.Process.ProcessModel.Get[T](String propertyPath)
   в Terrasoft.Core.Process.UsrProcess17NvgIncident1MethodsWrapper.ScriptTask1Execute(ProcessExecutingContext context)
   в Terrasoft.Core.Process.ProcessScriptTask.InternalExecute(ProcessExecutingContext context)
   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

 

В чем может быть проблема ? 

Нравится

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

Добрый день.

 

Какую версию срм используете?

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

7.14.1.935

Александр Че,

Проверьте, чтобы у Вас был интерпритируемый процесс (это в свойствах самого процесса устанавливается признак) и у скрипт такста был установлен признак 'Для интерпритируемого процесса' (точно не помню название).

Также посмотрите обсуждени по этой ссылке, чтобы было понятнее о чем речь.

Спасибо,
но как я понял из того же поста:
"Начиная с версии 7.12.3 все создаваемые бизнес-процессы в bpm’online являются интерпретируемыми. Для обращения к значениям параметра процесса следует использовать методы get и set."
В расширенных настройках только поле с Именем есть теперь.

Есть еще идеи ? 

Александр Че,

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

string activity1 = Get<string>("ActivityGuid");

И ещё меня смущает названия Ваших параметров: в строку пытаетесь получить параметр с названием 'ActivityGuid'. Вы точно правильно параметры приводите к соответствующим типам?

 

Александр Че пишет:
Начиная с версии 7.12.3 все создаваемые бизнес-процессы в bpm’online являются интерпретируемыми. Для обращения к значениям параметра процесса следует использовать методы get и set

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

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

И все равно та же ошибка с GET ..

Скриншоты БП ниже

А после изменения кода в скрипте компилировали процесс или только сохраняли?

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

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

 

На 7.16.1 аналогичное работает нормально:

String ProcessSchemaParameter1 = Get<String>("ProcessSchemaParameter1");
Set("ProcessSchemaParameter2", ProcessSchemaParameter1);
return true;

Но тут механизм параметров дорабатывался, добавили направление.

Сомневаюсь, что в 7.14.1 просто стандартное обращение к параметру не работало. Может, у Вас сначала было неправильно с типом или названием параметра, и это закешировалось?

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

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

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

 

Возможно, Ваш вопрос решит обновление.

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

В БП с таймером хочу получить локализованный шаблон email. 
Но при получении правил локализации получаю ошибку (см. https://community.terrasoft.ru/questions/osibka-pri-polucenii-sablona-email-v-fonovom-bp)
Вопрос. Почему ActorUserConnection, которое доступно после отработки таймера, не подходит DefaultLanguageIterator?
Вопрос 2: Можно ли сохранить UserConnection (в параметр или др. способом) для использования после таймера? 

Нравится

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

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

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

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

Всегда был интересен вопрос след. характера:

В чём отличие типа данных у параметра БП таких как Уникальный идентификатор и Справочник?

Может в Справочник можно как-то внутрь заглянуть и вытянуть displayValue, избегая запрос к root таблице?

Сталкивался кто с подобным, интересен опыт Ваш.

Нравится

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

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

_processSchemaParameter1 = () => { return (Guid)(new Guid("b06f1e0e-f46b-1410-7190-00155d043204")); };
_processSchemaParameter2 = () => { return (Guid)(new Guid("b06f1e0e-f46b-1410-7190-00155d043204")); };
...
private Func<Guid> _processSchemaParameter1;
public virtual Guid ProcessSchemaParameter1 {
	get {
return (_processSchemaParameter1 ?? (_processSchemaParameter1 = () => Guid.Empty)).Invoke();
	}
	set {
_processSchemaParameter1 = () => { return value; };
	}
}
 
private Func<Guid> _processSchemaParameter2;
public virtual Guid ProcessSchemaParameter2 {
	get {
return (_processSchemaParameter2 ?? (_processSchemaParameter2 = () => Guid.Empty)).Invoke();
	}
	set {
_processSchemaParameter2 = () => { return value; };
	}
}
...
private void WritePropertyValues(DataWriter writer, bool useAllValueSources) {
	if (!HasMapping("ProcessSchemaParameter1")) {
writer.WriteValue("ProcessSchemaParameter1", ProcessSchemaParameter1, Guid.Empty);
	}
	if (!HasMapping("ProcessSchemaParameter2")) {
writer.WriteValue("ProcessSchemaParameter2", ProcessSchemaParameter2, Guid.Empty);
	}
}
 
...
protected override void InitializeMetaPathParameterValues() {
	base.InitializeMetaPathParameterValues();
	MetaPathParameterValues.Add("e0873088-8334-4b85-96a4-fa3e5ecb7374", () => ProcessSchemaParameter1);
	MetaPathParameterValues.Add("246467c7-071b-4cb0-8073-30c4f72be120", () => ProcessSchemaParameter2);
...	
protected override void ApplyPropertiesDataValues(DataReader reader) {
	base.ApplyPropertiesDataValues(reader);
	bool hasValueToRead = reader.HasValue();
	switch (reader.CurrentName) {
case "ProcessSchemaParameter1":
	if (!hasValueToRead) break;
	ProcessSchemaParameter1 = reader.GetValue<System.Guid>();
break;
case "ProcessSchemaParameter2":
	if (!hasValueToRead) break;
	ProcessSchemaParameter2 = reader.GetValue<System.Guid>();
break;
	}
}
...

А в метаданных:

      "Parameters": [
        {
          "TypeName": "Terrasoft.Core.Process.ProcessSchemaParameter",
          "UId": "e0873088-8334-4b85-96a4-fa3e5ecb7374",
          "Name": "ProcessSchemaParameter1",
          "CreatedInSchemaUId": "f4c123c0-d628-4d9f-867c-6c0b78c86395",
          "ModifiedInSchemaUId": "f4c123c0-d628-4d9f-867c-6c0b78c86395",
          "DataValueType": "b295071f-7ea9-4e62-8d1a-919bf3732ff2",
          "SourceValue": {
            "Source": 3,
            "Value": "[#Lookup.c449d832-a4cc-4b01-b9d5-8a12c42a9f89.b06f1e0e-f46b-1410-7190-00155d043204#]",
            "ModifiedInSchemaUId": "f4c123c0-d628-4d9f-867c-6c0b78c86395"
          },
          "ReferenceSchemaUId": "c449d832-a4cc-4b01-b9d5-8a12c42a9f89"
        },
        {
          "TypeName": "Terrasoft.Core.Process.ProcessSchemaParameter",
          "UId": "246467c7-071b-4cb0-8073-30c4f72be120",
          "Name": "ProcessSchemaParameter2",
          "CreatedInSchemaUId": "f4c123c0-d628-4d9f-867c-6c0b78c86395",
          "ModifiedInSchemaUId": "f4c123c0-d628-4d9f-867c-6c0b78c86395",
          "DataValueType": "23018567-a13c-4320-8687-fd6f9e3699bd",
          "SourceValue": {
            "Source": 3,
            "Value": "[#Lookup.c449d832-a4cc-4b01-b9d5-8a12c42a9f89.b06f1e0e-f46b-1410-7190-00155d043204#]",
            "ModifiedInSchemaUId": "f4c123c0-d628-4d9f-867c-6c0b78c86395"
          }
        }
      ],

То есть разницы практически нет, хотя внешний вид и интерфейс выбора значения разные.

Также на значения параметров в выполняющемся процессе можно посмотреть запросом в базу:

select top 10 *, cast(PropertiesData as varchar(max)) from SysProcessData

Там для параметров видно тоже только Id.

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

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

В БД ничего похожего найти не смог 
Есть какие-нибудь идеи по удалению процесса?

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

Нравится

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

Начните с этого поста

Начните с этого поста

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

Всем привет.

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

Заранее спасибо за помощь.

Нравится

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

Начиная с версии 7.12.3 все создаваемые бизнес-процессы в bpm’online являются интерпретируемыми. Для обращения к значениям параметра процесса следует использовать методы get и set 

Метод Get возвращает значение параметра элемента или процесса.

Сигнатура метода:

Get<T>(string path)

где:

T — тип значения параметра;

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам:

“имя параметра”,

“имя свойства”,

“имя элемента.имя параметра”,

“имя элемента.имя свойства”.

Метод Set указывает значение параметру элемента или процесса.

Сигнатура метода:

Set(string path, T value)

где:

value — указываемое значение,

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам, описанным выше для метода Get.

 

Так например чтобы получить в скриптаске UserConnection нужно использовать конструкцию:

UserConnection userConnection = Get<UserConnection>("UserConnection");

Чтобы получить строковый параметр БП:

string message = Get<string>("Message");

Подробнее тут

Начиная с версии 7.12.3 все создаваемые бизнес-процессы в bpm’online являются интерпретируемыми. Для обращения к значениям параметра процесса следует использовать методы get и set 

Метод Get возвращает значение параметра элемента или процесса.

Сигнатура метода:

Get<T>(string path)

где:

T — тип значения параметра;

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам:

“имя параметра”,

“имя свойства”,

“имя элемента.имя параметра”,

“имя элемента.имя свойства”.

Метод Set указывает значение параметру элемента или процесса.

Сигнатура метода:

Set(string path, T value)

где:

value — указываемое значение,

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам, описанным выше для метода Get.

 

Так например чтобы получить в скриптаске UserConnection нужно использовать конструкцию:

UserConnection userConnection = Get<UserConnection>("UserConnection");

Чтобы получить строковый параметр БП:

string message = Get<string>("Message");

Подробнее тут

Григорий Чех,

Спасибо большое! Как-то этот мануал мимо меня прошёл.

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

У меня есть элемент "Читать данные", у него есть ИД, Имя, и другие параметры сущности, которую считали. Как получить значения этих параметров из кода в элементе "Задание-сценарий"?

Нравится

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

Добрый день! вот ссылка на статью https://academy.terrasoft.ru/documents/technic-bpms/7-12/element-proces…
 

Метод Get возвращает значение параметра элемента или процесса.

Сигнатура метода:

Get<T>(string path)

где:

T — тип значения параметра;

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам:

•“имя параметра”,

•“имя свойства”,

•“имя элемента.имя параметра”,

•“имя элемента.имя свойства”

Добрый день! вот ссылка на статью https://academy.terrasoft.ru/documents/technic-bpms/7-12/element-proces…
 

Метод Get возвращает значение параметра элемента или процесса.

Сигнатура метода:

Get<T>(string path)

где:

T — тип значения параметра;

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам:

•“имя параметра”,

•“имя свойства”,

•“имя элемента.имя параметра”,

•“имя элемента.имя свойства”

Вы можете нужные Вам значения из элемента "Читать данные" добавить в параметры бизнес-процесса (БП), а потом в элементе "Задание-сценарий" вычитать их из параметров БП с помощью метода Get

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

Добрый день!

В процессе использую параметр с типом Коллекция объектов. Значение данного параметра передается в процесс из родительского процесса. Далее в элементе с типом задание сценарий происходит некая работа с коллекцией (по сути коллекция передается в другой метод, сами ее значения не меняются). После чего по условию БП либо идет дальше, либо возвращается в данный же кубик задание сценарий и должен снова вызвать метод и передать данную коллекцию в качестве параметра. Однако, при повторном заходе в задание сценарий, БП падает с ошибкой 

Terrasoft.Common.ItemNotFoundException: Элемент с идентификатором "00000000-0000-0000-0000-000000000000" не найден
   в Terrasoft.Core.ManagerItemCollection`1.GetByUId(Guid uid)
   в Terrasoft.Core.Manager`2.GetInstanceByUId(Guid uid)
   в Terrasoft.Core.Process.GetGoldWarrantyAmountProcess.get_ProductConditionCollection()
   в Terrasoft.Core.Process.GetGoldWarrantyAmountProcess.ScriptTask1Execute(ProcessExecutingContext context)
   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Насколько я понимаю, это именно ошибка чтения параметра - коллекции объектов. 
В связи с этим у меня возникает вопрос: как корректно передавать параметр с типом коллекция объектов в другой БП, чтобы цикл его жизни не был равен одному запуску дочернего БП, а был доступен на всем протяжении работы данного БП?

Нравится

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

Судя по тому, что в первый раз передалось нормально, потом значение переменной кто-то очищает. Если есть возможность, можно произвести отладку и посмотреть, какое значение в разные моменты находится в параметре.

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

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

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

Здравствуйте! Возникла следующая задача: есть БП, в нём выполняется шарпный код, по таймеру, и при завершении процесса, в параметры этого процесса, записываются значения, и мне необходимо после выполнения этого БП, на клиенте анализировать эти параметры и выводить соответствующие информационные уведомления. Но я чего-то не пойму как передать в callback, выполнения БП, эти самые параметры?

Нравится

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

Здравствуйте! Попробуйте передавать по каналу web-socket
Код на стороне БП

var userConnection = Get<UserConnection>("UserConnection");
var messageToUser = Get<string>("AbMessageToUser");
Terrasoft.Configuration.MsgChannelUtilities.PostMessage(userConnection, "AbCreatingSmsAudienceProcess", messageToUser);
return true;

На клиенте следующий код
 

define("ContactSectionV2", [], function() {
	return {
		entitySchemaName: "Contact",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		methods: {
			init: function () {
				this.callParent(arguments);
				this.subscriptionFunction();
			},
			subscriptionFunction: function() {
				Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE,
				this.onAbCreatingSmsAudienceProcessMessage, this);
			},
			onAbCreatingSmsAudienceProcessMessage: function(scope, message) {
				if (!message || message.Header.Sender !== "AbCreatingSmsAudienceProcess") {
					return;
				}
				var message2 = message.Body;
				if (!this.Ext.isEmpty(message2)) {
					this.Terrasoft.showInformation(message2);
				}
			}
		},
		messages: {}
	};
});

 

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

 

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

Добрый день.

Запускаю  БП из действия раздела:

var selectedRows = this.get("SelectedRows");
var accounts = selectedRows.join();
var processName = "UsrChangeAccountOwnerProcess";

var params = {
	AccountIds: accounts
};
ProcessModuleUtilities.runProcess(processName, params);

При запуске БП по выделенным записям (более 50 записей) возвращается ошибка:

https://yadi.sk/i/k7KXj5VE3PTDoj

Предположительно ошибка связана с длиной строки с идентификаторами выделенных записей, которая передаётся в параметр процесса. Т.к. если выделено до 50 записей, то БП запускается. 
Вопросы:
Как снять ограничение на длину параметра?
Можно ли запустить БП с использованием callService, передав параметры в виде jsonData, а не в url?

Нравится

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

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

Терещук Сергей,

А с чем связана описанная мной проблема?

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

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

maxReceivedMessageSize. Но я могу и ошибаться.

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

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

Необходима помощь в решении нескольких тривиальных задач при построении БП (решение желательно листинг простенький или ссылку)

1) Как программно через элемент БП задание-сценарий получить ID созданной записи из элемента Страница редактирования

2) Как программно через элемент БП задание-сценарий получить/установить параметр БП

3) Как в условном потоке написать условие ID!=null, при том что ID с типом уникальный идентификатор

Данные вопросы возникли при решении простой задачи: при входе в подпроцесс на него передается AccountID -> при старте БП идет проверка AccountID есть/нет
если есть, то идем к шагу задачи
если нет, то идем на шаг с создание Контрагента

На данный момент реализация проверки на AccountID!=null довольно убогая... через чтение данных получаю count записей с id = AccountID и в условном потоке проверяю сравнением...

p.s. так же наблюдается некоторая странность при запуске подпроцесса. Первая задача падает в расписание, а не появляется сразу на экран (остальные задачи в подпроцессе отрабатывают нормально), возможно есть какая-нибудь настройка или прием?

p.p.s. Я пытался найти описание методов для получения коллекции параметров БП в SDK, но не нашел ) если они там есть и я просто проглядел - скиньте ссылку

Заранее спасибо!

Нравится

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

Артем, добрый день.

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

Но, т.к. в таком случае, Вам бы пришлось создать два БП, рассмотрим конкретно Ваш кейс.
БП будет следующим:

Стартовое сообщение - сигнал на объекте "Активность" после добавления новой записи.
Далее в элементе "Чтение данных" считываем все поля записи, по которой был запущен процесс:

После этого, создаем условный поток к элементу "Создание нового контрагента", условие следующее:

ReadDataUserTask1.ResultEntity.GetTypedColumnValue<Guid>("Account.Id") != Guid.Empty

где ReadDataUserTask1 - название элемента "Чтение данных".

и потом добавляем поток по умолчанию к элементу "Создать новую задачу".

В принципе это всё.

Если будут вопросы - обращайтесь.

Спасибо, Дмитрий!
Вопрос N3 можно считать решенным ) (не знал что в условии можно использовать C#)

К сожалению, Ваш способ по созданию контрагента мне не подходит по причине того, что необходимо далее передавать AccountID в подпроцесс (видимо нужно было более детально описать пример).

если при старте родительского БП AccountID был заполнен (была связь Лида с контрагентом), то передавать далее в подпроцесс необходимо именно его
, а если при старте родительского БП AccountID пустой (например Лида квалифицировали как контакт и поле Контрагент пустое), то передавать далее в подпроцесс необходимо идентификатор записи из шага "Создайте нового контрагента".

Можно конечно решить вопрос с помощью конструктора, но это избыточность в чистом виде =\ куда проще мне было бы вставить после шага "Создайте нового контрагента" скриптик, который просто заполнил бы параметр процесса AccountID идентификатором созданной записи из шага "Создайте нового контрагента" + я практически на 100% уверен что в будущем еще не раз придется работать с параметрами БП через скрипт.

Так что вопросы 1,2 все еще актуальны

Артём, добрый день.

Если Вы добавили в структуру процесса параметр MyParam с типом GUID, то обратиться к нему можно просто:

MyParam = new Guid(stringGuid);
Guid fromParam = MyParam;

это по второму вопросу. Т.е. обращаемся в любом скрипте процесса по имени параметра.

По первому вопросу:

Если Вы раскроете действие "Открыть карточку редактирования", то увидите там параметр RecordId, с него и считывайте:

Guid recordId = OpenPageElement1.RecordId;

Спасибо Дмитрий!
На этот раз все вопросы сняты

С уважением,
Волков Артем

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