Hi Team,



We are able to update the global search result for a few of the OOTB object schemas by replacing the corresponding module such as AccountSearchRowSchema and for contacts - ContactSearchRowSchema.



a)OOTB object schema,

Contact, Account



https://community.creatio.com/questions/modify-global-search-result



b)I couldn't find any schema as BankCardSearchRowSchema for the OOTB object

BankCard.  How to get this XSearchrowSchema generated?

No details on BankCardSchema



Please note the indexing for the object BankCard is enabled and the results are retrieved but wanted to update the result for this object. Unable to find 

 



Any help would be greatly appreciated!





Best Regards,

Bhoobalan P.

Like 0

Like

13 comments
Best reply

Hi Bhoobalan,

 

You can track if the global search results for the section uses its own SearchRowSchema or the BaseSearchRowSchema using the query below (MS SQL):

SELECT
	sme.Id, sme.ActionKindName, ss.[Name], ss.[UId]
FROM 
	SysModuleEdit sme
JOIN 
	SysSchema ss
ON
	sme.SearchRowSchemaUId = ss.UId
WHERE
	sme.SearchRowSchemaUId IS NOT NULL

But you can create a custom SearchRowSchema module for some section that doesn't have its own SearchRowSchema. The example below is for Documents section that also doesn't have its own SearchRowSchema module.

 

Here is the screenshot of the base result that the Global Search returns when searching a document:

Let's say we want to add the "Status" column to the search result (the one from the screenshot below):

To achieve this:

 

1) Create the "Page view model" in configurations with "UsrDocumentSearchRowSchema" code, "Document search row" name and select BaseSearchRowSchema as a parent:

2) Specify the following code in this schema:

define("UsrDocumentSearchRowSchema", [], function() {
	return {
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"parentName": "DataContainer",
				"propertyName": "items",
				"name": "State",
				"values": {
					"layout": {
						"column": 4,
						"row": 0,
						"colSpan": 12
					}
				}
			}
		]/**SCHEMA_DIFF*/
	};
});

and save the schema.

 

3) Find the SysModuleEdit record related to the Documents section (for example using the query below):

SELECT
	*
FROM
	SysModuleEdit
WHERE 
	ActionKindName = 'Document'

and then update the value for the "SearchRowSchemaUId" column in this record:

UPDATE 
	SysModuleEdit
SET 
	SearchRowSchemaUId = '63388eba-74f2-4bc4-85f2-e6c326adb3e5'
WHERE
	Id
IN
	(
		SELECT 
			Id
		FROM 
			SysModuleEdit
		WHERE
			ActionKindName = 'Document'
	)

4) Refresh the page and check the result. The "Status" column should appear in the SearchRowSchema for documents:

Same operation can be performed to any section needed.

 

Best regards,

Oscar

Hi Bhoobalan,

 

You can track if the global search results for the section uses its own SearchRowSchema or the BaseSearchRowSchema using the query below (MS SQL):

SELECT
	sme.Id, sme.ActionKindName, ss.[Name], ss.[UId]
FROM 
	SysModuleEdit sme
JOIN 
	SysSchema ss
ON
	sme.SearchRowSchemaUId = ss.UId
WHERE
	sme.SearchRowSchemaUId IS NOT NULL

But you can create a custom SearchRowSchema module for some section that doesn't have its own SearchRowSchema. The example below is for Documents section that also doesn't have its own SearchRowSchema module.

 

Here is the screenshot of the base result that the Global Search returns when searching a document:

Let's say we want to add the "Status" column to the search result (the one from the screenshot below):

To achieve this:

 

1) Create the "Page view model" in configurations with "UsrDocumentSearchRowSchema" code, "Document search row" name and select BaseSearchRowSchema as a parent:

2) Specify the following code in this schema:

define("UsrDocumentSearchRowSchema", [], function() {
	return {
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"parentName": "DataContainer",
				"propertyName": "items",
				"name": "State",
				"values": {
					"layout": {
						"column": 4,
						"row": 0,
						"colSpan": 12
					}
				}
			}
		]/**SCHEMA_DIFF*/
	};
});

and save the schema.

 

3) Find the SysModuleEdit record related to the Documents section (for example using the query below):

SELECT
	*
FROM
	SysModuleEdit
WHERE 
	ActionKindName = 'Document'

and then update the value for the "SearchRowSchemaUId" column in this record:

UPDATE 
	SysModuleEdit
SET 
	SearchRowSchemaUId = '63388eba-74f2-4bc4-85f2-e6c326adb3e5'
WHERE
	Id
IN
	(
		SELECT 
			Id
		FROM 
			SysModuleEdit
		WHERE
			ActionKindName = 'Document'
	)

