Skip to main content
Version: 4.1.0

Make decisions

The decision-making process is based on the rule engine that relies on two distinct rule files written in the Drools MVEL dialect:

  • Default rule files are out-of-the-box sets of rules designed to handle standard decision-making scenarios and serve as the system baseline. These files should not be modified, and their file names must remain unchanged. The files are located in S3:

    • doc-upload/payment_sanctions_screening/{tara_version}/rules/hit_rules.drl contains hit rules that run at the hit level.

    • doc-upload/payment_sanctions_screening/{tara_version}/rules/alert_rules.drl contains alert rules that run at the alert level.

  • The custom rule file allows you to implement rules tailored to specific business requirements. These rules are flexible and are used instead of the default rules to handle unique requirements. You can copy default rule files, modify their content as needed, assign a filename to your custom file, and add the name to the configuration. You must create the file manually and upload it to the following S3 location: doc-upload/payment_sanctions_screening/rules/custom_rules.drl. You can use custom_rules_sample.drl as a sample custom file.

Create rule

Facts and globals

In Drools, globals and facts are two fundamental concepts used to pass external data and context to rules and represent the data that rules act upon:

  • Facts are the data objects or domain objects that rules use to make decisions. A fact can be any Java object, and it serves as the basis for rule conditions, such as the when section of a rule. The following facts are defined:

    • PaymentMessage

    • PaymentMessageHit

    • PaymentInputEntity

    • PaymentDerivedData

    • PaymentWatchListEntity

    • TypeMatch

  • Globals are external objects made available to your rules, but, unlike facts, they are not part of the working memory. Globals provide a way to inject external resources, services, or configuration settings into your rules. Globals are typically immutable within a single rule execution. Once set, the value does not change during the rule execution. The following globals are defined:

    • idMatch

    • typeMatch

    • nameMatch

    • countryMatch

    • addressMatch

    • nameMatchingThreshold

    • dateMatchingThreshold

    • modelDecision

By combining facts and globals, you can build complex and flexible rule-based systems that leverage external resources while making decisions based on the current state of your data.

See the example to illustrate the use of facts and globals in Drools:

import com.example.Order

global com.example.ShippingService shippingService

rule "Apply Shipping Discount"
when
$order: Order(totalAmount > 100)
then
double discount = shippingService.calculateDiscount($order);
$order.applyDiscount(discount);
end

In the example:

  • Order is a fact that represents the order with a total amount.

  • shippingService is a global that provides access to a shipping service to calculate discounts.

  • The rule applies a discount to the order if its total amount is larger than 100. It uses both the fact and the global to make this decision.

When

In most cases, the section is required to qualify a hit or watchlist entity for a new rule. You can use any objects mentioned above. See the code sample:

$hit: PaymentMessageHit(conditions via comma)
$wle: PaymentWatchListEntity(conditions via comma)
eval (expression)

Then

The section contains two available options:

  • Resolve:

    resolve("comment", rulesDecision)
  • Escalate:

    escalate("comment", rulesDecision)

Salience

The out-of-the-box default rules have salience in the range of 3000 to 1000.

In Drools, the salience attribute is a crucial element in the rule definition that influences the execution order of rules within a rule file. It allows you to specify the priority of a rule relative to the other ones. Rules with higher salience values are executed before rules with lower ones. You can assign an integer value to the salience attribute to set up the rule execution order.

Mind the following key points about the salience attribute in Drools:

  • Execution order. The salience attribute determines the execution order of rules. The higher the value, the more important the rule is, and it gets executed earlier in the rule execution cycle.

  • Default value. If a rule does not specify a salience value, it is assigned the default value of 0. Rules without explicit salience values are executed in an arbitrary order and can depend on the rule engine's internal decisions.

  • Ascending order. When evaluating rules with the salience values, Drools arranges them in the ascending order. Rules with the lowest salience values are executed first, followed by rules with higher values.

  • Negative values. You can assign negative salience values to rules if you want specific rules to be executed earlier than rules with positive salience values. For example, a rule with salience -1 is executed before a rule with salience 0.

  • Use cases. The salience attribute is used to control the rule execution order or prioritize rules based on a specific business logic, for example, when specific rules should have precedence over others.

  • Caution. While the salience attribute can be a powerful tool for rule prioritization, it should be used judiciously. Overusing or misusing of salience values can make rule sets complex and hard to manage. Maintain clarity in your rule definitions and document the reasons for setting particular salience values.

Thus, the salience attribute is a mechanism used to control the rule execution order based on assigned priorities. By assigning salience values to rules, you ensure that rules critical to your business logic execute in the desired order, allowing you to create a robust and efficient rule-based system.

Add custom rule file

To write rules, you can use the following applications:

