Question

Is it possible to get the roles for a Stage from the client JS?

Hi, 

 

I have a requirement to filter a contact look up by the stage roles for the stage the record is at. Can I get the roles for the stage on the client JS code? Id so, how?

 

Thanks,

Jose

 

Need to get the roles highlighted programmatically.

Like 0

Like

7 comments

Hi Jose,

 

Please provide a business task for this requirement.

 

Best regards,

Oscar

Oscar Dylan,

Hi Oscar,

 

We have a field called 'Locked by' that indicates who is working on the record. A Supervisor can select multiple records (as long as they are on the same stage) and assign all records to a user. When selecting the user, we only want to display the users that have access to that stage.

 

Thanks,

Jose

Jose Hernandez,

 

Hi,

 

Here is an example of removing users from the "SysAdminUnit" lookup column that is located on the case page based on the restrictions of the current case status in DCM:

As we can see on the example of another record all the users are displayed in the case with the "New" status:

And if we look at the restrictions of the "Waiting for response" status we can see that the stage is restricted for 1 and 2 users and for the 1-st line support:

To achieve this result I've:

 

1) Created a replacing view module selecting CaseSectionActionsDashboard as a parent module and specified the following code there:

define("CaseSectionActionsDashboard", [], function() {
	return {
		messages: {
			"SendTheResultStagesRestrictionSet": {
						mode: Terrasoft.MessageMode.BROADCAST,
						direction: Terrasoft.MessageDirectionType.PUBLISH
					}
		},
		attributes: {
			"RestrictedStagesInfo": {
				"dataValueType": this.Terrasoft.DataValueType.TEXT,
				"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				"value": ""
			}
		},
		methods: {
			setActionsEnabled: function(actions) {
				this.callParent(arguments);
				var itemsArray = actions.collection.items;
				var stagesWithRestrictionsAndRoles = [];
				itemsArray.forEach(item => {
					if (item.changedValues.UsePermissions == true) {
                        var objectWithResults = new Object();
                        objectWithResults.RolesArray = [];
						objectWithResults.StageName = item.changedValues.Caption;
						item.changedValues.Permissions.forEach(role => {
							objectWithResults.RolesArray.push(role);
						});
						stagesWithRestrictionsAndRoles.push(objectWithResults);
					}
				});
				var stagesWithRestrictionsToPass = JSON.stringify(stagesWithRestrictionsAndRoles);
				this.set("RestrictedStagesInfo", stagesWithRestrictionsToPass);
				this.sandbox.publish("SendTheResultStagesRestrictionSet", stagesWithRestrictionsToPass);
			},
		},
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "remove",
				"name": "Tabs"
			}
		]/**SCHEMA_DIFF*/
	};
});

The key functionalities here are:

1.1) setActionsEnabled overridden method that checks if the user can or cannot modify the stage (in the OOB initialization). In the code above I call the parent method and then perform an additional check if each stage of the DCM has enabled restriction permissions or not and if it has I create an object with the stage name and the roles array (those that has no access to this stage modification (those mentioned in the stage settings like in one of the screenshots above)). This check is performed for each stage and once all the stages are checked we pass these objects to the stagesWithRestrictionsAndRoles array.

1.2) Once the stagesWithRestrictionsAndRoles array is filled in we encode it to JSON set the JSON string as a value for the RestrictedStagesInfo attribute and send a sandbox "SendTheResultStagesRestrictionSet" message with stagesWithRestrictionsToPass argument.

 

2) Created a replacing view module selecting the CasePage module as a parent and specified the following code there:

 define("CasePage", [],
		function() {
			return {
				entitySchemaName: "Case",
				details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
				modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "UsrSysAdminUnita70d79bf-0ec1-497d-8d9b-3ad54206b6a6",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 12,
						"layoutName": "ProfileContainer"
					},
					"bindTo": "UsrSysAdminUnit"
				},
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 12
			},
			{
				"operation": "merge",
				"name": "ProcessingTab",
				"values": {
					"order": 0
				}
			},
			{
				"operation": "merge",
				"name": "ESNTab",
				"values": {
					"order": 5
				}
			},
			{
				"operation": "merge",
				"name": "SolutionTab",
				"values": {
					"order": 1
				}
			},
			{
				"operation": "merge",
				"name": "SatisfactionLevelComment",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "CaseInformationTab",
				"values": {
					"order": 2
				}
			},
			{
				"operation": "merge",
				"name": "NotesFilesTab",
				"values": {
					"order": 4
				}
			},
			{
				"operation": "move",
				"name": "ResoluitonContainer",
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "move",
				"name": "ServiceItem",
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 6
			},
			{
				"operation": "move",
				"name": "ConfItem",
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 7
			},
			{
				"operation": "move",
				"name": "ServicePact",
				"parentName": "ProfileContainer",
				"propertyName": "items",
				"index": 4
			},
			{
				"operation": "move",
				"name": "SolutionCaptionProfile",
				"parentName": "ResolutionGridLayout",
				"propertyName": "items",
				"index": 0
			},
			{
				"operation": "move",
				"name": "SolutionFieldContainer",
				"parentName": "SolutionTab_gridLayout",
				"propertyName": "items",
				"index": 3
			},
			{
				"operation": "move",
				"name": "FirstSolutionProvidedOn",
				"parentName": "TermsControlGroup_GridLayout",
				"propertyName": "items",
				"index": 3
			}
		]/**SCHEMA_DIFF*/,
				mixins: {},
				attributes: {
					"UsrSysAdminUnit": {
						"dataValueType": Terrasoft.DataValueType.LOOKUP,
						"lookupListConfig": {
							"filters": [
								function() {
									var filterGroup = Ext.create("Terrasoft.FilterGroup");
									filterGroup.add("IsUser",
													Terrasoft.createColumnIsNotNullFilter("Contact"));
									filterGroup.add("IsActive",
													Terrasoft.createColumnFilterWithParameter(
										Terrasoft.ComparisonType.EQUAL,
										"Active",
										true));
									var restrictedUsers = this.get("ReceivedUsersArray");
									if (restrictedUsers && restrictedUsers.length != 0) {
										for (var i = 0; i < restrictedUsers.length; i++) {
											var caption = `IsAllowed${i}`;
											filterGroup.add(caption,
															Terrasoft.createColumnFilterWithParameter(
												Terrasoft.ComparisonType.NOT_EQUAL,
												"Id", restrictedUsers[i]
											));
										}
									}
									return filterGroup;
								}
							]
						}
					},
					"ReceivedUsersArray": {
						"dataValueType": this.Terrasoft.DataValueType.COLLECTION
					}
				},
				messages: {
					"SendTheResultStagesRestrictionSet": {
								mode: Terrasoft.MessageMode.BROADCAST,
								direction: Terrasoft.MessageDirectionType.SUBSCRIBE
							}
				},
				methods: {
					subscribeSandboxEvents: function() {
						this.callParent(arguments);
						this.sandbox.subscribe("SendTheResultStagesRestrictionSet", this.receivedMessageHandler, this);
					},
					receivedMessageHandler: function(stagesWithRestrictionsToPass) {
						var decodedRestrictedStages = Ext.decode(stagesWithRestrictionsToPass);
						var receivedRolesArray = [];
						var receivedUsersFromRolesArray = [];
						var currentStatus = this.get("Status");
						var currentStatusDisplayValue = currentStatus.displayValue;
							decodedRestrictedStages.forEach(item => {
								var itemStageName = item.StageName;
								if (itemStageName == currentStatusDisplayValue) {
									item.RolesArray.forEach(role => {
										receivedRolesArray.push(role);
									});
								}
							});
						if (receivedRolesArray.length == 0) {
							return;
						}
						var selectSysAdminUnitInRole = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "SysAdminUnitInRole"});
						selectSysAdminUnitInRole.addColumn("SysAdminUnit");
						selectSysAdminUnitInRole.addColumn("SysAdminUnitRoleId");
						receivedRolesArray.forEach(role => {
							selectSysAdminUnitInRole.filters.addItem(selectSysAdminUnitInRole.createColumnFilterWithParameter(3, "SysAdminUnitRoleId", role));
						});
						selectSysAdminUnitInRole.filters.logicalOperation = Terrasoft.core.enums.LogicalOperatorType.OR;
						selectSysAdminUnitInRole.getEntityCollection(function (result) {
							if (result.success && result.collection.getCount() > 0) {
								var items = result.collection.getItems();
								items.forEach(sysAdminUnitId => {
									var actualUsersIds = sysAdminUnitId.values.SysAdminUnit.value;
									receivedUsersFromRolesArray.push(actualUsersIds);
								});
							}
							this.set("ReceivedUsersArray", receivedUsersFromRolesArray);
						}, this);
					}
				},
				rules: {},
				userCode: {}
			};
		});

