В Бизнес процессе получаю коллекцию данных.

Далее у меня идет Задание-сценарий.

 

Как в задании-сценарии получить эту коллекцию?

Нравится

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

Всё просто.

 

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

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

Доброго времени суток, коллеги!

 

Такой вопрос появился, у меня есть бизнес-процесс в котором я собираю различные данные из разных справочников, я через задание-сценарий пишу код с формированием таблицы, как мне правильно синтаксически обращаться к этим данным? Искал на Академии, не нашел точного ответа.

 

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

Нравится

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

Доброе утро. Посмотрите вот это обсуждение и ещё это.

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

Добавляю данные в бизнес-процессе через задание сценарий. Делаем многострочный Insert

var insCertificateData = new Insert(UserConnection).Into("NavCertificateData");
foreach (var entity in navCertificateData)
{
	insCertificateData.Values()
		.Set("NavCertificate", Column.Parameter(certificateId))
		.Set("NavProduct", Column.Parameter(entity.NavProduct ))
		.Set("NavDiametr", Column.Parameter(entity.NavDiametr))
		.Set("NavMarka", Column.Parameter(entity.NavMarka,))
		.Set("NavNippelAssembly", Column.Parameter(entity.NavNippelAssembly))
		.Set("NavQuantity", Column.Parameter(entity.NavQuantity))
		.Set("NavWeight", Column.Parameter(entity.NavWeight))
		.Set("NavMinUES", Column.Parameter(entity.NavMinUES))
		.Set("NavMaxUES", Column.Parameter(entity.NavMaxUES))
		.Set("NavMinLength", Column.Parameter(entity.NavMinLength))
		.Set("NavMaxLength", Column.Parameter(entity.NavMaxLength))
		.Set("NavDK", Column.Parameter(entity.NavDK))
		.Set("NavBend", Column.Parameter(entity.NavBend))
		.Set("NavKTP", Column.Parameter(entity.NavKTP))
		.Set("NavCompanyGrafit", Column.Parameter(entity.NavCompanyGrafit));
}
insCertificateData.Execute();

В основном все типа string. В значении NavNippelAssembly иногда приходит EmptyString. И в этом случае получаем ошибку 

"Для параметра \"P5\" со значением null необходимо указать тип данных"

Собственно есть Column.Parameter(Object,DataValueType). Полагаю, что надо его использовать, но как указать этот самый DataValuType? Тип строка  

Нравится

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

Алексей Следь,

Посмотрите обсуждение в этой теме.

Для установки null можно использовать Column.Const(null)

Николай Кузьмин,

Так у меня ж не всегда null и 5 полей, где может быть string.Empty

Алексей Следь,

Посмотрите обсуждение в этой теме.

Алла, спасибо, я там как раз приводил похожий пример, только в нынешнем случае сравнение будет не с Guid.Empty, а с String.Empty.

 .Set("IndustryId", ((IndustryIdParameter!=Guid.Empty)?Column.Parameter(IndustryIdParameter):Column.Const(null)))

Ну, или проверять условие и если не выполняется, не производить добавление к формируемому запросу этого Set, тогда в SQL-запросе вообще не будет упоминания этого пустого поля.

Мда, как всегда решение на поверхности лежало. 

Александр, по мне правильней тогда делать сравнение не со string.Empty, а проверять stringIsNullOrEmpty(). А т.к. табличка у меня нуллы не поддерживает, то все пришло к такой конструкции

.Set("NavProduct", (string.IsNullOrEmpty(entity.NavProduct)? Column.Parameter(string.Empty) : Column.Parameter(entity.NavProduct)))

 

Алексей, если всё так, как описали, то зачем вообще два раза писать Column.Parameter и проверять на Empty? Можно только на null при помощи «??», как предложили тут:

.Set("NavProduct", Column.Parameter(entity.NavProduct ?? string.Empty))

 

Александр, учитывая источник данных, лучше проверять на Null и Empty. В любой момент Null может стать пустой строкой.

Так пустая строка в итоге и пишется, её же не надо на такую же заменять, можно сразу в параметр.

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

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

Guid activityId = Get("Activity11");

