При попытке добавления блока с пользовательским кодом возникает ошибка

An attempt to add a script task causes an error

System.InvalidCastException: Specified cast is not valid.
   at Terrasoft.Core.Process.ProcessModel.GetParameterValue[T](FoundParameterData result)
   at Terrasoft.Core.Process.Process1MethodsWrapper.ScriptTask1Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessScriptTask.InternalExecute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Сам код в блоке выглядит так: 

The code itself looks as following:

double result = Get<double>("amount") * Get<float>("rate") / Get<int>("division");
Set("result", result);
return true;

У меня нет опыта работы с BPMN, поэтому я не знаю, где именно я ошибся. Всё, что делают формулы - это запись данных из справочника в параметры процесса.

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

I'm totally new to BPMN so I have no idea where the error may be. The formulas only save lookup values into process parameters. 

Thanks in advance!

File attachments
Like 0

Like

2 comments

By the way, if there is a list of data type matches for decimal values (as I understood, float does not match all of them), I would really appreciate a link.

Кстати, если существует список соответствий типов данных для дробных значений (как я понял, float подходит не для всех), я был бы очень благодарен за ссылку.

Я нашёл необходимый тип данных, им оказался decimal. Вопрос можно закрыть

Вот ссылка на перечнь соответствующих типов:

Элемент процесса [Задание-сценарий] | Creatio Academy (terrasoft.ru)

I've found the necessary data type, it turned out to be decimal.

Above there is a link to a list of data type matches

Show all comments

Hi All,

Can some one suggest a better approach to loop through multiple records and modify them. Please note that the trigger is coming from Signal (Record Added).

 

Basically, I am trying to add multiple records using Multi-select lookup detail built using LookupMultiAddMixin.

Reference - https://academy.creatio.com/documents/technic-sdk/7-15/adding-multiple-records-detail?_ga=2.11560502.366292848.1628844467-134737415.1626226816 

This is configured in a custom detail and on add, business process places that many number of rows to that detail. Now based on the detail object specific column value, I want to update all the contact records that is mapped with that detail.

 

But what I notice is it is updating only 1 record. Kindly suggest how this could be achieved.

 

Like 0

Like

2 comments

Hi Anupama, 





 

One of the ways to create a loop in your process to work with the collection of records is  to create a sub-process and pass the collection into the subprocess. 

You can refer to the example below and create the process you need: 

 

 

Signal "Contact Added" element: 

Read Data "Read Contact" element:

 

 

For the sub-process, you would need to specify the [Parameters] of it:

 

 

And make a filter of the element within the sub-process based on the ID:

And finally, you would need to specify this parameter in the parent Business Process:

 

 

You may also find these academy Articles useful:

 

https://academy.creatio.com/docs/user/bpm_tools/process_elements_refere…

 

https://academy.creatio.com/docs/user/bpm_tools/bpm_process_examples/us…

 

Hope this helps!

 

Thank you!

 

Regards,

Yurii

Danyil 

Thanks Yurii Sokil for the detailed instruction and the sequential  Execution Mode is something I haven't tried it before. Would definitely try that.

 

In between I tried another approach where-in at the entry point where the Signal action is placed, I unchecked the option of "Run following elements in the background". With this, until the process is completed, I was able to read the required values and add/edit/delete multiple records.

 

 

Show all comments

Hi,

Let's say that I use a script task to get a request from a third party application and that request sends creatio a json with arrays.

 

What I need to do is to insert that data into some tables.

 

Can I pass the array to a collection parameter and then use it in my business process or do I need to insert the data via sql in the script task?

 

Thanks,

Raz

Like 0

Like

1 comments

Hi Raz, 

 

In fact, an array will work almost the same as a collection, so it doesn't make any sense to pass array into collection, but in this case you need to read this json data and then pass it through the collection for your further actions.

 

Please check out some practical examples of how to read and update data in script task: 

 



https://community.creatio.com/questions/use-script-task-update-column-r…

 

https://community.creatio.com/questions/use-collection-parameter-script…

 

https://community.creatio.com/articles/solved-code-how-send-http-post-r…

 

 

Regards, 

 

Bogdan L.

 

 

Show all comments

Hi,

 

I have a business process where I need to read the read element values in a script task.

When the read element is set to "read a collection of records" I'm using the following code:



var AccountsData = Get>("ReadDataUserTask12.ResultCompositeObjectList");

var AccountData = AccountsData.First();



var AccountAddress="";

AccountData.TryGetValue("Address", out AccountAddress);

 

What change do I need to do when the read element is set to "read the first record"?

 

Thanks,

Raz

 

 

Like 0

Like

3 comments

 

 

 

 

 

 

 

 

string name = string.Empty;
string email = string.Empty;
Guid RecordId = Guid.Empty;
 
/**
 * This approach should not be used in production
 * Please create process parameters and set values with standard tools (i.e. Formula)
 * ReadDataUserTask1 is the Code of "Read One Contact" element
 */
var re = context.Process.FindFlowElementByName("ReadDataUserTask1").GetPropertyValue("ResultEntity");
 
