I am reading a collection of records, and would like to concatenate one of the fields from all the records into one long field. I tried using a sub-process to do the concatenation but it does not seem to pass anything back. Has anyone found a way to do this?

Like 0

Like

7 comments

Hi Heather, 

I usually do this in a script task with an ESQ, however, if you can set a field to flag the records you can do it in a process without coding. You can see this article for some details on how to loop in a process by flagging records: https://customerfx.com/article/how-to-loop-through-records-in-a-process…

The basic idea is:

  1. Create a process param that will hold the concatenated value
  2. Use a modify data to flag all the records you want to work with
  3. Now, read the flagged records
  4. Check if you got a record by checking if the Id != Guid.Empty
  5. Concatenate the value in the process param
  6. Unflag the record by using a modify data to un-set the field
  7. Loop back to #3

Make sure the maximum number of repetitions setting for the process is larger than the typical set of data you'd be working with. Anyway, hope this helps. Of course, doing it in code is pretty straight forward as well if you're interested in going that route I'd be happy to help.

Ryan

Ryan Farley,

Thanks for your response. I have been trying to get away from using loop flags because it causes all the records to be marked as "modified", which causes confusion about when the records were actually last modified by a user. Could you give me an example of how you do it with a script task? I have never worked with script tasks before.

Heather,

Here's an example that uses an EntitySchemaQuery to read all accounts with a type of Customer and creates a comma delimited string of the account names. When done, it puts the value in a process parameter named TextParam.

var text = "";
 
var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Account");
esq.AddColumn("Name");
 
var customerFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Type.Name", "Customer");
esq.Filters.Add(customerFilter);
 
var accounts = esq.GetEntityCollection(UserConnection);
foreach (var account in accounts)
{
	var name = account.GetTypedColumnValue<string>("Name");
	text += name + ", ";
}
text = text.Trim().TrimEnd(',');
 
Set("TextParam", text);
return true;

Hope this helps get you started.

Ryan

Ryan Farley,

Thanks so much, I was able to get that to work. Do you happen to know how to get the value from a non-Typed column? I'm assuming you have to get the GUID and then do a separate lookup from that table?

Heather,

If I am understanding you correctly, you can do that all in the same query. For example, in the example I posted, let's say you want to get the Account Owner's email address (Owner is a lookup to contact). I would add a column like this:

esq.AddColumn("Owner.Email");

Then, I could read that from the results like this (the dots are replaced with underscores):

var ownerEmail = account.GetTypedColumnValue<string>("Owner_Email");

You can go through many object relationships like this, for example Owner.City.Name, etc.

Ryan

 

Ryan Farley,

Thank you for all your help so far. I will check out the method you suggest. I got this almost working using a different method and I'm wondering if you can help with the last step. I just need to get the value of the record that I want to filter on in my script. I have tried a number of different syntax but just keep getting errors. I'm tryin gto get the UsrContact, which is a Contact Lookup record, and add that value to my SQL as the "user". I have tried it as a Guid and a string and get different errors depending on what way I do it.

 

var text = "";

var user = Get<string>("UsrContact");

var sql = "select case when cc.Name is null then ' ' else cc.Name end, "+ 

                 "case when org.Name is null then ' ' else org.Name end, "+ 

                 "case when cc.Phone is null then ' ' else cc.Phone end, "+ 

                 "case when cc.MobilePhone is null then ' ' else cc.MobilePhone end, "+ 

                 "case when freq.Name is null then ' ' else freq.Name end, "+ 

                 "case when rm. UsrLastCPIContact is null then ' ' else rm.UsrLastCPIContact end "+

            "from kwlcustomerMatrix rm "+ 

            "left outer join Contact cc on rm.KwlRCustomerContact1Id=cc.ID "+ 

            "left outer join Account org on rm.KwlCMAccountId=org.ID "+

            "left outer join KwlFrequency freq on rm.KwlExpectedMinFrequencyId=freq.ID "+

            "where rm.KwlROurcontact1Id='"+user+"'";

Actually, that issue was a silly mistake on my part. I got this working. Thank you so much for your help in this. I will post my code in case this is useful for someone else in the future.

var text = "";
Guid user = Get&lt;Guid&gt;("UsrContactGuid");
var sql = "select case when cc.Name is null then ' ' else cc.Name end, "+ 
                 "case when org.Name is null then ' ' else org.Name end, "+ 
                 "case when cc.Phone is null then ' ' else cc.Phone end, "+ 
                 "case when cc.MobilePhone is null then ' ' else cc.MobilePhone end, "+ 
                 "case when freq.Name is null then ' ' else freq.Name end, "+ 
                 "case when rm. UsrLastCPIContact is null then ' ' else convert(varchar, rm.UsrLastCPIContact, 23) end "+ 
            "from kwlcustomerMatrix rm "+ 
            "left outer join Contact cc on rm.KwlRCustomerContact1Id=cc.ID "+ 
            "left outer join Account org on rm.KwlCMAccountId=org.ID "+
            "left outer join KwlFrequency freq on rm.KwlExpectedMinFrequencyId=freq.ID "+
            "where rm.KwlROurcontact1Id='"+user+"'"+
            "ORDER BY CASE WHEN freq.Name = 'Daily' THEN '1'"+
                          "WHEN freq.Name = 'Semi-Weekly' THEN '2'"+
                          "WHEN freq.Name = 'Weekly' THEN '3'"+
                          "WHEN freq.Name = 'Monthly' THEN '4'"+
                          "WHEN freq.Name = 'Quarterly' THEN '5'"+
                          "WHEN freq.Name = 'Semi-Annually' THEN '6'"+
                          "WHEN freq.Name = 'Annually' THEN '7'"+
                          "ELSE freq.Name END ASC";
 
 
var query = new CustomQuery(UserConnection, sql);
using (var db = UserConnection.EnsureDBConnection())
{
    using (var reader = query.ExecuteReader(db))
    {
        while (reader.Read())
        {
 
            text += "&lt;tr&gt;&lt;td&gt;"+reader.GetString(0)+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;"+
                        "&lt;td&gt;"+reader.GetString(1)+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;"+
                        "&lt;td&gt;"+reader.GetString(2)+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;"+
                        "&lt;td&gt;"+reader.GetString(3)+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;"+
                        "&lt;td&gt;"+reader.GetString(4)+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;"+
                        "&lt;td&gt;"+reader.GetString(5)+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;";
 
 
 
 
 
        }
    }
}
 
text = text.Trim().TrimEnd(',');
Set("UsrEmailContentTableRows", text);
return true;

 

Show all comments

Hi Community,

 

I have a configuration Service, how can I execute my Business process inside my configuration service?

 

By the way my business process includes opening an edit page. Is this possible?

 

 

 

 

Thanks

Like 0

Like

3 comments
Best reply

Fulgen Ninofranco,

 

The problem here is that the page will be created, but it is not opened automatically and remains in the CTI-panel on this tab:

But you can open it by clicking the page name in the CTI-panel (Test in our case on the screenshot below). And it seems that it is not possible to open this page not in the background, but I've created a problem for our R&D team so they could modify the ProcessEngineService so to allow opening auto-generated and pre-configured pages not in the background in case they are called via Web-service.

 

Best regards,

Oscar

Dear Fulgen, 

 

You can use this article: https://academy.creatio.com/docs/developer/integrations_and_api/process… to launch the process from web-service.

 

Best regards,

Angela

Angela Reyes,



Hi Angela, I am able to launch the business process. I can also see it In my process log that the BP was triggered successfully. But edit page is not opening. Is it possible to launch BP with edit page via configuration service? If possible, how?

Fulgen Ninofranco,

 

The problem here is that the page will be created, but it is not opened automatically and remains in the CTI-panel on this tab:

But you can open it by clicking the page name in the CTI-panel (Test in our case on the screenshot below). And it seems that it is not possible to open this page not in the background, but I've created a problem for our R&D team so they could modify the ProcessEngineService so to allow opening auto-generated and pre-configured pages not in the background in case they are called via Web-service.

 

Best regards,

Oscar

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 created a process that is triggered when a Lead is saved, and it updates some columns in the just-saved lead. 

Is it possible to force lead edit page refresh after save ?

 

If it is not possible, an alternative could also be to force return to the section page.

Like 0

Like

2 comments

I need a single field to hold a DateTime variable.

It should be available for being read/written via business processes.

I tried to use System settings for this, but with no success; I couldn't manage a business process to set a value for a System setting.

What is the best way to keep a global variable in Creatio?

Like 0

Like

6 comments

Yurily,

A system setting is the best place for something like that. Normally, I'd use a Modify Data element in the process to write it back, but in current versions of Creatio the lookup to add columns to update causes a client-side error so you're unable to select columns. 

However, you can set it with a script task. Let's assume your value is a string value and currently in a process parameter named "MyParameterValue". You'd add code something like this to read it from the parameter and set a system setting with a code of "UsrMySetting":

var val = Get<string>("MyParameterValue");
Terrasoft.Core.Configuration.SysSettings.SetValue(UserConnection, "UsrMySetting", val);
return true;

Ryan

Ryan Farley,

Thanks for your answer. The thing I don't understand is what "Yurily" means :)

Yuriy Konstantinov,

lol, sorry for the typo Yuriy!

Ryan Farley,

Hi Ryan,

 

I'm doing this, but for some reason the updated value is not on the System Setting if I see it by the System Settings, but If I ask it on a process I get the updated number.

 

I try to explain better, I create a System Setting variable, and init it with a number, in the process I update the value of the system setting and use it for some task, but when I come back to Creatio System setting and open the System setting is just like I define it, no change, but If I ask its value from a process it's updated.

 

I think is something related with cache or whatever, did you know what could be wrong?

 

For example, the following sub process is called in a "Read collection of records" loop.

 

In the first image you can see, I get the value of the System Setting called "Incidencias Detectadas - Correlativo Histórico" and add 1 and stores it in a local parameter.

 

The initial value in the System setting is 1

 

In the next step of the sub process I did something with the value, and in the third element of the sub process I update the system setting using the updated value in step 1. ie the old number + 1

 

 

It works OK, it's fine!, but when I came to System Setting, it shows me the initial number, ie: 1 and it must be 800 to my example,

 

You can see the value still is one, but If I read the value from a process, it gives to me the correct value. WHAT'S WRONG?

 

Thanks in advance

Julio Falcón

Ryan Farley,

Does your code set the system setting for the All employees role, or specifically for whichever user triggered the BP? Is there a way to choose this? The setting we are trying to set should be a single system setting for all users, but after running the BP, it appears to be creating a system settings value record for the user who runs the BP.

Harvey Adcock,

For a non per-user setting you can use SetDefValue

Terrasoft.Core.Configuration.SysSettings.SetDefValue(UserConnection, "UsrMySetting", val);

Ryan

Show all comments

Hi Community,

I've some questions about using this business process element "Open Edit Page".

Is it possible to use this element without creating activities behind it? 

I would like to use this element in my process everytime I cancel or create a new record. Is it possible to open a new record page without creating a new activity? 

 

Thanks in Advance.

 

Best Regards,

Pedro Pinheiro

 

Like 3

Like

3 comments
Best reply

Hi Pedro,

The only other way to achieve this that comes to mind is to add a script task in your process to send a message for the user back to the client. You can see how to do that here: https://customerfx.com/article/sending-a-message-from-server-side-c-to-…

Then, in the client, you'd have to listen for that message, check to see if it is for the current user and then navigate to the record: https://customerfx.com/article/programmatically-navigating-to-a-page-in…

In order for that to work, you'd have to add your code in the client to something that is available in all pages, so you'd add it to something like MainHeaderSchema.

Ryan 

Hi Pedro,

 

Records created in the CTI-panel upon calling the "Open edit page" element are system records and disabling these system records creation is not possible in the current application logic. But we will ask our R&D team so they could add this functionality as an improvement into their functionality development roadmap.

 

Thank you for helping us to make our application better!

 

Best regards.

Oscar

Hi Pedro,

The only other way to achieve this that comes to mind is to add a script task in your process to send a message for the user back to the client. You can see how to do that here: https://customerfx.com/article/sending-a-message-from-server-side-c-to-…

Then, in the client, you'd have to listen for that message, check to see if it is for the current user and then navigate to the record: https://customerfx.com/article/programmatically-navigating-to-a-page-in…

In order for that to work, you'd have to add your code in the client to something that is available in all pages, so you'd add it to something like MainHeaderSchema.