String activity1 = Get("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 и компилировал еще раз пакет уже в конфигурации, но ошибка так и не уходит.. такое ощущение что библиотеки не хватает.

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

 

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

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

Коллеги, всем здоровья. Не могу разобраться в синтаксисе методов Get и Set для элемента процесса "задание-сценарий". Прошу помощи.

 

Кейс следующий.

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

 

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

 

Судя по странице документации для получения/передачи параметров нужно использовать методы Set и Get вот с таким синтаксисом:



Get(string path)

Set(string path, T value)

 

При этом: 

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

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

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

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

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

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

 

В Creatio Community я нагуглил вот такой пример Get метода для получения коллекции:



Get>("ReadDataUserTask1.ResultCompositeObjectList");



А path сформировал исходя из того, что элемент (шаг) чтения данных называется ReadDataUserTask6, а параметр, который мне нужен - ResultCompositeObjectList.



В результате в сценарии получился вот такой код:



string[] products = Get>("ReadDataUserTask6.ResultCompositeObjectList");



string productstring = "";

String seperator = ", ";

productstring += String.Join(seperator, products);



Set("ProcessSchemaParameter2", string productstring);



return true;

 

При компиляции шага получаю вот это:



Изображение удалено.

 

Открываю исходный код бизнес-процесса, смотрю на 40 строчку и не понимаю, что не так:

 

Изображение удалено.

 

(а) синтаксис в точности такой же, как указано в документации:

Set(string path, T value)



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



Изображение удалено.



Если это не "String", то что? И вообще, как определить эти значения, которые нужно подставлять вместо буковки Т? Ведь автор примера в community их откуда-то взял :) Поделитесь знаниями? :)



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

 

Нравится

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

Добрый вечер.

 

Вот таким образом можно получить значение параметра:

DateTime collectionDate = Get<DateTime>("CollectionDate");

 

А вот так присвоить:

Set<DateTime>("StorageDate", storageDate);

 

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

 

Добрый вечер.

 

Вот таким образом можно получить значение параметра:

DateTime collectionDate = Get&lt;DateTime&gt;("CollectionDate");

 

А вот так присвоить:

Set<DateTime>("StorageDate", storageDate);

 

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

 

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

 на сколько я помню то Set ставится без указания типа

Set(" StorageDate ", storageDate);

В вашем случае Вы указали все верно, только не нужно было указывать тип для передаваемого параметра - Set("ProcessSchemaParameter2", productstring);

Александр Тыра пишет:

на сколько я помню то Set ставится без указания типа Set(" StorageDate ", storageDate);

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

 

Странно то, что установка параметра процесса работает и в синтаксисе, который приведен мной с указанием типа данных в скобочках.

 

На досуге попробую разобраться с этим, если будет что-то интересное, то поделюсь здесь.

Коллеги, всем спасибо за ответы. Действительно, указание типа данных в синтаксисе для метода "Set" работает. Это оказалось очень полезным для отладки. Чтобы убедиться в работоспособности метода я попробовал передать статичную строку "Hello" и вывести её на автогенерируемую страницу. Сработало только с указанием типа данных.



При этом синтаксис для метода Set, указанный Аллой отличается от синтаксиса, указанного в официальной документации. 

У Аллы (то, что сработало): 

Set<DateTime>("StorageDate", storageDate);

 

То есть, в терминологии документации это

Set<Т>(string path, value)

 

Сравните с тем, что написано в статье документации:

Set(string path, T value)

 

Это меня и смутило.

 

И ещё - всё-таки, как "простому смертному" понять, что при работе с коллекцией нужно декларировать тип данных как <ICompositeObjectList<ICompositeObject>> ? Я не нашёл этого в описании, а это ведь важное знание, без него функционалом метода пользоваться не получится. 



Коллеги из Террасофт - если вы нас читаете, поправьте, пожалуйста сигнатуру метода Set в указанной статье документации и добавьте сопоставление значения параметра T в методе для *каждого* типа данных в бизнес-процессе. Вот скриншот дропдауна с вариантами типа данных в параметре процесса. Смотрите, сколько их там:

 

Не знаю как другим, а мне как разработчику это просто категорически важно. ОК, для коллекции значений я нагуглил <ICompositeObjectList<ICompositeObject>> . А вот как понять, какой тип данных у коллекции значений с атрибутами? А у коллекции объектов (EntityCollection)?

 

А ещё ведь возникают вопросы вроде "у вас 5 вариантов дробных чисел, для всех вариантов прописывать <float>?"

 

Кому-то это очевидно, кому-то нет. А на мой взгляд должно быть очевидно каждому. Без это клиенты вынуждены "рыскать" по форумам, а это на мой взгляд неправильно.

Евгений, поискал по содержимому cs-файлов конфигурации, вариант Set без типа в угловых скобках не раз встречается в «коробке». Например, в FileImportProcess для логического:

Set("IsUsePersistentFileImportEnabled", UserConnection.GetIsFeatureEnabled("UsePersistentFileImport"));