4) Refresh the page and check the result. The "Status" column should appear in the SearchRowSchema for documents:

Same operation can be performed to any section needed.

 

Best regards,

Oscar

Oscar Dylan,

 

This is informative and thanks for sharing the steps!



I have an issue,



By default, the card search is working for the BankCard object in the customer journey bundle but one of the values shows as (not filled in)



a) Bound values not shown



b) When clicked on (not filled in) it opens the record and the top left label is filled in as depicted below,





I have ran the re-indexation, but still the value is not shown in UI.



Any help would be higly appreciated!







Best Regards,

Bhoobalan Palanivelu.

Bhoobalan Palanivelu,

 

Please send a complete code of the SearchRowSchema of the BankCard schema.

 

Best regards,

Oscar

Oscar Dylan,

Thanks for the quick response!



Unfortunately, there is no SearchRowSchema of the BankCard schema.



I have enabled the indexed in BankCard section and the result appears but there is no trace for "SearchRowSchema".

 



Also, I ran the query to track the schema of Global search below is the result

 

Attaching the "BaseSearchRowSchema" of Customer journey bundle,

define("BaseSearchRowSchema", ["NetworkUtilities", "ConfigurationEnums", "EmailHelper", "GlobalSearchViewGenerator",
	"MiniPageUtilities"], function(NetworkUtilities, ConfigurationEnums, EmailHelper) {
	return {
		hideEmptyModelItems: true,
		attributes: {
			/**
			 * Schema view config.
			 */
			"ViewConfig": {
				dataValueType: Terrasoft.DataValueType.CUSTOM_OBJECT
			},
			/**
			 * Array of found column names.
			 */
			"FoundColumnsCollection": {
				dataValueType: this.Terrasoft.DataValueType.COLLECTION
			},
			/**
			 * Entity schema caption.
			 */
			"EntitySchemaCaption": {
				"dataValueType": Terrasoft.DataValueType.TEXT,
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
			},
			/**
			 * Primary column url value.
			 */
			"PrimaryColumnURL": {
				"dataValueType": Terrasoft.DataValueType.TEXT
			}
		},
		mixins: {
			MiniPageUtilities: "Terrasoft.MiniPageUtilities"
		},
		methods: {
 
			/**
			 * Returns state object module id for edit page.
			 * @private
			 */
			_getStateObjModuleId: function() {
				return Ext.String.format("{0}_{1}_{2}", this.sandbox.id,
					this.entitySchemaName, this.get(this.primaryColumnName));
			},
 
			/**
			 * @private
			 */
			_initTypedColumnValue: function (callback, scope) {
				const typeColumnName = this.get("TypeColumnName");
				if (typeColumnName && !this.get(typeColumnName)) {
					NetworkUtilities.getAttributeValueByRecordId({
						entitySchemaName: this.entitySchemaName,
						entityId: this.get(this.primaryColumnName),
						attribute: typeColumnName
					}, function(typedValue) {
						this.set(typeColumnName, { value: typedValue });
						Ext.callback(callback, scope);
					}, this);
				} else {
					Ext.callback(callback, scope);
				}
			},
 
			/**
			 * @inheritdoc Terrasoft.BaseSchemaViewModel#init
			 * @overridden
			 */
			init: function(callback, scope) {
				const parentMethod = this.getParentMethod();
				Terrasoft.chain(
					function(next) {
						parentMethod.call(this, next, this);
					},
					this._initTypedColumnValue,
					function() {
						this.initEditPages();
						this.initMultiLookup();
						this.initAttributeValues();
						Ext.callback(callback, scope);
					}, this
				);
			},
 
			/**
			 * Fills lookup field.
			 * @param {String} name Entity schema name
			 * @param {String} value Entity value.
			 * @param {Function} callback Callback-function.
			 * @param {Object} scope Execution context.
			 */
			loadLookupDisplayValue: Terrasoft.emptyFn,
 
			/**
			 * @inheritdoc Terrasoft.BaseSchemaViewModel#sendGoogleTagManagerData
			 * @overridden
			 */
			sendGoogleTagManagerData: Terrasoft.emptyFn,
 
			/**
			 * Initializes viewmodel attributes.
			 * @protected
			 */
			initAttributeValues: function() {
				this.initSchemaCaption();
				this.set("PrimaryColumnURL", this.getPrimaryColumnURL());
			},
 
			/**
			 * Initializes entity schema caption.
			 */
			initSchemaCaption: function() {
				this.set("EntitySchemaCaption", this.entitySchema && this.entitySchema.caption || "");
			},
 
			/**
			 * Returns eintity image url or section logo url or default image url.
			 * @protected
			 * @return {String} Image url.
			 */
			getImage: function() {
				var primaryImageColumnValue = this.get(this.primaryImageColumnName);
				if (primaryImageColumnValue && primaryImageColumnValue.value) {
					return this.getSchemaImageUrl(primaryImageColumnValue);
				}
				var moduleStructure = this.getModuleStructure(this.entitySchemaName);
				if (moduleStructure && moduleStructure.logoId) {
					return this.Terrasoft.ImageUrlBuilder.getUrl({
						source: Terrasoft.ImageSources.SYS_IMAGE,
						params: {
							primaryColumnValue: moduleStructure.logoId
						}
					});
				}
				return this.getDefaultImage();
			},
 
			/**
			 * Returns default image url.
			 * @protected
			 * @return {String} Default image url.
			 */
			getDefaultImage: function() {
				return this.Terrasoft.ImageUrlBuilder.getUrl(this.get("Resources.Images.DefaultSearchImage"));
			},
 
			/**
			 * Returns primary display column value.
			 * @protected
			 * @returns {String} Primary display column value.
			 */
			getPrimaryDisplayColumnValue: function() {
				var notFilledValue = this.get("Resources.Strings.NotFilled");
				if (this.primaryDisplayColumnName) {
					return this.get(this.primaryDisplayColumnName) || notFilledValue;
				}
				return notFilledValue;
			},
 
			/**
			 * Returns primary display column caption.
			 * @protected
			 * @returns {String} Primary display column caption.
			 */
			getPrimaryDisplayColumnCaption: function() {
				if (this.primaryDisplayColumnName) {
					var primaryColumn =  this.columns[this.primaryDisplayColumnName];
					return primaryColumn.caption;
				}
				return "";
			},
 
			/**
			 * Returns found column items view config.
			 * @private
			 * @return {Array} Found column items view config.
			 */
			getFoundColumnItemsConfig: function() {
				var columnNames = this.getAdditionalColumnNames();
				var items = [];
				Terrasoft.each(columnNames, function(columnName) {
					var columnContainer = {
						"id": columnName + "Container",
						"className": "Terrasoft.Container",
						"items": []
					};
					var column = this.getColumnByName(columnName) || this.get(columnName);
					var caption = column && column.caption || columnName;
					var value = this.get(columnName);
					if (this.isNotEmpty(value)) {
						columnContainer.items.push({
							"className": "Terrasoft.Label",
							"classes": {"labelClass": ["found-column-caption"]},
							"caption": caption
						});
						columnContainer.items.push({
							"className": "Terrasoft.Label",
							"classes": {"labelClass": ["found-column-value"]},
							"caption": value.displayValue || value,
							"highlightText": this.getHighlightText(columnName)
						});
						items.push(columnContainer);
					}
				}, this);
				return items;
			},
 
			/**
			 * Returns found columns.
			 * @private
			 * @return {Object} Found columns array.
			 */
			getFoundColumns: function() {
				var foundColumnsCollection = this.get("FoundColumnsCollection");
				return foundColumnsCollection.getByIndex(0).get("FoundColumns");
			},
 
			/**
			 * Returns additional column names for view searcg result.
			 * Gets not showed found column names.
			 * @private
			 * @return {String[]} Not showed found column names.
			 */
			getAdditionalColumnNames: function() {
				var bindMap = this.getBindMap();
				var bindMapKeys = bindMap ? bindMap.getKeys() : [];
				var foundColumns = this.getFoundColumns();
				var additionalColumnNames = [];
				Terrasoft.each(foundColumns, function(item, columnName) {
					if(!(Ext.Array.contains(bindMapKeys, columnName)
							|| this.primaryDisplayColumnName === columnName)) {
						additionalColumnNames.push(columnName);
					}
				}, this);
				return additionalColumnNames;
			},
 
			/**
			 * Generates configuration of the element view.
			 * @protected
			 * @param {Object} itemConfig Link to the configuration element of ContainerList.
			 */
			onGetItemConfig: function(itemConfig) {
				var viewConfig = {
					"id": "foundColumns",
					"className": "Terrasoft.Container",
					"classes": {"wrapClassName": ["found-columns-list"]},
					"items": []
				};
				viewConfig.items = this.getFoundColumnItemsConfig();
				itemConfig.config = viewConfig;
			},
 
			/**
			 * Returns not showed columns container visibility.
			 * @protected
			 * @return {Boolean} Not showed columns container visibility.
			 */
			isFoundColumnsVisible: function() {
				var notShowedFoundColumns = this.getAdditionalColumnNames();
				return notShowedFoundColumns.length > 0;
			},
 
			/**
			 * Returns primary column link url.
			 * @protected
			 * @return {String} Primary column link url.
			 */
			getPrimaryColumnURL: function() {
				return Ext.String.format("ViewModule.aspx#{0}", NetworkUtilities.getEntityUrl(this.entitySchemaName,
						this.get(this.primaryColumnName), this.getTypeColumnValue(this)));
			},
 
			/**
			 * Handler on primary column link mouse over.
			 * @protected
			 */
			onPrimaryColumnMouseOver: function(options) {
				this.openMiniPage({
					targetId: options.targetId,
					entitySchemaName: this.entitySchemaName,
					recordId: this.get(this.primaryColumnName)
				});
			},
 
			/**
			 * Handler on primary column link click.
			 * @protected
			 * @return {Boolean} False.
			 */
			onPrimaryColumnLinkClick: function() {
				var typedColumnValue = this.getTypeColumnValue(this);
				NetworkUtilities.openEntityPage({
					entityId: this.get(this.primaryColumnName),
					entitySchemaName: this.entitySchemaName,
					typeId: typedColumnValue,
					sandbox: this.sandbox,
					stateObj: {
						moduleId: this._getStateObjModuleId()
					}
				});
				return false;
			},
 
			/**
			 * @overridden
			 * @inheritdoc Terrasoft.BaseSchemaViewModel#onLinkClick
			 */
			onLinkClick: function(url, columnName) {
				this.updateColumnReferenceSchemaByMultiLookupValue(columnName);
				var column = this.getColumnByName(columnName);
				var columnValue = this.get(columnName);
				var entityId = columnValue && columnValue.value;
				if (!column || !entityId) {
					return true;
				}
				NetworkUtilities.openEntityPage({
					entityId: entityId,
					entitySchemaName: column.referenceSchemaName,
					sandbox: this.sandbox,
					stateObj: {
						moduleId: this._getStateObjModuleId()
					}
				});
				return false;
			},
 
			/**
			 * Returns found column text for highlight.
			 * @private
			 * @param {String} columnName Column name.
			 * @return {String[]} Found column text array.
			 */
			getHighlightText: function(columnName) {
				var highlightTextArray = [];
				var foundColumns = this.getFoundColumns();
				if (columnName === "PrimaryColumn") {
					columnName = this.primaryDisplayColumnName;
				}
				Terrasoft.each(foundColumns, function(item, foundColumnName) {
					if (foundColumnName === columnName) {
						highlightTextArray = item;
					}
				}, this);
				return highlightTextArray;
			},
 
			/**
			 * Returns email url.
			 * @protected
			 * @param {String} columnName Column name.
			 * @return {String} Email url.
			 */
			getEmailUrl: function(columnName) {
				return EmailHelper.getEmailUrl(this.get(columnName));
			},
 
			/**
			 * Open browser mailto.
			 * @param {HTMLElement} target Target element.
			 * @param {String} columnName Email column name.
			 */
			onEmailUrlClick: function(target, columnName) {
				location.href = EmailHelper.getEmailUrl(this.get(columnName));
			},
 
			/**
			 * @overridden
			 * @inheritdoc Terrasoft.BaseSchemaViewModel#getLinkConfig
			 */
			getLinkConfig: function(columnName) {
				var config = this.callParent(arguments);
				var lookupLinkConfig = this.getLookupLinkConfig(columnName);
				this.Ext.apply(config, lookupLinkConfig);
				return config;
			},
 
			/**
			 * Gets lookup link config for open card.
			 * @private
			 * @param {String} columnName Column name.
			 * @return {Object} {schemaName: String} lookup link config for open card.
			 */
			getLookupLinkConfig: function(columnName) {
				var column = this.getColumnByName(columnName);
				var columnValue = this.get(columnName);
				if (column && this.isNotEmpty(column.multiLookupColumns)) {
					var multiLookupColumn = this.getColumnByName(columnValue.column);
					var referenceSchemaName = multiLookupColumn.referenceSchemaName;
					var schemaName = this.getCardSchemaName(referenceSchemaName, multiLookupColumn.name);
					return {schemaName: schemaName};
				}
				return {};
			}
		},
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "PrimaryImage",
				"propertyName": "items",
				"values": {
					"getSrcMethod": "getImage",
					"readonly": true,
					"onImageClick": {bindTo: "onPrimaryColumnLinkClick"},
					"generator": "ImageCustomGeneratorV2.generateSimpleCustomImage"
				}
			},
			{
				"operation": "insert",
				"name": "DataContainer",
				"propertyName": "items",
				"values": {
					"isViewMode": true,
					"itemType": Terrasoft.ViewItemType.GRID_LAYOUT,
					"items": [],
					"collapseEmptyRow": true
				}
			},
			{
				"operation": "insert",
				"name": "PrimaryColumnContainer",
				"parentName": "DataContainer",
				"propertyName": "items",
				"values": {
					"itemType": Terrasoft.ViewItemType.CONTAINER,
					"classes": {
						"wrapClassName": ["primary-column-container", "control-width-15"]
					},
					"items": [],
					"layout": {
						"column": 0,
						"row": 0,
						"colSpan": 12
					}
				}
			},
			{
				"operation": "insert",
				"name": "PrimaryColumnCaption",
				"parentName": "PrimaryColumnContainer",
				"propertyName": "items",
				"values": {
					"itemType": Terrasoft.ViewItemType.LABEL,
					"caption": {"bindTo": "getPrimaryDisplayColumnCaption"},
					"classes": {
						"labelClass": ["primary-column-caption"]
					}
				}
			},
			{
				"operation": "insert",
				"name": "PrimaryColumnValue",
				"parentName": "PrimaryColumnContainer",
				"propertyName": "items",
				"values": {
					"itemType": Terrasoft.ViewItemType.HYPERLINK,
					"classes": {"hyperlinkClass": ["primary-column-link"]},
					"caption": {"bindTo": "getPrimaryDisplayColumnValue"},
					"click": {"bindTo": "onPrimaryColumnLinkClick"},
					"linkMouseOver": {"bindTo": "onPrimaryColumnMouseOver"},
					"href": {"bindTo": "PrimaryColumnURL"},
					"tag": "PrimaryColumn",
					"highlightText": { bindTo: "getHighlightText" }
				}
			},
			{
				"operation": "insert",
				"name": "EntitySchemaCaption",
				"parentName": "DataContainer",
				"propertyName": "items",
				"values": {
					"caption": {"bindTo": "Resources.Strings.EntitySchemaLabelCaption"},
					"layout": {
						"column": 12,
						"row": 0,
						"colSpan": 6
					}
				}
			},
			{
				"operation": "insert",
				"name": "FoundColumnsContainerList",
				"propertyName": "items",
				"parentName": "DataContainer",
				"values": {
					"layout": {
						"column": 0,
						"row": 1,
						"colSpan": 12
					},
					"itemType": Terrasoft.ViewItemType.CONTAINER,
					"generator": "ContainerListGenerator.generateGrid",
					"collection": {"bindTo": "FoundColumnsCollection"},
					"onGetItemConfig": {"bindTo": "onGetItemConfig"},
					"visible": {"bindTo": "isFoundColumnsVisible"},
					"selectableRowCss": "",
					"items": []
				}
			}
		]/**SCHEMA_DIFF*/
	};
});

 

 