if (re.TryGetPropertyValue("Email", out object _email))
{
	email = _email.ToString();
}
 
if (re.TryGetPropertyValue("Name", out object _name))
{
	name = _name.ToString();
}
 
if (re.TryGetPropertyValue("Id", out object _id))
{
	if(Guid.TryParse(_id.ToString(), out Guid Id))
	{
		RecordId = Id;
	}
}
 
//Set values to process parameters
Set&lt;string&gt;("Name", name);
Set&lt;string&gt;("Email", email);
Set&lt;Guid&gt;("RecordId", RecordId);
 
return true;

 

 

 

Kirill Krylov CPA,

Hi Kirill,

 

I don't understand you code.

So if shouldn't use this code in production.

 

what should I do?

 

I don't manage to get the values from ResultEntry.

 

Thanks,

Raz

Kirill Krylov CPA,

Your code is exactly what I need if I don't want to use "get a set of records" and if I don't what to use the "Formula" process element.

Why not to use it in production?

Show all comments



Dear Community,

 

I am trying to copy values from a field and lookups to put it in the "Name" fields before saving.

I use the following code in the script task but I don't know how to get the value from a lookup:

Entity.Name = $"{Entity.Code } - {Entity.Description}";

Code being the lookup.



So if you create a record in a lookup it would go like this:

[Name][Code][Description]

[           ][ 001 ][Code for info]



The Name should automatically be filled with "001 - Code for info" after saving.

What is the correct way to set the script?

Thank you!

 

 

Kind regards,

Yosef

 

Like 0

Like

2 comments

Hi!

 

Just add on saving event in your lookup entity, and add a script

 