А со скобками встречается только в доработанном коде. Вероятно, по аналогии с Get.

 

В чём преимущество с типом, что хотите его внести в документацию? Как именно не работает на автогенерируемой странице со строкой? А если строку-константу явно привести к string, то нормально? 

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

Да, именно если для строки-константы явно указать string, то работает. Согласен, что по всей видимости код доработан по аналогии с Get. Речь о внесении в документацию идет не из-за преимуществ с типом/без типа, а из-за того, что если указывать тип так, как это написано в документации, компилятор выдаёт ошибки. Т.е. то, что сейчас написано в документации, не соответствует тому, как фактически нужно делать. 



А до файлов конфигурации мне физически не добраться, т.к. у нас облако. 

По последнему, я искал не в файлах, а через базу в SysSchemaSource. В облаке тоже можно, если ставить дополнение для SQL-запросов.

 

По отсутствию примера Set, недокументированному параметризируемому Set<> и списку типов, согласен, написал им. Обратите внимание, в академии внизу есть форма для обратной связи.

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

Большое спасибо за комментарии, за пояснения и за доставку обратной связи "по адресу". Это очень ценно. Также буду иметь ввиду форму обратной связи на страницах академии. 

Спасибо за полезную информацию

Друзья, нид хелп) 

Задача ровно такая же, как у Евгения.

Скрипт вот такой:

string[] placeId = Get<ICompositeObjectList<ICompositeObject>>("WebService1.AxCandidatesPlaceid");

string placeidstring = "";

string seperator = ", ";

placeidstring += String.Join(seperator, placeId);

Set("ParsedPlaceId", placeidstring);

return true;

где AxCandidatesPlaceid - текстовый параметр из коллекции входящих параметров 

 

При компиляции получаю ошибку: 

Cannot implicitly convert type 'Terrasoft.Common.ICompositeObjectList<Terrasoft.Common.ICompositeObject>' to 'string[]'

 

Подскажите, как можно исправить? Куда смотреть? 

Сергей, Вы считали объект типа ICompositeObjectList<Terrasoft.Common.ICompositeObject> и пытались автоматически преобразовать в массив строк. Если такое не предусмотрено, нужно самостоятельнообрабатывать, например, перебирая элементы коллекции и считывая значения поля, где хранится интересующий текст.

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

Добрый день!

При вызове скрипта генерирования печатной формы в бизнес-процессе он падает с ошибкой:

System.NullReferenceException: Object reference not set to an instance of an object.

   at Terrasoft.Configuration.ReportService.ReportService.GetSchemaNameByTemplateId(Guid templateId)

Определили, что это возникает только когда бизнес-процесс вызывается сигналом или событием, т.е. только тогда когда процесс запускается от имени Supervisor. Запускаем вручную - всё работает отлично.

Вопросы: как можно заменить Supervisor на другого пользователя? Или может посоветуете как получить UserConnection другого пользователя для выполнения ReportService? Возможно ли обойтись в ReportService без UserConnection?

Спасибо!

Нравится

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

а как происходит инициализация ReportService в бп?

Ранее тема обсуждалась тут и тут. В ReportService в логике функций GenerateMSWordReport или GenerateDevExpressReport есть фрагменты, которые позволяют его запускать только при работе из браузера, но не в фоновом режиме с сервера, когда UserConnection нет. В комментариях один из участников рассказал, что в итоге переделал этот сервис, чтобы не использовать UserConnection. А другой предложил запускать от имени какого-то пользователя посредством ProcessEngineService, так работает нормально.

Варфоломеев Данила,

Процесс запускается через задание-сценарий вызовом 

GenerateMSWordReport, в который передаются параметры бизнес-процесса и UserConnection

 

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

Спасибо вам за информацию!

