Business Rule not returning same value as Background script.

Aaron Duncan
Mega Sage

I have the following script that when run as a background script, runs perfectly. When I place it in an After Business Rule, the values for the conditions are no longer the same as when they were in the business rule. The variables in the IF statements return false on the Business Rule. There is another business rule that runs before this that sets the field values that this depends upon.

 

    // Decision Table Builder code to take the fields and pass them through to the Decision Table for Legal Category assignment.
    try {
        var inputs = {};
        inputs['u_data_selected'] = current.u_if_customer_pii_data_selected.getDisplayValue(); // String 
        inputs['u_customer_characteristics'] = current.u_cpii_customer_characteristics.getDisplayValue(); // String 
        inputs['u_medical_insurance_information'] = current.u_cpii_medical_insurance_info.getDisplayValue(); // String 
        inputs['u_commercial_information'] = current.u_cpii_commercial_information.getDisplayValue(); // String 
        inputs['u_internet_communication_activity'] = current.u_cpii_internet_comm_activity.getDisplayValue(); // String 
        inputs['u_biometric_information'] = current.u_cpii_biometric_information.getDisplayValue(); // String 
        inputs['u_geolocation_information'] = current.u_cpii_geolocation_information.getDisplayValue(); // String 
        inputs['u_sensory_data'] = current.u_cpii_sensory_data.getDisplayValue(); // String 
        inputs['u_employment_education_information'] = current.u_cpii_employment_education_information.getDisplayValue(); // String 
        inputs['u_inferences'] = current.u_cpii_inferences.getDisplayValue(); // String 

        var dt = new sn_dt.DecisionTableAPI();
        var response = dt.getDecisions('5f86416e93a94210561430747aba1073', inputs);

        for (var i = 0; i < (response && response.length); i++) {
            var result = response[i];
			gs.info('Legal Categories Result: ' + result);
            var result_elements = result.result_elements;
            var u_biometric_information = result_elements.u_biometric_information; // True/False
            var u_commercial_information = result_elements.u_commercial_information; // True/False
            var u_geolocation_information = result_elements.u_geolocation_information; // True/False
            var u_identifiers = result_elements.u_identifiers; // True/False
            var u_inferences = result_elements.u_inferences; // True/False
            var u_internet_network_activity = result_elements.u_internet_network_activity; // True/False
            var u_none = result_elements.u_none; // True/False
            var u_sensory_data = result_elements.u_sensory_data; // True/False
            var u_sensitive_personal_information = result_elements.u_sensitive_personal_information; // True/False
            var u_protected_classification_characteristics = result_elements.u_protected_classification_characteristics; // True/False
            var u_professional_employment_info = result_elements.u_professional_employment_info; // True/False
            var u_other_personal_information = result_elements.u_other_personal_information; // True/False

            if (u_biometric_information == true) {
                current.u_biometric_information = true;
            }
            if (u_commercial_information == true) {
                current.u_commercial_information = true;
            }
            if (u_geolocation_information == true) {
                current.u_geolocation_information = true;
            }
            if (u_identifiers == true) {
                current.u_identifiers = true;
            }
            if (u_inferences == true) {
                current.u_inferences = true;
            }
            if (u_internet_network_activity == true) {
                current.u_internet_network_activity = true;
            }
            if (u_sensory_data == true) {
                current.u_sensory_data = true;
            }
            if (u_sensitive_personal_information == true) {
                current.u_sensitive_personal_information = true;
            }
            if (u_professional_employment_info == true) {
                current.u_professional_employment_info = true;
            }
            if (u_other_personal_information == true) {
                current.u_other_personal_information = true;
            }
            if (u_protected_classification_characteristics == true) {
                current.u_protected_classification_characteristics = true;
            } 
	current.setWorkflow(false);
        current.update();
        }
        current.update();
        if (current.u_biometric_information == false && current.u_commercial_information == false && current.u_geolocation_information == false && current.u_identifiers == false && current.u_inferences == false && current.u_internet_network_activity == false && current.u_sensitive_personal_information == false && current.u_sensory_data == false && current.u_other_personal_information == false && current.u_professional_employment_info == false && current.u_protected_classification_characteristics == false) {
            current.u_none == true;
            current.update();
        }

    } catch (e) {
        gs.warn("Couldn't run this script Error: " + e)
    }

 

6 REPLIES 6

Kieran Anson
Kilo Patron