Any insight or help is highly appreciated!





Best Regards,

Bhoobalan Planivelu.

Bhoobalan Palanivelu,

 

Thank you!

 

I understood that you've created the SearchRowSchema for the BankCard and asked to share its code.

 

I will try to implement the same on my side and see what happens.

 

Best regards,

Oscar

Oscar Dylan,

Thanks, please let me know the results once you have a successful implementation.



I enabled the index in the section page of BankCard but no SearchRowSchema is found for it.

 

Oscar Dylan,

Any update on this part, please?



Best regards,

Bhoobalan Palanivelu.

Bhoobalan Palanivelu,

 

Hi,

 

I am sorry, but I don't need the BaseSearchRowSchema from your app (I do also have access to the BaseSearchRowSchema module from the bank bundle app), I need your custom SearchRowSchema code for the BankCard schema.

 

Best regards,

Oscar

Oscar Dylan,

That is the catch here, I couldn't find any SearchRowSchema for BankCardSchema. That is what I have shared in previous comments.



1. The SQL query doesn't return the BankCardSchema

2. There is no SearchRowSchema for BankCard.

3. All I did is open the Bank Card section and enable the Indexing by clicking the check box Indexing for full-text search.



The results appear and it doesn't have any X-SearchRowSchema and at the same time it shows (not filled in).