Ryan 

Ryan Farley,

I've tried implementing your solution and it worked. Thank you.

 

Best Regards,

Pedro Pinheiro

Show all comments

Hi Community,

 

I have this situation where I need to excute some process through client side. While executing this process I want to pass a collection of ids to one of the process parameters. These ids are the Quotes that I multi-selected in the image bellow.

Pressing the  "Merge Quote" button will execute the following code.

This code will create a new collection with all the ids selected before and send them to my process. The next image shows the collection created.

I want to know which type of data should I use for my parameter in my process for this type of collection, where can I learn more about these types of collections and its methods and how can I access its values with the various process tasks?

 

For tests purposes I want to display one of the ids using a "Open Popup Window". 

 

Thanks in Advance.

 

Best Regards,

Pedro Pinheiro.

Like 1

Like

1 comments

Hello Pedro,

 

Creatio works with collections if it's needed to process such data but not to display it. You can pass items to sub_process or web_service elements or perform some script_task over it. Please refer to https://academy.creatio.com/docs/user/bpm_tools/business_process_setup/process_collections where this process is described.

 

In case if you want to work with the result of your script that returns a collection as described in your example,  you need to write it in a text string with ";" separator for Id's and then - split it on the next step to parse Id's and reflect them where you want.

 

Best regards,

Bogdan

Show all comments

Dear mates,

I build a process on the call object.

When a record is add the process should be launch.

But it never start.

it looks like the problem i all ready have with this object:

https://community.creatio.com/questions/open-call-page-after-call

Does anybody has an idea or should i call the support ?

Thank you,

Nicolas

Like 0

Like

2 comments

Hello, Nikolas,

please try removing filters from the start signal (in order to make sure that is not the reason). Thank you.

Hello Daria,

Woups, it looks like there are two Post on the same subject !

https://community.creatio.com/questions/new-calls-does-not-launch-proce…

i deleted this one but you can reach it from your side !

If you can help me i m allways looking for a solution.

Have a nice day and thank you,

Nicolas

Show all comments



Hello,

 

I've implemented a custom notification, but i've seen that there is one field : "unique caption ID" by this field I already know that there are possibilities to redirect to one contact, account, etc.

But I want to redirect the user to one folder when this user is clicking on the link of the notification

 

 

And by the way, by a second notification I want to redirect the user to one tab of the Contact's section dashboards

 

 

Is anyone knows how can I do these several things?

 

Like 0

Like

2 comments
Best reply

Hello Marvyn,

 

The difficulty here that makes this task almost impossible is that notifications were developed to open some section record, but not to select some section element (like tab or folder). Theoretically it could be done using pushing the current user back to the section of the notification record

 

(this.sandbox.publish("PushHistoryState", {

                                        hash: requestUrl

                                    })

 

and data manipulations in the SysProfileData table, but this was never tested.

 

Best regards,

Oscar

Hello Marvyn,

 

The difficulty here that makes this task almost impossible is that notifications were developed to open some section record, but not to select some section element (like tab or folder). Theoretically it could be done using pushing the current user back to the section of the notification record

 

(this.sandbox.publish("PushHistoryState", {

                                        hash: requestUrl

                                    })

 

and data manipulations in the SysProfileData table, but this was never tested.

 

Best regards,

Oscar

Oscar Dylan,

Thanks a lot for your answer, i've tested the fact that if the unique caption ID field is not completed the user will be redirected to the section of the notification..

But if you find a way in order to do this task, let me know it..



Thanks a lot.

Show all comments

Hello colleagues,

 

I have a process and some elements have a lot of parameters, I need to create another with the same parameters to get some info, and don't want to have to write all them again. Is there any way to do it?

 

Thanks in advance

Like 0

Like

4 comments

The only way to do it is to duplicate the entire process by selecting it in the process library and clicking the Copy option.

Dear Julio, 



Please see the response above from Ryan. 

The only possible way to copy all the needed parameters is to copy an entire process and then work with this copy. 



Kind regards,

Roman

Thanks or create a custom one and reuse it, in this case the element I want to reuse was a "User Task", thanks

It would be really helpful to be able to copy a single process element instead of copying an entire business process. Can this functionality be added?

 

Show all comments