Model the second Rulesheet
- Last Updated: March 24, 2022
- 13 minute read
- Corticon
- Version 6.3
- Tutorials
Let’s take a quick look at what we did in the first Rulesheet (checks.ers):
- We defined an action-only rule to extract the department code from the barcode of each item.
- We defined a rule to identify if there are any items from the Liquor department, and if so, to raise an alert.
- We defined a rule to check if a customer is a preferred card holder.
- Finally, we defined another action-only rule to calculate the total price of items in the shopping cart.
Now, we are ready to model the second Rulesheet. Recall that the second Rulesheet corresponds to the second substep in the Checkout process.
In the second Rulesheet, we apply some promotional rules to our Preferred Account holders when they spend a pre-defined amount of money or buy items from specific departments at our store. The promotions may change frequently, but modeling them in Corticon will make future changes much easier.
Create the Rulesheet
Create a second Rulesheet under the MyAdvancedTutorial rule project. Name it coupons. Ensure that it uses the groceryStore.ecore Vocabulary.
Define the rule scope
Next, let’s define the rule scope. Open the Scope pane, by selecting Rulesheet > Advanced View. Just like in the checks.ers Rulesheet, we will build our Scope around the Customer entity, since we want to apply promotional rules to each preferred customer. Define the rule Scope as shown:
Notice that once again, you assigned the alias currentCart to a customer’s shopping cart, just like in the checks.ers Rulesheet. In addition, you have created two new aliases to define the currentCart.item perspective of the data. For now, the two aliases (allItems and sodaItems) represent the same perspective, but we’ll differentiate between them shortly. Finally, as before, the account alias represents the preferredCard account associated with our customer.
Save the Rulesheet.
Create a Ruleflow
Before we define rules in the coupon.ers Rulesheet, let’s create a Ruleflow and add the checks.ers and the coupons.ers Rulesheets to it. When multiple Rulesheets are included in a Ruleflow (a single .erf file), the Rulesheets will execute in a sequence determined by their Rulesheet order in the Ruleflow.
Creating a Ruleflow at this point is a good practice. Instead of testing only the Rulesheet as we develop it, we will test the whole Ruleflow, since the Ruleflow represents the decision step that needs to be automated. This enables us to test not only the rules as we define them in the Rulesheet, but also how the Ruleflow works, and how the rules behave as part of the Ruleflow. This way, we can detect and fix problems earlier in the lifecycle.
Create a Ruleflow as follows:
- Right-click the MyAdvancedTutorial rule project in the Project
Explorer view and select File > New > Ruleflow.
- In the Create New Ruleflow wizard, enter MyAdvancedTutorial as the
Ruleflow file name and click Next.
- Confirm that groceryStore.ecore is selected as the Vocabulary, and then click Finish.
The Ruleflow opens in the its editor.
Now we’ll add Rulesheets to the Ruleflow:
- Drag and drop checks.ers from the Rule Vocabulary view to the
Ruleflow editor.
- Drag and drop coupons.ers from the Rule Vocabulary view to the
Ruleflow editor, placing it to the right of the checks.ers Rulesheet.
- Click Connection in the Palette.
- Click on checks.ers, keep the mouse pressed, and drag the connection
to the coupon.ers Rulesheet. Your final output should look like this. The Ruleflow
shows the Rulesheet processing sequence.
Save the Ruleflow.
Define a Filter in the coupons.ers Rulesheet
Now, let’s go back to our coupons.ers Rulesheet. Before we continue modeling our promotional rules, we need to define a filter to filter out customers who do not have preferred accounts. This is because the promotional rules apply only to customers who have a preferred account card.
To do this, we must define a Filter expression. A Filter expression acts to limit or reduce the data in working memory to only that subset whose members satisfy the expression. A filter does not permanently remove or delete any data, it simply excludes data from evaluation by the rules in the same Rulesheet.
We often say that data satisfying the Filter expression “survives” the filter. Data that does not satisfy the expression is said to be “filtered out.” Data that has been filtered out is ignored by other rules in the same Rulesheet. Note: Data filtered out in one Rulesheet is not also filtered out in other Rulesheets unless you include the Filter expression in those Rulesheets, too.
Create a Filter expression in the Filters pane as shown.
![]()
The Filter expression (Customer.isPreferredMember=T) “filters out” all non-preferred customers by allowing only those customers with an isPreferredMember attribute value of true to pass (survive). Those customers whose isPreferredMember attribute value is not true are filtered out and not evaluated by other rules in this Rulesheet.
Define a rule to calculate cashBackEarned
The first rule we will define in the coupons.ers Rulesheet is to calculate cash back for every preferred customer.
Define an action-only rule (with a rule statement) as shown:
![]()
As you can see, action row A in column 0 calculates the cashBackEarned for a customer’s total purchase. Our rule defines the formula as the totalAmount of all items in the customer’s shopping cart multiplied by 0.02, which is the same as 2% of totalAmount.
Save the Rulesheet.
Now, let’s test this rule as part of the Ruleflow. Testing at the Ruleflow level ensures that Rulesheets are processed in the correct sequence and allows values derived in prior Rulesheets to be used in subsequent Rulesheets.
Create a Ruletest named coupons1. Ensure that the test subject of the Ruletest is the MyAdvancedTutorial.erf Ruleflow.
To test the rule, we need to provide input data where the customer is a preferred account holder. Add a few items to the shoppingCart and enter names and prices for each of them. Enter details in the Input pane of the Ruletest as shown here:
![]()
According to the rule we are testing, the shopping cart of a preferred cardholder should earn cash back equal to 2% of the totalAmount in the shopping cart. Also notice that the list of items contains an item from the Liquor department. This should raise an alert, based on the rules in the checks.ers Rulesheet, which is part of the Ruleflow.
Run the Ruletest.
![]()
Notice that the totalAmount attribute now has a value of $98.99 (as calculated by a rule in checks.ers) and the cashBackEarned attribute has been assigned a value of $1.9798, or 2% of $98.99. Our rule has worked as expected.
Define a rule to calculate cumulative cash back
Now that we have calculated cash back earned, we need a rule to add it to cumulative cash back. Note: In our third Rulesheet, we will define a rule to address the scenario where a customer wants to apply their cumulative cash back to a purchase.
Define an action-only rule as shown:
![]()
Action row B in Column 0 calculates the cumulativeCashBack amount in a customer’s account by incrementing its value (using the += Decimal operator) by the cashBackEarned in the current shopping cart.
Add a rule statement with dynamic data
It is often a good idea to define rule statements that contain dynamic data—where the value of an attribute is extracted and added to the rule message. This can provide more meaningful and informative rule messages.
In this case, we want the value of cashBackEarned as well as cumulativeCashBack to be part of the rule message. We do this by enclosing the attributes in curly braces in the rule statement as shown:
![]()
Save the Rulesheet.
Test the rule
Now, let’s test the rule. Create a Ruletest named coupons2.ert that uses MyAdvancedTutorial.erf as its test subject.
To test that cash back earned is being added to cumulative cash back, we need a starting amount for cumulative cash back and a total amount for the shopping cart. We define in the test input a customer who is a preferred account holder, whose cumulative cash back is $10, and whose total amount (for the shopping cart) is $100. We’ve already tested this Ruleflow’s ability to sum up the prices of each individual item to calculate a totalAmount, so we don’t need to enter individual item prices again.
Define the input as shown here:
![]()
Run the test.
As you can see, the rule works as expected. The rule calculates the cash back earned ($2) based on the total amount ($100), and adds it to the cumulative cash back ($10), giving it the updated value of $12. Notice that the rule message contains this data as well.
Define a promotional rule for customers purchasing from the Floral department
Now that the cumulative cash back rule is complete, let’s move on the next business rule:
For every item purchased from the Floral department, a coupon must be issued for a free balloon. Let’s assume that the Floral department has the department code 290.
Define a rule in coupons.ers as shown.
![]()
The first Condition in our Rulesheet is used to identify any items purchased from department 290 (the Floral Department). For each item identified, we want to give the customer a coupon (using the Entity operator .new) for a free balloon.
We assign the value of 12/31/9999 to the expirationDate attribute, which is one way to indicate that the expiration date is indefinite. This is the appropriate date format for our use case. Your preferred format might be 31/12/9999. Or any one of the dozen date formats defined in Corticon.
Save the Rulesheet.
Testing the rule
Create a Ruletest named coupons3.ert. Define the input data as shown.
![]()
In this Ruletest, we want to make sure that when an item has been purchased from the Floral Department (department 290), a new Coupon is created entitling the customer to one free balloon.
Notice also that we set cumulativeCashBack to 0 for this test. One of the rules in the coupons.ers Rulesheet (in Action row B, column 0) needs a real initial value of cumulativeCashBack to increment. If its initial value is null, the rule will not fire.
Run the test.
Our rule has worked as expected. As you can see, department 290 has been recognized and the informational message has been posted. Also, our new Coupon entity has been created, displaying a value of One Free Balloon in the description attribute and 12/31/9999 in the expirationDate attribute, indicating that the coupon will not expire (practically speaking).
Also, note the new message posted by our new rule—it contains the value of allItems.name embedded in it.
Define a promotional rule for customers purchasing more than 3 soda/juice items
Let’s move on to the next business rule:
This rule must create a “$2 off” coupon when a customer buys 3 or more items from the Soda/Juice department. When we were determining whether any items from the Floral Department were in the shopping cart, we used the allItems alias. But to determine if 3 or more items were purchased from the Soda/Juice department, we don’t need to count all items in a shopping cart, just those from the Soda/Juice department. We’ll use the sodaItems alias we defined earlier in the Scope section.
To reduce the collection of items in the shopping cart to only those we want to count, we will use a Filter expression to filter the sodaItems alias. Let’s assume that the department code for the Soda/Juice department is 285. Define a Filter expression as shown:
The filter in row 2 ensures that the “surviving” members of the sodaItems alias all have a department value of 285.
Now, let’s model the rule. The Collection operator →size counts the number of elements in a collection. We’ll use this operator to check how many soda/juice items are in the shopping cart. Define a condition as shown:
If the number of items counted by the →size operator in the sodaitems collection is 3 or more, then a $2 off coupon will be issued to the customer. Define the action for this as shown:
The action creates a new Coupon. The expirationDate attribute derives its value from the Date operator .addYears, set here to 1, so we know that the coupon will expire one year from its date of issue.
Save the Rulesheet.
Next, let’s test this rule. Create a Ruletest named coupons4.ert that uses the MyAdvancedTutorial.erf Ruleflow as its test subject.
To test this rule, our shopping cart must contain 3 or more items from the Soda/Juice Department (department 285). Additionally, the customer must be a preferred account holder so that the data passes the filter (Customer.isPreferredMember=T) in this Rulesheet. Finally, the cumulative cash back must be set to 0, to enable an earlier rule to fire, where cashBackEarned is added to cumulativeCashBack (and it cannot be added to a null value). Define the input as shown:
Run the Ruletest.
The rule works as expected. The items from the Soda/Juice department have been identified and counted. A Coupon has been added with a “$2 off next purchase” description and an expirationDate of 06/01/2016 (which is 1 year from the date this test was run).
The other rules have fired as well. For example, the total amount of the shopping cart and the cash back earned have been calculated. The cash back earned has been added to the cumulative cash back (which was set to 0).
Define a promotional rule for customers purchasing more than $75 in this cart
Let’s now model the last rule in the coupons Rulesheet:
The last rule checks if the total amount is $75 or more, and if so, issues a coupon for 10% off of a future gasoline purchase. Define this rule as shown:
The rule condition identifies when the totalAmount of a customer’s shopping cart is $75 or more. The rule action creates a new coupon (again, using the .new operator) for 10% off a future gasoline purchase. The expirationDate attribute derives its value from the Date operator .addMonths, set here to 3, so the coupon will expire three months from its date of issue.
As always, it is a good practice to add a corresponding rule statement, explaining in clear language what the business rule does.
Let’s test this rule. Create a new Ruletest named coupons5.ert that uses the MyAdvancedTutorial.erf Ruleflow as its test subject.
For our test, we need to include items in the shopping cart that add up to more than $75 in order to generate a 10% off gas coupon. Define the input as shown.
Run the test.
Our rule has worked as expected. The items have been totaled and the amount exceeds the $75 threshold so the 10% off Coupon has been created.
We have now modeled all the rules in the Calculations, Promotions and Coupons substep of the Checkout process.
Here is our completed Rulesheet: