Hi, 

 

I'd liket to create a script task in a business process, that given an email template, it executes it on a specific context. I mean, if the email template is based on a custom macro related with the Lead entity, I can pass the LeadID and the emailTemplateId to the script task, and the result is the text of the email template executed for that specific lead. 



Is there way to do that?



Thanks!

Ignacio 

Like 0

Like

4 comments

Hi Ignacio,

 

You can pass LeadId and the TemplateId as process parameters (create two Guid parameters in the process settings). Then you can use the "Read data" element and read specific columns of the lead record (use the LeadId parameter in the "Read data" filtration to get the value for needed columns). Then you can create additional text parameters and pass the read column values to them (using formulas for example). The same approach is for the "Email template" object and TemplateId parameter (you need to get the template body, so you need to read it in the "Read data" process element). And finally you can use string interpolation (or String.Replace method) in the script task to replace macroses (macorses, not their values, like [#UsrSomeColumn#], it's passed in the template body) with the actual values read from the "Lead" object using the "Read data" element (the ones that we wrote to the process parameters). To get process parameters values in the script task you need to use Get<string>("ParameterCode") (see more examples here) construction in the script task, then you can use String.Replace in the following manner:

string UsrStringParameterValueToUse = Get&lt;string&gt;("UsrStringParameterValue");
string EmailTemplateBody = Get&lt;string&gt;("UsrEmailTemplateBodyParamter");
EmailTemplateBody= EmailTemplateBody.Replace("[#UsrSomeColumn#]", UsrStringParameterValueToUse);

And then you can return EmailTemplateBody to some another string parameter value using Set<string> command and as a result you will get the result needed.

Thank you for your response Oleg!

 

Right, that would be the "manual" approach. I was hoping I could reuse the same service that is being used when creating an email from a template. For example, I can use a ReportService to generate a printable inside a business process. I was hoping that we have in Creatio something like "EmailService" that processes an email template and returns the generated text.

Pavel Shkomov,

 

You need to use the script-task to send the email from the code directly. Please see this Academy article that describes how to form and send the email from the code (this article also have examples of implementations, please use the "Examples" tab at the top of the article).

Ignacio Alvarez,

 

there is another approach:

var macrosHelperClassFactory = ClassFactory.Get&lt;MacrosHelperV2&gt;(new ConstructorArgument("userConnection", UserConnection));
 
string emailTemplateCode = Get&lt;string&gt;("ResultEmailTemplatePlain");
string templateEntityName = Get&lt;string&gt;("ContactEntityName");
Guid templateEntityId = Get&lt;Guid&gt;("ContactRecordId");
 
var replacementResult = macrosHelperClassFactory.GetTextTemplate(emailTemplateCode, templateEntityName, templateEntityId);
Set&lt;string&gt;("ResultEmailTemplateHTML", replacementResult);
return true;

There should be also the following parameter values:

1) the code is ContactEntityName - Text (50 characters) data type ("Contact" value by default) - represents the object from which data for macros is selected

2) the code is ContactRecordId - Unique identifier data type - represents the record Id to get data for macroses

3) the code is ResultEmailTemplateHTML - Unlimited length text data type - contains the template with filled macroses

4) the code is ResultEmailTemplatePlain - Unlimited length text data type - contains the template without filled macroses

 

Also you need to add the following namespaces to the process usings:

Terrasoft.Configuration.Utils

Terrasoft.Core.Factories

 

You need to use the "Read data" process element and read specific email template (the object is "Message template") and you need only the "Body" column value. Then the read body of the template should be passed to the "ResultEmailTemplatePlain" parameter using the "Formula" process element.

 

As a result of the script-task process element you will get the formed email template body with filled macroses in the ResultEmailTemplateHTML parameter that can be then displayed for example using the autogenerated page.

Show all comments

Hello community,

 

I have a case where based on a lookup value, I need to display an image. The code is working and logging values as expected but the image does not seem to load. When inspect HTML I find the following