Best Regards,

Bhoobalan Palanivelu.

Oscar Dylan,

Any help/update on this?



Best regards,

Bhoobalan PAlanivelu

Bhoobalan Palanivelu,

 

Please read my post with the instruction carefully. I've asked to create a replacing view module using the BaseSearchRowSchema as a parent and then connect it to the SysModuleEdit record of your section using the SearchRowSchemaUId column (and provided an example with the Documents section that also don't have its own SearchRowSchema).

Oscar Dylan,

I have followed the same steps as suggested and there needs a little update.



Step 1: Find the target object for GS result update (Here, it is BankCard)

Step 2: Create the "Page view model" in configurations with "CTZBanCardSearchRowSchema" code, "BankCard search row" name and select BaseSearchRowSchema as a parent

Step 3: Update the design of the schema and save.

Step 4: Find the SysModuleEdit record related to the BankCard section (for example using the query below):

SELECT
	*
FROM
	SysModuleEdit
WHERE 
	ActionKindName = 'BankCard'

Step 5: update the value for the "SearchRowSchemaUId" column in the target objects record.

UPDATE 
	SysModuleEdit
SET 
	SearchRowSchemaUId = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
WHERE
	Id
IN
	(
		SELECT 
			Id
		FROM 
			SysModuleEdit
		WHERE
			ActionKindName = 'BankCard'
	)