To add a rule, complete the following steps:

  1. Create a custom rule file locally. The recommended filename is custom_rules.drl.

    You can use a different name for your custom rule file and specify it when configuring Tara. This allows you to maintain multiple versions of the rule file, which is useful for managing variations or retaining versions for auditing purposes.

  2. Edit the rule file. Use any text editor of your choice to open the file.

  3. Create a rule using the following template:

    rule "Name of the rule"
    activation-group "default"
    salience 2003
    when
    // Evaluation of the rule conditions goes here
    then
    // Define the actions to resolve or escalate based on the rule
    end
    1. Replace "Name of the rule" with a meaningful and descriptive name for your rule.

    2. Leave activation-group as "default".

    3. Set salience based on specific requirements.

    4. In the when section, define the conditions to be met for the rule to trigger.

    5. In the then section, specify the actions to be taken when the rule is triggered, including how to resolve or escalate the decision.

  4. Save the changes.

  5. Upload the modified file to S3: doc-upload/payment_sanctions_screening/rules/custom_rules.drl.

Example

As an example, let's implement the following business rule: "A hit should be resolved when the sender and the receiver are from the same country. Should be executed before the default rules."

  1. Define the rule structure:

    • Leave activation-group "default". This is a required value.

    • Set salience to 4000. As the rule should be executed before the default one, you must set the salience value to more than 3000.

    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when

    then

    end
  2. Define the when section:

    1. Specify the $message object.
    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage()
    then
    end
    1. Add base filtering for the message based on the payment info object.
    tip

    In Drools MVEL, you can call fields of the objects in () and also use . to access fields in the nested objects.

    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null)
    then
    end
    1. Add filtering for the country existing in the sender and receiver objects. Check for null values to avoid a Null Pointer Exception.
    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null,
    payment.sender.country != null, payment.reciever.country != null)
    then
    end
    1. Add a condition to evaluate the hit. You can use $message to get the sender and receiver data. Wrap all conditions in the eval() method to produce a Boolean outcome.
    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null,
    payment.sender.country != null, payment.reciever.country != null)
    eval($message.payment.sender.country == $message.payment.reciever.country)
    then
    end
  3. Define the then section.

    rule "Sender and Receiver from the same country"
    activation-group "default"
    salience 4000
    when
    $message: PaymentMessage(payment != null, payment.sender != null, payment.reciever != null,
    payment.sender.country != null, payment.reciever.country != null)
    eval($message.payment.sender.country == $message.payment.reciever.country)
    then
    resolve("Sender and Receiver countries are the same: " + $message.payment.sender.country, rulesDecision)
    end

Migrate custom rules for version compatibility

The rule file structure can change between Tara versions. As a result, custom rules created in earlier versions might need to be synchronized manually. Starting with Tara v4.1.0, note the following changes:

  • The derived object is no longer referenced in the rule file. All key data points are moved to the consolidated idMatch, countryMatch, and addressMatch objects.

    Remove all references to the derived object, such as derived != null, and replace:

    • $hit.derived.address with addressMatch.input

    • $hit.derived.countryConfirmed with countryMatch.countryConfirmed

    • $hit.derived.addressConfirmed with addressMatch.countryConfirmed

    • $hit.derived.subType with idMatch.subType

    • derived.subType with idMatch.subType

    • derived.type with typeMatch.inputType

  • The IdMatch object is updated. Replace global com.workfusion.sanctions.jnw.domain.rules.ModelFeature idMatch; with global com.workfusion.sanctions.jnw.domain.rules.IdMatch idMatch;.

  • Rules are split into hit rules and alert rules.

    • Hit rules run when the rule has the agenda group set to hit (agenda-group "hit").

    • Alert rules run when the rule has the agenda group set to alert (agenda-group "alert"). A

    rule "blacklist_country_strong"
    activation-group "default"
    agenda-group "hit"
    salience 1700
    • Alert rules are intended to set the final MessageDecision output comment and status fields.

    Example of setting the default MessageDecision.comment:

    decision.setComment(RulesUtils.getStatisticalAlertLevelComment(decision, decisionStatistic));

    Example of setting the default MessageDecision.status:

    decision.setStatus(RulesUtils.getAlertLevelStatus(decision, decisionStatistic));

    The provided DecisionStatistic object contains information about the final alert decision from Tara. You can use this object to create custom comments and statuses that differ from the default values (RESOLVE and NO_DECISION). For example, you can define custom statuses, such as PASS, HALF_PASS, L1, or L2.

    public class DecisionStatistic {
    private final int numHitsResolved;
    private final int numHitsDrResolved;
    private final int numHitsEscalated;
    private final Map<String, Integer> decisionCodeCounts;
    private final List<String> resolveReasons;
    private final List<String> noDecisionReasons;