[object Object]" title="">

 

and the error

https://dev2-is-il.creatio.com/0/Nui/[object%20Object] 404

 

However my method is returning the correct URL 

https://dev2-is-il.creatio.com/0/conf/content/img/UsrRequests1Page-Dril…

 

Please find the code below



Diff

{
				"operation": "insert",
				"name": "UsrProjectCategoryCaption",
				"values": {
					"itemType": 6,
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					},
					"visible":  {
						"bindTo": "IsPrjCatIconContVisible"
					},
					"caption": {
						"bindTo": "Resources.Strings.ProjectCategoryCaption"
					}
				},
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "insert",
				"name": "AccountPhotoContainer",
				"values": {
					"itemType": 7,
					"wrapClass": [
						"image-edit-container"
					],
					"items": [],
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					},
					"visible":  {
						"bindTo": "IsPrjCatIconContVisible"
					},
				},
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 1
			},
			{
				"operation": "insert",
				"name": "Photo",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 2
					},
					"getSrcMethod": "getPhotoSrcMethod",
					"readonly": true,
					/*"defaultImage": {
								"bindTo": "getPhotoSrcMethod"
					},*/
					"generator": "ImageCustomGeneratorV2.generateCustomImageControl"
				},
				"parentName": "AccountPhotoContainer",
				"propertyName": "items",
				"index": 0
			},

 

Methods

 

getPhotoSrcMethod:function()
			{
 
			    var reqId=this.get("Id"); 
				this.getProjectCategory(reqId, function(result) {
 
					 this.console.log("cbdone:" + result);
					 if(result.pjtCatId==="5f43b0aa-f7f6-4ffa-bc6d-15cf1fd581e0")
							{
								this.console.log("getIcon NationalPriorityImage");
								this.set("Resources.Strings.ProjectCategoryCaption", result.pjtCatName);
								this.set("IsPrjCatIconContVisible", true);
								this.console.log("IsPrjCatIconContVisible true");
								//class="ts-image-edit-full-size-element ts-image-style-rectangular"
 
						 		return this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.NationalPriorityImage"));
							}
						else if(result.pjtCatId==="08135814-ecdb-48ed-adea-5d4e5f1b0129")
							{
								this.console.log("getIcon BicyclePathsIcon");
								this.set("Resources.Strings.ProjectCategoryCaption", result.pjtCatName);
								this.set("IsPrjCatIconContVisible", true);
 
								return this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.BicyclePathsIcon"));
							}
						else if(result.pjtCatId==="a1a8e24d-6c6c-49ea-bb3c-5d76da662a27")
							{			   
								this.console.log("getIcon DrillingExplorationIcon");
								this.set("Resources.Strings.ProjectCategoryCaption", result.pjtCatName);
								this.set("IsPrjCatIconContVisible", true);
								this.console.log(this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.DrillingExplorationIcon")));
							//	return this.getSchemaImageUrl(this.get("Resources.Images.DrillingExplorationIcon"));
								return this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.DrillingExplorationIcon"));
 
							}
						else if(result.pjtCatId==="18588952-b4bf-4477-a614-a15a103adc28")
							{
								this.console.log("getIcon DrillimgAndNPIcon");
								this.set("Resources.Strings.ProjectCategoryCaption", result.pjtCatName);
								this.set("IsPrjCatIconContVisible", true);
 
								return this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.DrillingAndNPIcon"));
							}
						else
							{
								this.set("IsPrjCatIconContVisible", false);
								this.console.log("IsPrjCatIconContVisible is false due to regular prj 2");
								return this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.AnalyticsDataIcon"));
 
							}
 
                        },this);
 
 
			},
			getProjectCategory :function(reqId,callback,scope)
			{
				var result;
				var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
					rootSchemaName: "UsrRequests"
				});
				esq.addColumn("Id");
				esq.addColumn("UsrProject.UsrProjectCategory.Id","CatId");
				esq.addColumn("UsrProject.UsrProjectCategory.Name","CatName");
				esq.filters.add("ProjectFilter", Terrasoft.createColumnFilterWithParameter(
						Terrasoft.ComparisonType.EQUAL, "Id",reqId));
				esq.getEntityCollection(function(result) {
 
					var resultValue = result.collection.collection.items;
					var pjtCatId = resultValue[0].values.CatId;
					var pjtCatName = resultValue[0].values.CatName;
					this.console.log("pjtCatId:" + pjtCatId);
					this.console.log("pjtCatName:" + pjtCatName);
					result ={ success:true,
							  pjtCatId : pjtCatId,
							  pjtCatName:pjtCatName
							};
					callback.call(scope || this, result);
				},this);
			},

 

