Question

Case Term Calculation using a different object

Hi All,

I am working on a scenario where system will update Case Resolution Time and Response Time from a different object(Query Type lookup in case) for some accounts and for other accounts use default service section using Alternative case deadline calculation schema.

 

I came across following academy article

https://academy.creatio.com/documents/technic-sdk/7-16/adding-new-rule-…

 

I created the calculation schema as below

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Terrasoft.Common;

using Terrasoft.Core.Configuration;

using Terrasoft.Core;

using Terrasoft.Core.Entities;

using CalendarsTimeUnit = Terrasoft.Configuration.Calendars.TimeUnit;

using SystemSettings = Terrasoft.Core.Configuration.SysSettings;

using Terrasoft.Configuration;

namespace Terrasoft.Configuration

{

    class QueryTypeDeadlineCalculation : BaseTermStrategy

    {

        protected class StrategyData

        {

            public Guid QueryTypeId

            {

                get;

                set;

            }

        }

        protected StrategyData _strategyData;

        public QueryTypeDeadlineCalculation(UserConnection userConnection, Dictionary args)

            : base(userConnection)

        {

            _strategyData = args.ToObject();

        }

        public override CaseTermInterval GetTermInterval(CaseTermStates mask)

        {

            var result = new CaseTermInterval();

            var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "UsrQueryType");

            

            esq.AddColumn("Name");

            esq.AddColumn("UsrReactionTimeUnit");

            esq.AddColumn("UsrReactionTimeValue");

            esq.AddColumn("UsrResolutionTimeUnit");

            esq.AddColumn("UsrResolutionTimeValue");

            var queryTypeRecord = esq.GetEntity(UserConnection, _strategyData.QueryTypeId);

            result.ResponseTerm.Type = queryTypeRecord.GetTypedColumnValue("UsrReactionTimeUnit");

            result.ResponseTerm.Value = queryTypeRecord.GetTypedColumnValue("UsrSolutionTimeValue");

            result.ResponseTerm.CalendarId = new Guid("F0FF1F0E-F46B-1410-1787-0026185BFCD3");

            result.ResolveTerm.Type = queryTypeRecord.GetTypedColumnValue("UsrResolutionTimeUnit");

            result.ResolveTerm.Value = queryTypeRecord.GetTypedColumnValue("UsrResolutionTimeValue");

            result.ResolveTerm.CalendarId = new Guid("F0FF1F0E-F46B-1410-1787-0026185BFCD3");

            return result;

            throw new NotImplementedException();

        }

    }

}

I am getting a null exception in _strategydata. I figured I am not sending the QueryTypeId into args from frontend or from where ever it is triggered.

 

I am unable find the frontend code for that. Could you please help me figure this out?

 

And also how can we use this alternative schema based on a condition?

Like 0

Like

4 comments

Hi,

 

The code from the front-end that calls the case term strategy is located in the CaseServiceUtility module in the getDefaultCaseTermStrategy method (that is called from the setInitialValues method from the CasePage module).

 

As for using the alternative schema based on a condition, I guess you need to somehow override the getDefaultCaseTermStrategy or handleStrategies methods in the CaseServiceUtility module and set some conditions there.

 

Best regards,

Oscar

Hi Oscar,

 

First of all, Thanks for replying. It helped me a lot. I have checked the "getDefaultCaseTermStrategy" from the CaseServiceUtility module. It is only trying to build the Sequence of Strategies from the default strategy and the callback function is also an empty function.

 

getDefaultCaseTermStrategy: function(callback, scope) {

                    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "DeadlineCalcSchemas"

                    });

                    esq.addColumn("Id");

                    esq.addColumn("Default");

                    esq.addColumn("AlternativeRule");

                    esq.getEntityCollection(function(response) {

                        this.handleStrategies(response);

                        if (this.Ext.isFunction(callback)) {

                            callback.call(scope || this);

                        }

                    }, this);

                },

 

But Here I think I need to add a new argument "Query Type" in addition to previous ones(ServiceItem, ServicePact, Priority). But I am not able to find where to add this new argument I found something in "CaseTermCalculationDescribeUtilities" But, I am not sure where it is being used.

I am also unable to find what is the main service that will be called and where it is being called.  Where is this handler schema I have written above is being called?

 

Please help me find the solution.

 

 

Nagaraju,

 

Hi,

 

Ok, I reviewed the code deeper and found out the chain of actions:

 