**Note: This Column's "SearchRowSchemaUId" value should be the UID of the newly created Page view model performed in Step 2.



UID can be obtained by using the below query,

select Id, UId, Name from SysSchema 
where 
Name like ('%CTZBanCardSearchRowSchema%')



Thanks for the guide!





Best regards,

Bhoobalan Palanivelu

 

Interesting.

Will this work for Details as well, if we make a SearchRowSchema? 

Show all comments

Hi Team,

 

I have a business scenario where  let's say a user will first filter records for export(let's say export to excel) and if the records are more than 50 then before exporting the records user requires an approval from the department admin over email, Once the user receive an approval over email then only he/she will be able to export those records from system.

 

Note : Email for approval can be sent from the system, but approval email received will not come into the system.

 

Please suggest you solution how we can achieve this in Creatio.

 

Thank you for your time!

Like 0

Like

2 comments

Hi Akshit,

 

This task can be achieved using the following scenario:

 

1) Create two boolean columns in the "System administration object" (SysAdminUnit) object. One of them will be called "Was approval sent?" the second will be "Was approved?"

 

2) The preparation method that is called when clicking the export to excel action is called exportToExcel and located in the BaseDataView module that then calls the exportToExcel method from the GridUtilitiesV2 that then calls exportToExcelFile method from the DataUtilities module (all according to the call stack of calls, you can debug it on your end).

 