Entity.SetColumnValue("Name", string.Format("[{0}][{1}]", Entity.GetTypedColumnValue&lt;string&gt;("Code"), Entity.GetTypedColumnValue&lt;string&gt;("Descritpion"));

 

Dmytro Oliinyk,

 

 

Thank you but that didn't seem to work for me, this was the solution for me:

 

var name = Entity.GetColumnValue("Name");
var description = Entity.GetColumnValue("Description");
 
var esq = new EntitySchemaQuery(Entity.Schema);
esq.AddColumn("Code.Name");
 
var CodeEntity= esq. GetEntity(UserConnection, Entity.PrimaryColumnValue);
if (CodeEntity != null) {
 
	var columnUsrCodeName = CodeEntity .GetTypedColumnValue&lt;string&gt;("Code_Name");
 
	string fullName= $"{name}: {columnUsrCodeName } - {description}";
	Entity.SetColumnValue("Name", fullName);
}
return true;

Let me know if there's an easier way to do this.

 

 

Kind regards,

Yosef

Show all comments

I have a business process that reads a collection of data.

Two of the fields that are being read are datetime fields.

Because the read data process reads many rows, I'm reading those rows in a script task and using the following code:

 

var ProductLines = Get>("ReadDataUserTask1.ResultCompositeObjectList");

    foreach(var ProductLine in ProductLines) {

 

It's very important to understand that inside the foreach loop I'M NOT TRYING TO GET THE DATETIME FIELDS, BUT OTHER STRING TYPE FIELDS.

 

Once I run the process I get the following error message:

Terrasoft.Common.UnsupportedTypeException: Type "System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" is not supported.

   at Terrasoft.Common.CompositeObject.Add(String key, Object value)

   at Terrasoft.Common.CompositeObjectListUtilities.Transform(ICompositeObject source, IReadOnlyDictionary`2 keyMap)

   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()

   at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)

   at Terrasoft.Common.CompositeObjectListUtilities.Transform[T](IEnumerable`1 source, IReadOnlyDictionary`2 keyMap)

   at Terrasoft.Core.Process.Configuration.ReadDataUserTask.FillResultCompositeObjectList(IProcessParametersMetaInfo schemaElement, EntityCollection entityCollection)

   at Terrasoft.Core.Process.Configuration.ReadDataUserTask.InternalExecute(ProcessExecutingContext context)

   at Terrasoft.Core.Process.ProcessActivity.ExecuteElement(ProcessExecutingContext context)

   at Terrasoft.Core.Process.ProcessActivity.ExecuteItem(ProcessExecutingContext context)

   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

 

I'm looking forward to having your assistance with the issue.

 

Best Regards,

Raz

Like 0

Like

1 comments

Hi Raz, 

 

Could you please provide a full script-task code you use so we will be able to test it at our end?

 

Regards,

Anastasiia

Show all comments

we have a custom button on the section page that triggers a process.

When the business process returns to the section page code, is it possible to capture a return parameter from the process  ? how ?

Like 0

Like

1 comments

The issue is that the process will execute asynchronously. The only way to get the value back from the process is, instead of using it as an output param, to send it as a message using a script task in the process that you will retrieve with client-side code on the page. 

You can see an article outlining how to do this here: https://customerfx.com/article/sending-a-message-from-server-side-c-to-…

 

Basically, at the end of your process, you'll add a script task. In that script task you'll get the param value, then send it as a message (as outlined in the article). Then, in your page code, you'll listen for that message, check to make sure it's the message sent from your process, and then read the value and do whatever is needed with it.

Ryan

Show all comments

What is the data type to read a date parameter in a script task ?

 

var myVar = Get<????>("MyParameter") 

 

Like 0

Like

3 comments
Best reply

You would use:

 

var myDate = Get<DateTime>("MyDateParam");

 

A date only param is still just a .NET DateTime struct just like a Date and Time value in Creatio -  A date only will just have a zero time value (so the value would be something like "Oct 29, 2020 00:00:00")

Ryan

You would use:

 

var myDate = Get<DateTime>("MyDateParam");

 

A date only param is still just a .NET DateTime struct just like a Date and Time value in Creatio -  A date only will just have a zero time value (so the value would be something like "Oct 29, 2020 00:00:00")

Ryan

Hi Ricardo,

 

Indeed, you can use the solution suggested above. However, please note that you'll get the date in a server timezone.

var myDate = Get<DateTime>("MyDateParam");

 

There is an option to pass a string as usual and parse it then. Also, you can pass ticks and use the result. For example: 

long ticks = Get<long>("MyDateParameterInTicks");

new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();

 

Please read more about ticks property by the link below:

https://docs.microsoft.com/en-us/dotnet/api/system.datetime.ticks?view=…

 

Regards,

Anastasiia

Anastasiia Markina,

That is good to know, thanks Anastasiia.

Show all comments

Hi. I am getting the this error :

When I compile the script task:

What is missing ? Please help.

Like 0

Like

4 comments

IIRC the DataValueType param expected here isn't an enum. Try changing the code to add this:

var dataValueTypeManager = (DataValueTypeManager)userConnection.AppManagerProvider.GetManager("DataValueTypeManager");
var textDataValueType = (TextDataValueType)dataValueTypeManager.GetInstanceByName("Text");

 

Then use:

storedProcedure.WithOutputParameter("res_msg", textDataValueType);

Ryan

Ryan Farley,

Thanks. Now it runs.

But sorry, I still need some help on recovering the output prm from the stored procedure. It always returns "Core.DB.QueryParameter", instead of the string returned by the SP.

 

Ricardo Bigio,

You can capture that using this:

var resultParameter = (string)storedProcedure.Parameters.FindByName("res_msg").Value;

Ryan

Perfect. Thanks

Show all comments

Hi,

For a few weeks I struggled with sending a HTTP POST Request to a third party application via script task.

I have a collection object that needs to be sent via the web service and eventually catch the response and use the data inside process parameters.

 

Here you can find the code for doing that using a JSON object.

 

string x_param = Get("x_process_param");

string y_param = Get("y_process_param");

string z_param = Get("z_process_param");



var ProductLines = Get>("ReadDataUserTask6.ResultCompositeObjectList");

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://url/api/v1/Documents/?token="+x_param);

httpWebRequest.ContentType = "application/json";

httpWebRequest.Method = "POST";

int ProductLineIndex = 0;

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))

using (JsonTextWriter writer = new JsonTextWriter(streamWriter))

{

    JObject InvoiceJSon = new JObject (

                            new JProperty("y",y_param),

                            new JProperty("z",z_param));

                            

    JArray JProductLinesArray = new JArray();

    foreach(var ProductLine in ProductLines) {

        

        var ProductName = "";

        decimal Qty;

        decimal UnitPrice;

        

        ProductLine.TryGetValue("Name", out ProductName);

        ProductLine.TryGetValue("Quantity", out Qty);

        ProductLine.TryGetValue("Price", out UnitPrice);

        

        JProductLinesArray.Add(new JObject(

            new JProperty("ChargeVAT","true"),

            new JProperty("Number",++ProductLineIndex),

            new JProperty("ProductName",ProductName),

            new JProperty("Qty",Qty),

            new JProperty("Rate",1),

            new JProperty("UnitPrice",UnitPrice),

            new JProperty("VATRate",17)));

    }                        

    

    InvoiceJSon.Add(new JProperty("DocumentLines",JProductLinesArray));

    

    InvoiceJSon.WriteTo(writer);

    

}



var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();

using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))

{

    var result = streamReader.ReadToEnd();

    var LinkToPdf = JObject.Parse(result)["LinkToPdf"].ToString();

    var CaspitDocNum = JObject.Parse(result)["Number"].ToString();

    

    Set("DocLinkToPdf",LinkToPdf);

    Set("FinanceDocId",DocNum);

}

return true;

 

Furthermore, I attached a screenshot with the methods that I'm using in the process

 

Hope it helps.

 

Have fun :)

Good luck

 

Like 1

Like

Share

2 comments

Hi!

 

Thank you for contacting us! 

 

Could you please provide us with additional screenshots of the issue appeared to understand the case better?

 

Regards, 

Anastasiia

Anastasiia Markina,

Hi Anastasiia,



There is no issue. I struggled with this issue and I solved it.



The above code is my collaboration to the community :)

 

Hope it helps devs with the same issue.

 

Best Regards,

Raz

Show all comments