Like 0

Like

6 comments
Best reply

Shivani Lakshman,

Rather than bind the image element in the diff to the function (which won't work since the ESQ in the function is asynchronous), bind it to an attribute, then set the attribute in the asynchronous function (and just call the function in the onEntityInitialized).

Example:

First add the attribute:

"MyImageAttr": {
	dataValueType: Terrasoft.DataValueType.TEXT,
	type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
	value: ""
}

Then, create the function that retrieves the image using the ESQ:

function getImage() {
	// do the ESQ to get the image, then simply set in attribute
	this.set("MyImageAttr", Terrasoft.ImageUrlBuilder.getUrl(imageConfig));
}
 
// also call image from onEntityInitialized so it runs when the record is loaded
function onEntityInitialized() {
	this.callParent(arguments);
	this.getImage();
}

Now, add the image to the diff, bound to the attribute:

// image element in diff
// note "MyImageAttr" is an attribute we're binding to
{
	"operation": "insert",
	"name": "MyImage",
	"parentName": "ImageContainer",
	"propertyName": "items",
	"values": {
		"itemType": Terrasoft.ViewItemType.COMPONENT,
		"className": "Terrasoft.ImageView",
		"imageSrc": {"bindTo": "MyImageAttr"}
	}
}

Then the record loads, it will run the ESQ in the function, which will set the attribute with the image. Since the diff element is bound to the attribute, it will show the image when it is set, so it won't matter that the ESQ is asynchronous. 

Ryan

Hello Shivani,

 

As far as I remember there is no way to dynamically modify the image in the photo container from the client side code since it's strictly connected to the value stored in the "Photo" column of the object. In this case you may try modifying the photo on the server side and refresh the page if needed.

Oleg Drobina,

 

I believe we can. We have already implemented this in another section. Please see a screen grab in this link

 

https://drive.google.com/file/d/1BKT6E_azsOjjh1N9VZh0bPpfUjrttm79/view?…



We posted on the forum here because for some reason the code is not working when there is esq involved.

 

 

Shivani Lakshman,

 

Ok, I was wrong, then this is possible. Then probably the reason is that esq is asynchronous and you don't get the data needed at the moment the image should be loaded to the UI (this is the most probable reason). In this case try avoiding using esq and use some other approach.

Oleg Drobina,

 

I have used callback and when the breakpoint hits my method, the code for  

the image I need hits before the default image gets loaded. I am actually puzzled ? 

 

Can you please suggest another approach ? I don’t want to add another column because this image will be dynamic and change frequently.

 

Is there an attribute that can hold images and that can be loaded onto the UI?

 

Would appreciate your help here!

Shivani Lakshman,

Rather than bind the image element in the diff to the function (which won't work since the ESQ in the function is asynchronous), bind it to an attribute, then set the attribute in the asynchronous function (and just call the function in the onEntityInitialized).

Example:

First add the attribute:

"MyImageAttr": {
	dataValueType: Terrasoft.DataValueType.TEXT,
	type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
	value: ""
}

Then, create the function that retrieves the image using the ESQ:

function getImage() {
	// do the ESQ to get the image, then simply set in attribute
	this.set("MyImageAttr", Terrasoft.ImageUrlBuilder.getUrl(imageConfig));
}
 
// also call image from onEntityInitialized so it runs when the record is loaded
function onEntityInitialized() {
	this.callParent(arguments);
	this.getImage();
}

Now, add the image to the diff, bound to the attribute:

// image element in diff
// note "MyImageAttr" is an attribute we're binding to
{
	"operation": "insert",
	"name": "MyImage",
	"parentName": "ImageContainer",
	"propertyName": "items",
	"values": {
		"itemType": Terrasoft.ViewItemType.COMPONENT,
		"className": "Terrasoft.ImageView",
		"imageSrc": {"bindTo": "MyImageAttr"}
	}
}

Then the record loads, it will run the ESQ in the function, which will set the attribute with the image. Since the diff element is bound to the attribute, it will show the image when it is set, so it won't matter that the ESQ is asynchronous. 

Ryan

Ryan Farley,

 

Thank you for your help! Really appreciate it :)

Show all comments

Hi community,

 

I am developing an application only for the "Sales" module which includes the Sales enterprise, the sales team and the sales commerce edition. Actually, I am developing the application in a "Sales Enterprise" environment and I only have the "SalesEntepriseSoftKey_ENU" package.

 

Which should be the right package to set to work with all the Sales product versions ?

 

Many thanks for your help.

 

Best regards,

Jonathan

Like 0

Like

3 comments

Hello,

 

Please refer to this Academy article (+ this) to define the package dependencies.

 

Best regards,

Mira

hi @Jonathan,



It's recommended to have the package that has access/connected to all the base packages of the Creatio bundle. Also, the package dependency diagram in the configuration section will give insight into the structure of the package of products (Sales, Service, Marketing, Studio).







In your case (i.e., sales bundle), the package SalesEntepriseSoftKey_ENU shall be added in dependency. Please be informed that SalesEntepriseSoftKey_Obselete package shouldn't be added in dependency as this might be removed in the product updates.





BR,

Bhoobalan Palanivelu.

Bhoobalan Palanivelu,

 

Hi @Bhoobalan,

 

The problem here is that if I put the dependency on "SalesEnterpriseSoftkey_ENU" package, it will only work with the "SalesEnterprise" products of Creatio, not SalesTeam nor SalesCommerce.

 

Best regards,

Jonathan

Show all comments

Hello team,

 

I was trying to replicate account photo functionality in a custom section. I noticed that the getAccountLogo method gets called twice. Please see below screenshot (Hello from getAccountLogo is repeated twice)



This is causing errors in my functionality. Can someone please check?

Like 0

Like

1 comments

Hi,

If you want to add a photo to your custom section then there is instruction on how to do it.

Take a look at this conversation, there you can find an article and example.

Show all comments

Hello

I have a business case were the managers need to extract a report to identify the accounts and/or contacts group by user, where the user is either the owner of the record or the user to whom the record has been shared with. Please note that the records are visible by owner, that said, is a private model.

i.e

  • Contact A is owned by Sales Rep 1 (only that sales rep has visibility on it)
  • Sales Rep 1 shares contact A with the Sales Rep 2 granted read-only rights (now both Sales Rep 1 and Sales Rep 2 can see the record)
  • Both sales reps have the same manager
  • Manager wants to have a list grouped by sales rep to track which are the records they have to work on. Expected result should be as follows:
    • Sales Rep 1: Contact A, Contact M, Contact Z
    • Sales Rep 2: Contact A, Contact X, Contact L

Any help on how to achieve above will help me a lot! 

 

Thanks!

 

Like 0

Like

2 comments
Best reply

Hi Adriana, 

 

You can create VIEW in the database (Access rights to Contact are stored in the table SysContactRight) and object based on that view. Then you can use this object for report or for tagging records.



A little bit more complicated situation is when record has access rights for group (e.g. All Employees). That means that this record is shared with more users and you need to calculatate all of them

 

Hi Adriana, 

 

You can create VIEW in the database (Access rights to Contact are stored in the table SysContactRight) and object based on that view. Then you can use this object for report or for tagging records.



A little bit more complicated situation is when record has access rights for group (e.g. All Employees). That means that this record is shared with more users and you need to calculatate all of them

 

Hello Vladimir

Thank you so much for your reply, I have also consulted internally and I got the same solution so I guess thats the best alternative!

Show all comments

We're looking for a way to link a document that is loaded into Creatio in an email template that is sent. 

 

For example, a contract is uploaded into the Attachments section of an Opportunity. The Opportunity is won, and a notification email goes out to specified users. The email includes information from the record, but also a link to the document within the Attachments section. 

Like 2

Like

1 comments

Hello Susan,

 

Your business task can be achieved via custom business process. You'd need to use [Process file] and [Send email] elements to achieve this business task. 

More detailed information about these elements can be found on our Academy:

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

https://academy.creatio.com/docs/7-17/user/bpm_tools/process_elements_r…



Best regards,

Anastasiia

Show all comments

Dear,

I would like to display a field on the timeline of email activity on the account page.

On my activity custom object, i have add fields : dateRead, dateClick, dateBounce…

For example i would like to display dateClick if it is filled in.

So to know more about the account tile :

select *, [Data], cast('' as xml).value('xs:base64Binary(sql:column("Data"))', 'varchar(max)')

from TimelinePageSetting

if i decode the base64 account page result :

[
                                 {
                                               "entityConfigKey": "706f803d-6a30-4bcd-88e8-36a0e722ea41",
                                               "entitySchemaName": "Activity",
                                               "referenceColumnName": "Account",
                                               "masterRecordColumnName": "Id"
                                 },
                                 {
                                               "entityConfigKey": "09a70391-b767-40ab-97b8-6d1b538adbe6",
                                               "entitySchemaName": "Activity",
                                               "typeColumnName": "Type",
                                               "typeColumnValue": "e2831dec-cfc0-df11-b00f-001d60e938c6",
                                               "referenceColumnName": "Account",
                                               "masterRecordColumnName": "Id"
 
                                 }, …

I have two activity results.

The email tile activity seems to be the second line.        

select Name, [Data],cast('' as xml).value('xs:base64Binary(sql:column("Data"))', 'varchar(max)')
from TimelineTileSetting

 

After decode, here’s the json in the db :

{
 
                "entitySchemaName": "Activity",
                "typeColumnValue": "e2831dec-cfc0-df11-b00f-001d60e938c6",
                "viewModelClassName": "Terrasoft.UsrEmailTimelineItemViewModel",
                "viewClassName": "Terrasoft.UsrEmailTimelineItemView",
                "orderColumnName": "SendDate",
                "authorColumnName": "SenderContact",
                "messageColumnName": "Body",
                "filters": {
                               "ownerFilter": {
                                               "comparisonType": 15,
                                               "existsFilterColumnName": "[ActivityParticipant:Activity].Id",
                                               "subFilterColumnName": "Participant"
                               }
                },
                "columns": [{
                               "columnName": "Title",
                               "isSearchEnabled": true,
                               "columnAlias": "Subject"
                },{
                               "columnName": "Sender",
                               "columnAlias": "AuthorEmail"
                },{           "columnName": "Recepient",
                               "columnAlias": "RecipientEmail"
                },{           "columnName": "Contact",
                               "columnAlias": "Recipient"
                }]
}

I have changed

"viewModelClassName": "Terrasoft.EmailTimelineItemViewModel",

"viewClassName": "Terrasoft.EmailTimelineItemView",



by

"viewModelClassName": "Terrasoft.UsrEmailTimelineItemViewModel",

"viewClassName": "Terrasoft.UsrEmailTimelineItemView",

(to update :

UPDATE TimelineTileSetting
SET
Data=convert(varbinary(MAX),'{VAR json}')
WHERE Id='{VAR Id}'

)

I copied objects EmailTimelineItemViewModel and EmailTimelineItemView to UsrEmailTim…

But modifications i do on this two new objects are not displayed in the tile.

Did i do something wrong ?

Thank you !

Nico

Like 0

Like

2 comments

Sorry for the inconvenience, but it actually works fine.

it would be nice to have an interface to manage the tiles

Hi Nicolas, 

Thank you for this example and a new idea, we will give it to our developers.

Thank you for helping us make the system better.

Show all comments

Dear Creatio Community,

 

when linking a mail to a record a pop-up shows up and asks the user if he wants to "Link all emails from the conversation with this record?".

We don't seem to fully understand the meaning of this message. If the user clicks "yes" it appears like all e-mails from this e-mail address are also linked with the same record...

Could someone please explain the function of this pop-up?

Is it possible to disable it when linking a mail to a record?

 

Kind regards,

Markus Kumpfmüller

Like 0

Like

1 comments

Dear Marcus,

 

Thanks for your question.

 

The pop-up message 'Link all emails from the conversation with this record?' should show the emails that are on the thread only.

 

If it appears that all the user's emails are linked with a record, please contact us at support@creatio.com and provide us with access to:

 

the website the issue occurred;

 

examples of emails that appeared in the record which are in and not in the thread.

 

This functionality is a part of the core logic that is not connected to any feature or system setting, and as for now, there is no way to disable it in the application. 



We've created a problem for our R&D team so they could add either a feature or a system setting that could allow disabling this functionality. Thank you for reporting this issue to us and for helping us to make our application better!

 

Best regards,

Anastasiia

Show all comments

Hi,

 

We need to notify the admin if any user exports data using Export to Excel option. I have created a small business process to create the notification. I need to call this business process when someone exports the data. I see the exportToExcelFile() in Data Utilities that calls ReportService to generate the report, but not sure how to override this function to call the process after the service is called. Any help is much appreciated. 

Like 1

Like

4 comments

Hi,

You can add replacing module to the schema BaseDataView and call your business-process in the method exportToExcel.

 define("BaseDataView", [], function() {
	return {
		messages: {},
		mixins: {},
		methods: {
			exportToExcel: function() {
				this.callParent(arguments);
 				console.log("Test!!!!");
			}
		},
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
	};
});

Example of how to run a process you can find here.

Dmytro Vovchenko,

Thank you Dmytro! 

I already tried this. But the problem is that if the user does not have the Export Permission, this function still executes and the process runs to notify the admin that the user exported when in reality he could not. 

I saw the exportToExcelFile() in Data Utilities where the actual service ReportService is getting called. Will probably need to add the process call there to ensure the process is called only when the file is downloaded. But I'm not sure how to replace that module. I am unable to find that in the parent list in Replacing View Model. Please provide your insights. 

 

Regards,

Nirupama Mohan Latha,

 

hello! You can add your own operation permission check using the RightUtilities module and the checkCanExecuteOperations method inside the replaced exportToExcel method and trigger or not trigger the process as a result of this check.

Oleg Drobina,

Thank you Oleg! I can try that but will it also work when trying to export from Detail grids? When I tested I did not see this function getting executed. Let me know if I'm missing something.

Show all comments

I Have a detail where the copy ,edit and delete options must be hidden to all users except for the system administrator. Can someone help?

Thanks

Like 0

Like

1 comments

Hello Yasaswini,

 

This can be achieved only by means of development. You can find some examples here on our Community posted by other participants: 

https://community.creatio.com/questions/hide-detail-grid-menu-options

https://community.creatio.com/questions/hide-bunisess-process-option-de…

 

Best regards,

Bogdan S.

Show all comments