1) In the CaseServiceUtilities there is a recalculateServiceTerms method that is triggered from either onRegisteredOnChanged (by the way, strategies we've described above are only used here = are used when the case is created since this is the only way to change the RegisteredOn value in the OOB version of the app) or onServiceItemChanged or onStatusChanged or onPriorityChanged methods.

 

2) The recalculateServiceTerms method checks either the ServiceTerms feature is enabled (it's enabled in the OOB version of the app, can be checked using this command in the console (returns "true" in my app): Terrasoft.Features.getIsEnabled("ServiceTerms")).

 

3) Check in step 2 calls the getCaseTermCalculatorServiceConfig method that will get an array of conditions (returned upon prepareCaseTermCalculatorConditions method execution):

				prepareCaseTermCalculatorConditions: function() {
					var conditions = [];
					this.addToConditions(conditions, "ServiceItem");
					this.addToConditions(conditions, "ServicePact");
					this.addToConditions(conditions, "Priority");
					this.addToConditions(conditions, "Id");
					this.addToConditions(conditions, "SolutionOverdue");
					return conditions;
				},

get the RegisteredOn value for the case, encode this RegisteredOn value into JSON and return the config of the service that is going to be called:

return {
						serviceName: "CaseTermCalculationService",
						methodName: "CalculateTerms",
						data: {
							arguments: conditions,
							registrationDate: encodedDate
						}
					};

4) Once the service config from step 3 is returned the recalculateServiceTerms method continues its execution (step 2), once again perfom ServiceTerms feature state check and calls the service using the config. The handler for the response (callback function) is onRecalculateCaseTerms [1] and we will return to it later.

 

5) As can be seen from step 3, the service that is being called is CaseTermCalculationService and the method is CalculateTerms. CalculateTerms method calls the InternalCalculateTerms method of the same CaseTermCalculationService class and the InternalCalculateTerms calls the CalculateTerms method of the CaseTermCalculateEntryPoint class instance:

private ServiceTermResponse InternalCalculateTerms(Dictionary<string, object> arguments, string registrationDate) {
			Dictionary<string, object> featuredDictionary = GetDictionaryWithGuids(arguments);
			var parsedRegistrationDate = DateTime.Parse(registrationDate);
			var userConnectionArg = new ConstructorArgument("userConnection", UserConnection);
			var entryPoint = ClassFactory.Get<CaseTermCalculateEntryPoint>(userConnectionArg);
			return entryPoint.CalculateTerms(featuredDictionary, parsedRegistrationDate);
		}
...
public string CalculateTerms(Dictionary<string, object> arguments, string registrationDate) {
			var stringResponse = new ServiceTermStringResponse();
			try {
				ServiceTermResponse response = InternalCalculateTerms(arguments, registrationDate);
				if (response.ReactionTime != null) {
					stringResponse.ReactionTime = response.ReactionTime.Value.ToString(_dateFormat);
				}
				if (response.SolutionTime != null) {
					stringResponse.SolutionTime = response.SolutionTime.Value.ToString(_dateFormat);
				}
			} catch (Exception e) {
				return e.Message;
			}
			return JsonConvert.SerializeObject(stringResponse);
		}

Also these methods use the registrationDate string variable that is a JSON RegisteredOn  string value from step 3.

 

6)  CaseTermCalculateEntryPoint class CalculateTerms method uses CaseTermIntervalSelector class Get method.

 

7) CaseTermIntervalSelector class Get method uses the CaseTermStrategyManager class instance GetTermInterval method.

 

8) GetTermInterval method is an abstract method of the BaseTermStrategy class that is called by the BaseTermStrategy method of the CaseTermStrategyManager class instance created in the Get method of the CaseTermIntervalSelector selector from step 7. In the Academy article you've shared we override the GetTermInterval method to get the data we need.

 

9) Once the service goes through all the logic from steps 5-8 the response from those steps is being processed in the callback onRecalculateServiceTerms [1] function from step 4 and values for the ResponseDate and SolutionDate fields are specified.

 

So you need to study all this route of calls to find out what needs to be modified.

 

Best regards,

Oscar

Oscar Dylan,

 

Thanks for the detailed answer oscar. I have gone through the code. Please help me with following

 

1. I understood that we get strategy queue from CaseTermStrategyManager class. In CaseTermIntervalSelector class we are looping through the queue and if response & resolution time is null then it automatically goes to the next. Am I right here? If I just keep my QueryType column (where I define Response and solution term) null in case record, does System automatically goes to Alternate schema?

 

2. I am also trying to replace the "CaseServiceUtility" Mixin, But I am getting "substitution is not allowed". How can I add modify

prepareCaseTermCalculatorConditions() in CaseServiceUtility.

 

Thanks in advance

 

Show all comments