Hey Aaron this is a bit of a monster script, I've tidied it up below for readability. Best practice in SN is to not be updating the current record in an onAfter BR either.

 

Couple other observations:

  1. You're using getDecisions - are you expecting more than 1 result? If so, you're going to be rapidly updating fields and overwriting previous values
  2. Are you using the ability in Decision Builder to return a default answer? This could be u_none = true in your case and avoid the complex if condition you have.
  3. Have you considered using flow designer as a low-code option?

 

var DECISION_TABLE = '5f86416e93a94210561430747aba1073';
//Below makes it easy to extend in the future.
var fieldInputMap = {
    'u_data_selected': 'u_if_customer_pii_data_selected',
    'u_customer_characteristics': 'u_cpii_customer_characteristics',
    'u_medical_insurance_information': 'u_cpii_medical_insurance_info',
    'u_commercial_information': 'u_cpii_commercial_information',
    'u_internet_communication_activity': 'u_cpii_internet_comm_activity',
    'u_biometric_information': 'u_cpii_biometric_information',
    'u_geolocation_information': 'u_cpii_geolocation_information',
    'u_sensory_data': 'u_cpii_sensory_data',
    'u_employment_education_information': 'u_cpii_employment_education_information',
    'u_inferences': 'u_cpii_inferences',
};

var decisionInput = {};
//Loop through the field input map, setting the key as the left side, 
//and getting the value of the "current" gliderecord from the right
Object.keys(fieldInputMap).forEach(function(field) {
    decisionInput[field] = current.getDisplayValue(fieldInputMap[field]);
});

var dt = new sn_dt.DecisionTableAPI();
var dtResponse = dt.getDecision(DECISION_TABLE, decisionInput);

if (gs.nil(dtResponse) || !Array.isArray(dtResponse))
    return;

//Hold our returned details in something easy to enumerate
var dtOutput = [];

//Cycle over the decision result values
//Also set the value on the current record
Object.keys(dtResponse.result_elements).forEach(function(key) {
    if (!('sys_meta' == key || 'sys_id' == key)) {
        dtOutput[key] = dtResponse.result_elements[key].toString();
		current.setValue(key , dtOutput[key]);
    }
});

//If everything is false, set u_none to true
//Below tests if atleast one field is "true" and stops
var hasResult = Object.keys(dtOutput).some(function(field){
	return dtOutput[field] == true
});

current.setValue('u_none' , !hasResult);

 

 Hello, @Kieran Anson 

Thank you for code snippet

 
Do you have any suggestions how to handle dynamic input for decision table in the code?
For example, if i need to find all records in decision table matching :  input1 or input2 or input3 (every time the number of inputs is different)
thank you in advance
 
 
 
 
 

Assuming it's not the decision table that is dynamically expanding with inputs, as that is possible given the APIs available to create decision tables, you can add a check in the decisionInputs builder like so

 

var fieldInputMap = {
    'u_data_selected': 'u_if_customer_pii_data_selected',
    'u_customer_characteristics': 'u_cpii_customer_characteristics',
    'u_medical_insurance_information': 'u_cpii_medical_insurance_info',
    'u_commercial_information': 'u_cpii_commercial_information',
    'u_internet_communication_activity': 'u_cpii_internet_comm_activity',
    'u_biometric_information': 'u_cpii_biometric_information',
    'u_geolocation_information': 'u_cpii_geolocation_information',
    'u_sensory_data': 'u_cpii_sensory_data',
    'u_employment_education_information': 'u_cpii_employment_education_information',
    'u_inferences': 'u_cpii_inferences',
};

var decisionInput = {};
//Loop through the field input map, setting the key as the left side, 
//and getting the value of the "current" gliderecord from the right
Object.keys(fieldInputMap).forEach(function(field) {
    var fieldValue = current.getDisplayValue(fieldInputMap[field]);
    if (!gs.nil(fieldValue))
        decisionInput[field] = current.getDisplayValue(fieldInputMap[field]);
});

The simple if check will check a value exists

Hi @Kieran Anson, I am using GetDecisions, as I do expect multiple results. I am only keeping the results that are true and updating a field based on which results is true. The false results are discarded. 

 

I'm not returning a default value currently, and not sure that would benefit me.

 

To be honest, I haven't, as I expected this to be an after business rule, based on when the Tieiring Assessment is completed. I might look into that.