You need to add additional check if the "Was approved?" and "Was approval sent?" booleans are checked for the user that initiated the export. To get the current user info you can use the user session (can be received using Terrasoft.sessionId) and then you can perform an ESQ select query to SysUserSession object to get the UserId and then perform another ESQ select query to get information from the SysAdminUnit object directly (we are interested in two boolean columns and the SysAdminUnit Id column value).

 

3) If the "Was approved?" and "Was approval sent?" booleans are not checked then you need to trigger a business process that will send an email (using ProcessModuleUtilities). You need to pass the SysAdminUnit Id column value as a parameter of this process and use it inside the process to form a link to either Reject and Approve "Call to action" buttons.

 

4) To either approve or reject the possibility of export an email with two options "Approve" and "Reject" should be sent. The link should lead you to the webservice on the Creatio side. This webservice should update the specific SysAdminUnit record with an Id that will be passed as a parameter to this webservice (and the parameter will be specified as a part of the link).

 

As for the link itself it can be formed as a text parameter (based on the Id passed from the UI using ProcessModuleUtilities) and passed to the HTML body of the custom template in the "Send email" element as:

"<a href=" + [#LinkParameter#] + "><img alt= \"Accept\" src=\"link_to_the_image_here\" width=\"100\" height=\"100\" ></a>"

Before sending an email the "Was approval sent?" checkbox should be checked for the SysAdminUnit record (using modify data for example).

 

5) The webservice will update the boolean columns "Was approved?" and "Was approval sent?" using the following scenario:

 

5.1) If the approval was rejected - uncheck both "Was approved?" and "Was approval sent?" checkboxes for the user

5.2) If the approval was approved - check the "Was approved?" boolean and uncheck the "Was approval sent?".

 

6) On the section module also add additional check for both boolean columns (as in step 2): if the "Was approved?" is checked and the number of exported items is greater than 50 - permit the export and uncheck the "Was approved?" checkbox for the user.

 

Please study the scenario I described above and use it when implementing the logic on your end.

 

Best regards,

Oscar

Oscar Dylan,

 

Thank you!

Show all comments

Hi Community,

 

Any idea how can I achieve this requirement. I am throwing a custom exception message from object validation. However, in mobile it is showing as generic error, user needs to click on "Send Report" to view the actual exception message I was throwing from object validation. How can I show it on mobile's pop dialog right away?

 

 

Like 0

Like

1 comments

Hi Fulgen,

 