The key functionalities here are:

 

2.1) Subscribing to the SendTheResultStagesRestrictionSet message in the subscribeSandboxEvents method

2.2) Initializing the receivedMessageHandler method that is the SendTheResultStagesRestrictionSet message handler function. The logic of the method is simple: receive the stagesWithRestrictionsToPass JSON string, decode it, check if the current case status is present in the list of statuses inside the decoded JSON string, if it's not present - finish the method execution, if it's present - create the ESQ query (selectSysAdminUnitInRole) to the SysAdminUnitInRole table to get the list of users related to the roles received for the stage in the stagesWithRestrictionsToPass  JSON string. The result of the ESQ is then written into the ReceivedUsersArray attribute (COLLECTION data type).

2.3) Creating a filter for the UsrSysAdminUnit lookup based on the results received in the ReceivedUsersArray attribute.

 

Feel free to study the implementation (please do it carefully) and debug it to achieve the same on your end.

 

Best regards,

Oscar

Oscar Dylan,

Thanks Oscar. I was able to adapt your instructions and make it work on the scenario where the user will assign on record at a time. (Open the record, change the Locked by field that now only shows the expected contacts.)

 

However, the requirement asks for the user to be able to assign multiple records to a user. The person assigning selects multiple records (all on the same status) and then assigning all of them to a user. 

 

I added an action to the section that is only available when records are selected and then I call a process that validates that all records are on the same status. If they are a preconfigured page opens allowing the user to select who to assign the cases to. I need to filter that lookup to show only users in roles allowed on the stage that status defines. See screenshots below.

 

Is that possible?

 

Thanks,

Jose

 

Assign Process

 Action that calls the process

Preconfigured page

Jose Hernandez,

 

I am not sure it's possible and you need to test it. The code I wrote indeed works for one user assignment and also the field is located on the same page where the DCM is located. But you want to filter the lookup on the process page that has no connection to the page.

 

Best regards,

Oscar

Oscar Dylan,

Hi Oscar, 

 

I guess I was wondering if there is a query where I could get the roles from. Something like:

 

Select <Roles> from <Case> where   <name> = 'My case Name' and <Status> = 'record status'.

 

For example select <roles> from <case> where <name> = 'Process Correspondence Case ' and <Status> = 'Processed'  will return the roles PPDR DRA, PPDR Intake Specialist, PPDR Management, etc.

 

Thanks,

Jose

 

Oscar Dylan,

Hi Oscar, 

 

The code you provided worked on our DEV/QA environments but not in production and I'm not sure why. 

 

In Production the item.changedValues.Permissions.forEach is failing on the code below. And it is failing because in Prod item.changedValues.Permissions is returned as a comma separated string while in QA/DEV is returned as an Array. See screenshots below. 

 

Any idea what can cause that? All environments are running the same Creatio version (7.18.4.1532) and the same browser version (FireFox 97.0)

 

Thanks,

Jose

 

Code

setActionsEnabled: function(actions) {
                    var itemsArray = actions.collection.items;
                    var stagesWithRestrictionsAndRoles = [];
                    itemsArray.forEach(item => {
                        if (item.changedValues.UsePermissions == true) {
                            var objectWithResults = new Object();
                            objectWithResults.RolesArray = [];
                            objectWithResults.StageName = item.changedValues.Caption;
                            item.changedValues.Permissions.forEach(role => {
                                objectWithResults.RolesArray.push(role);
                            });
                            stagesWithRestrictionsAndRoles.push(objectWithResults);        
                        }
                    });
                    var stagesWithRestrictionsToPass = JSON.stringify(stagesWithRestrictionsAndRoles);
                    this.set("RestrictedStagesInfo", stagesWithRestrictionsToPass);
                    this.sandbox.publish("SendTheResultStagesRestrictionSet", stagesWithRestrictionsToPass, [this.getSenderSandboxId()]);
                    var isModelItemsEnabled = this.get("IsModelItemsEnabled");
                    if (!isModelItemsEnabled) {
                        this.iterateActions(actions, function(action) {
                            action.set("Enabled", false);
                        }, this);
                        return;
                    }
                    this.callParent(arguments);
                }
            },

PROD

DEV

Show all comments