Мы заметили, что новый функционал в 7.13.2 "Фоновое выполнение операции" предназначен для запуска фоновых задач, которые требуют UserConnection. Я правильно понимаю, что с помощью этого функционала можно создать UserConnection для передачи в GenerateMSWordReport? (https://academy.terrasoft.ru/documents/technic-sdk/7-13/fonovoe-vypolne…)

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

и может вы знаете как на время изменить в процессе системную настройку текущего системного пользователя по умолчанию с Supervisor на другого пользователя, чтобы таким образом взять его UserConnection?

Дело не в том, что это конкретно Supervisor. Если под Supervisor зайти в систему и по действию построить отчёт, всё отработает.

Варианты по ссылкам предлагались ещё до появления 7.13.2, можете проверить и этот механизм.

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

Добрый день.

Процесс -> Задание сценарий содержит некий код:

if (UserConnection.GetIsFeatureEnabled("EmailMessageMultiLanguage"))

{

    некий код...

}

else

{

    некий код...

}

При запуске данного процесса всегда отрабатывает ветка "else".

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

В профиле пользователя так же ничего похожего не обнаружил.

Нравится

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

Это Механизм отключения функциональности Feature Toggle. По ссылке написано, как менять значение пользовательскими средствами и где оно хранится в базе.

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

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

Спасибо, действительно пройдя по адресу [Адрес приложения]/0/Nui/ViewModule.aspx#BaseSchemaModuleV2/FeaturesPage

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

У меня на тестовом сайте 7.12 Sales Enterprise она есть, выключена. Возможно, зависит от версии.

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

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

Ранее в сообществе несколько раз поднимались темы использования элемента "Чтение данных" для получения "результирующей коллекции", чтобы в последствии её использовать в элементе "Задание-сценарий" для различных нужд. В версии 7.8 осталось только режимы: "читать первую запись", "считать количество записей" и "считать функцию".

Каким образом в данной версии можно получить Результирующую коллекцию? И каким образом можно к ней обратиться в элементе "Задание-сценарий"?

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

Нравится

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

Добрый день!

Пример обработки коллекции из чтения данных в ScriptTask:

EntityCollection entities = Get<EntityCollection>("ReadDataUserTask1.ResultEntityCollection");

var result = new Collection<string>();

foreach(Entity entity in entities) {

    

    var cityName = entity.GetTypedColumnValue<string>("Name");

    string temp = cityName.ToString();

    result.Add(temp);

    }

string displayValue = result.ConcatIfNotEmpty(",");

Set("MyResult", displayValue);

return true;

* MyResult - параметр процесса с типом Строка неограниченной длины

* ReadDataUserTask1 - название элемента Чтения данных

 

Олег, Спасибо!

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

Всем доброго времени суток.
Хотелось бы узнать если ли возможность в элемент бизнес-процесса "Задание-сценарий" вставить запрос к базе данных и если есть, то можно хоть самый простой пример c Select.

Нравится

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

Сергей, такая возможность есть.
Пример можно посмотреть на академии в этой статье.

Спасибо Наталия. Буду разбираться.

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

Добрый день.

Не могу понять как запустить БП из другого БП через элемент "Задание-сценарий". Подскажите, можно ли это сделать?
Так же в запускаемый процесс мне нужно передать параметр.

Нравится

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

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

Запустить БП из ScriptTask можно. Для передачи параметров необходимо использовать словарь. Пример:
DateTime someDate = Get("dateTimeParam");
IDictionary parameters = new Dictionary();
parameters["ContactNum"] = Get("ContactNum");
parameters["starttime"] = someDate.ToString();
IProcessExecutor processExecutor = userConnection.ProcessEngine.ProcessExecutor;
processExecutor.Execute("UsrSomeProcessName ", parameters);

"Зарицкий Олег" написал:Здравствуйте!

Запустить БП из ScriptTask можно. Для передачи параметров необходимо использовать словарь. Пример:
DateTime someDate = Get("dateTimeParam");
IDictionary parameters = new Dictionary();
parameters["ContactNum"] = Get("ContactNum");
parameters["starttime"] = someDate.ToString();
IProcessExecutor processExecutor = userConnection.ProcessEngine.ProcessExecutor;
processExecutor.Execute("UsrSomeProcessName ", parameters);

Спасибо. Попробовала сделать как вы сказали. В элементе "Задание-сценарий" прописала:

UserConnection userConnection=context.UserConnection;
IDictionary<string, string> parameters = new Dictionary<string, string>();
parameters["param1"] = idSale.ToString();
IProcessExecutor processExecutor = userConnection.ProcessEngine.ProcessExecutor;
processExecutor.Execute("UsrProcess23", parameters);

При сохранении и публикации процесса возникает ошибка (скриншот прикрепляю).
Не подскажите что я делаю не так?

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

Зачем придумывать велосипед? Есть элемент "Подпроцесс" - можно использовать его. Альтернативный вариант был описан в теме:
http://www.community.terrasoft.ru/forum/topic/25071

"Демьяник Алексей" написал:Зачем придумывать велосипед? Есть элемент "Подпроцесс" - можно использовать его.

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

Можете из скриптаска дернуть веб сервис, вот статья:
https://academy.terrasoft.ru/documents/technic-sdk/7-4-0/zapusk-process…

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