I am sure that your task can be achieved in another way. Please see this Academy article regarding push notifications where you can pass the validation message.

 

Best regards,

Oscar

Show all comments

Hi Community,

 

I want to override qualify button method in Leads section and check if some of the fields have appropriate value. If not, I want to stop the lead qualification process. Can someone help me in achieving the same?

Thanks,

Gokul

 

 

Like 0

Like

5 comments

Hi Gokul,

 

As I already stated here the method that is called upon the "Qualify" button click is onLeadManagementButtonClick (for the LeadPageV2 module).  In the LeadSectionV2 the method is onLeadManagementSectionButtonClick. You can override both methods in the replaced modules: in LeadPageV2 you can add additional this.get(Column)!= check and then call parent method and in the LeadSectionV2 you need to get ActiveRow and perform an ESQ select query to check if the record by ActiveRow has the data needed to start the process.

 

Best regards,

Oscar

Oscar Dylan,

Thank you  for the reply. In case of section page as told I am running an esq. How can i call parent method based on execution of esq?

onLeadManagementSectionButtonClick:function(){
	activeRowId = this.get("ActiveRow");
	var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
		rootSchemaName: "Lead"
	});
	esq.addColumn("Id");
	esq.addColumn("Account");
	esq.addColumn("Email");
	esq.getEntity(activeRowId, function (result) {
		if (result.success) {
			var account = result.entity.values.Account;
			var email = result.entity.values.Email;
			if(account==='' || email==='')
			{
				Terrasoft.showErrorMessage("error msg");
			}
			else
			{
				//call parent method
				this.callParent(arguments);
			}
 
	  }
	}, this);
},	

 

S Gokul Aditya,

 

ESQ is asynchronous so you won't be able to call the parent method. But we can do it in another way. Try this code:

onLeadManagementSectionButtonClick: function() {
				var gridData = this.get("GridData");
				var activeRow = this.get("ActiveRow");
				var activeRowGridData = gridData.get(activeRow);
				var activeRowGridDataAccount = activeRowGridData.get("Account");
				var activeRowGridDataEmail = activeRowGridData.get("Email");
				if (!activeRowGridDataAccount || !activeRowGridDataEmail) {
					Terrasoft.showErrorMessage("error msg");
					return;
				}
				this.callParent(arguments);
			}

But in this case you will have to display both account and email columns in the lead section grid:

This approach works on my side, should also work on your end.

 

Best regards,

Oscar

Oscar Dylan,

thanks for the quick reply. I have few more such fields to be checked. Can it be done without adding columns to the section grid?

S Gokul Aditya,

 

Not sure, the code should be debugged to find out the proper way of the customer's business task completeness. I just gave an example, the final implementation can differ.

Show all comments

How can I set up B2B2C hierarchy in CRM, think of it as a franchise based business where each franchise has its own employees, customers/leads/accounts/deals etc. Franchise employees can login and manage their leads, contacts and deals and we at the top of hierarchy can see all franchises and aggregated the data. Does Creatio CRM supports this by default and if not then can we customize and supports it. We need this B2B2C hierarchy  for all marketing, sales and service. Please suggest.

 

Like 0

Like

4 comments

Hello Gaurav,

 

Unfortunately, our platform does not have any presents for such projects.

Although, it is possible to achieve such configuration by setting up roles and distributing the access to the system between your customers.



For example: You can branch out the access in the way that only certain users will full access to all the data on your instance while "franchises" will be able to access the information only related to them.

 

Thank you,

Artem.

Artem,

Thanks for providing that information, but what is going to be name of entity/object which will represent a Franchise/Partner in creation CRM, I can see Partnerships, Accounts etc but not sure it can be used to represents a franchise or not. Also can we achieve the flexibility of assigning a lead, deal to a user where dropdown will only show the users/employees of that franchise not all users in system. We can filter by franchise, means can see all leads, contacts, deals etc for each franchise and so on. Can we customize the Creation CRM which means all sales, marketing and service to this much extent or its too much to do, I mean adding new tables/entities or columns in user tables etc. Please suggest.

Take a Look at this franchise management app developed on Creatio CRM. Here is the link: https://marketplace.creatio.com/app/franchise-management-creatio

Harold Busby,

Thanks for providing that link, I have installed this app but not sure what is entity for franchise in this app, can you please share some link to its documentation so that I can understand it.

Show all comments

Hi community,

 

Is it possible in a mass email to use the "CALL TO ACTION" block without "creatio" adding the tracking information in the "CALL TO ACTION" link in the email?

I have to send an email with a link to a web application and the parameters added for tracking in the "CALL TO ACTION" are causing some problems for the web application.

Like 0

Like

1 comments

Hello Stefano,

 

Thank you for your question!

 

Parameters are added to links automatically and they cannot be turned off. They are needed in order to find out which recipient and which bulk email the review belongs to.

 

Kind regards,

Anastasiia

Show all comments

Case Management platform has being configured and distributed to one of our clients. They had a request to change the page that appear after the customer provides a feedback through email. Image of the page provided below.

The Logo and text in the page need to be changed.

Can someone please provide me a method configure this?

Thank you!

Like 0

Like

4 comments

Hello Shinoli,



The only way to customize this page using out-of-the-box tools is the system setting called "Logo - Thank you for your feedback" that is described in the Academy article here.



The only way to completely change this page is to apply changes to "CaseRatingFeedbackPage" schema (using additional development). Bogdan is already CC'd to this email so I hope he will be able to find a developer who can adjust this page base on your needs in terms of advisory hours.



At the same time we have two problems registered to our R&D team so to make the possibility to change this page more user-friendly (using standard tools such as section wizard), but unfortunately there is no ETA on this task. Once it is done - we will update all our clients and partners about it in our official release notes. 

 

Best regards,

Bogdan

Thank you for the information.

Important to update this page design without code!

I agree with all of the above, this is a major reason why one of our clients does not use this functionality.

Show all comments

Hi Team,

 

I have created two custom attachment Detail [ Attach claims & Attach Documents], and linked them with the section but getting error when opening the record page please see the below screenshot

 

Also if you see layout of "Drag file here" in case of custom attachment detail is not looking good. Is there a way to remove that ?

 

Please help !

Thanks for your time!

Like 0

Like

1 comments

Hello 



Unfortunately, the system does not provide the ability to display two details on the same page.

We have conveyed your wishes to the product analysts, they will consider the possibility of implementing functionality for you in the next releases of the product.

 

Best regards,

Bogdan

Show all comments

Hi Team,



Is there a way to use two different servers for IMAP and SMTP for on-premises deployment as below?



a)Consume the IMAP server available in the on-premise network.

b)Consume SMTP via AWS.



If there is a way to achieve this, kindly share the guidelines.







Best Regards,

Bhoobalan P.

Like 0

Like

2 comments

Hello Bhoobalan,



Thank you for your question!

Unfortunately, Creatio does not support using different mail servers for one mailbox.

 

As a workaround, you can set up multiple mailboxes that will use different mailing servers.

 

Best regards,

Artem.

Artem,

Thanks for the response!

 

Show all comments

Hi Community,

 

To test the HAProxy, I've installed two Creatio Applications on my virtual machine, using Docker. Each instance can be access through a specific container address.

 

I've successfully configured HAProxy by following this guide (https://academy.creatio.com/docs/user/on_site_deployment/deployment_additional_setup/application_server_web_farm_shortcut/application_server_web_farm). If I stop one of the containers, the HAProxy sends the requests to the other container, as expected. However, when both containers are up and running, I cannot pass through the login page.

 

I need help to understand:

What is the cause of such behaviour?

What are the possible solutions to solve this problem?

Will this problem occur if each instance is in a separated machine?

 

Note: I’ve notice on other tests that when I have two Creatio instances on the same machine I can only be logged one at the time. Maybe this is related to the problem.

 

Best Regards,

Pedro Pinheiro

Like 1

Like

3 comments

I think I’ve managed to solve this problem. In some applications we need to ensure that the user must be connected to the same server during the whole session. So, to allow this I changed the Load Balance Algorithm to source.

frontend front
     maxconn 10000
     #Using these ports for binding
     bind *:80
     bind *:443
     #Convert cookies to be secure
     rspirep ^(set-cookie:.*)  \1;\ Secure
     default_backend creatio
 
backend creatio
     #set balance type
     balance source       
     server node_1 nodeserver1:80 check weight 2
     server node_2 nodeserver2:80 check weight 1

The problem was solved, but I don't know if this is the correct way to solve it. I would like to hear some feedback. Thank you.

 

Best Regards,

Pedro Pinheiro

Hi Pedro, 



We generally recommend using round-robin, as it's optimal in most cases, but the "source" algorithm is working as well. 

As for why the log-in issue happened: it's hard to say definitely, but on of the options is if the machinekey is different on different nodes - it won't let you log in. 

 

Best regards,

Yurii.

Hi Yurii Sokil,

 

I moved this infrastructure to a Linux server. In this server I have the same two instances but with different ports instead of docker containers. How can I generate this "machinekey”?

 

The documentation only explains how to generate them on windows servers, through  PowerShell.

 

Best Regards,

Pedro Pinheiro

Show all comments