Let’s take a quick look at what you did in the first Rulesheet (checks.ers):

  • Defined an action-only rule to extract the department code from the barcode of each item.
  • Defined a rule to identify the presence of any items from the Liquor department, and if present, to raise an alert.
  • Defined a rule to check if a customer is a preferred card holder.
  • Finally, you defined another action-only rule to calculate the total price of items in the shopping cart.

Now, you 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, you apply some promotional rules to the preferred account holders when they spend a pre-defined amount of money or buy items from specific departments at the store. The promotions may change frequently, but modeling them in Corticon makes future changes much easier.

Create the Rulesheet

  1. Create a second Rulesheet under the MyAdvancedTutorial rule project.
  2. Name it coupons.
  3. Ensure that it uses the groceryStore.ecore Vocabulary.

Define the rule scope

To define the rule scope:

  1. Open the Scope pane, by selecting Rulesheet > Advanced View.
  2. Like in the checks.ers Rulesheet, build the scope around the Customer entity, to apply promotional rules to each preferred customer.
  3. Define the rule scope as shown:


    1. Assign the alias currentCart to a customer’s shopping cart, just like in the checks.ers Rulesheet.
    2. Create two new aliases (allItems and sodaItems)to define the currentCart.item perspective of the data.
    3. Use the account alias to represent the preferredCard account associated with the customer.
  4. Save the Rulesheet.

Create a Ruleflow

Before you 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 execute in a sequence determined by their Rulesheet order in the Ruleflow.

At this point, it is good to create a Ruleflow so that instead of testing only the Rulesheet as you develop it, you can test the whole Ruleflow, which represents the decision step that needs to be automated. It enables you to test not only the rules as you define them in the Rulesheet, but also how the Ruleflow works, and how the rules behave as part of the Ruleflow. This way, you can detect and fix problems earlier in the lifecycle.

Create a Ruleflow as follows:

  1. Right-click the MyAdvancedTutorial rule project in the Project Explorer view and select File > New > Ruleflow.


  2. In the Create New Ruleflow wizard, in the File name field, type MyAdvancedTutorial, and click Next.


  3. Confirm that groceryStore.ecore is selected as the Vocabulary, and then click Finish.

The Ruleflow opens in its editor.

Now let's add Rulesheets to the Ruleflow:

  1. Drag checks.ers from the Rule Vocabulary view, and drop it in the Ruleflow editor.


  2. Drag coupons.ers from the Rule Vocabulary view, and drop it to right of the checks.ers Rulesheet.


  3. Click Connection in the Palette pane.
    Note: The Ruleflow Palette for JavaScript does not have the Service Call-out and Iterative options.
  4. Select and hold checks.ers, and drag the connection to coupon.ers. The Ruleflow shows the Rulesheet processing sequence.


  5. Save the Ruleflow.

Define a Filter in the coupons.ers Rulesheet

Now, let’s go back to the coupons.ers Rulesheet. Before you continue modeling promotional rules, filter out customers who do not have preferred accounts because the promotional rules apply only to customers who have a preferred account card.

Define a Filter expression. A Filter expression, which 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.

The data satisfying the Filter expression survives the filter, and data that does not satisfy the expression is 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.



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 you define in the coupons.ers Rulesheet is to calculate cash back for every preferred customer.



  1. Define an action-only rule (with a rule statement) as shown:

    The action row A in column 0 calculates the cashBackEarned for a customer’s total purchase. This 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.

    Note: Often, it’s desirable to use another Vocabulary attribute (a parameter) to hold a value, such as the percentage used in this formula, rather than hard-coding it (as in 0.02). If the value of an attribute such as cashBackRate is derived by other rules or maintained in an external database then it can be changed without changing the rule that uses it.
  2. Save the Rulesheet.
  3. Test this rule as part of the Ruleflow. Testing at the Ruleflow level ensures that Rulesheets are processed in the correct sequence and allows the values derived in prior Rulesheets to be used in subsequent Rulesheets.
  4. Create a Ruletest named coupons1. Ensure that the test subject of the Ruletest is the MyAdvancedTutorial.erf Ruleflow.
  5. To test the rule, 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 by entering details in the Input pane of the Ruletest:

    Note: According to this rule, the shopping cart of a preferred cardholder should earn cash back worth 2% of the totalAmount in the shopping cart.
    Note: Because the list of items contains an item from the Liquor department, based on the rules in the checks.ers Rulesheet, (part of this Ruleflow), an alert should be raised.
  6. Run the Ruletest.


The rule has worked as expected. 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.



After calculating the cash back earned, you need a rule to add it to cumulative cash back.
Note: In our third Rulesheet, you 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 cumulativeCashBack amount in a customer’s account by incrementing its value (using the += Decimal operator) by cashBackEarned in the current shopping cart.

Add a rule statement with dynamic data

You should define rule statements that contain dynamic data—where the value of an attribute is extracted and added to the rule message. It can provide more meaningful and informative rule messages.

In this case, the value of cashBackEarned and cumulativeCashBack to be part of the rule message, so enclose the attributes in curly braces in the rule statement as shown:



Save the Rulesheet.

Test the rule

  1. Create a Ruletest named coupons2.ert that uses MyAdvancedTutorial.erf as its test subject.
  2. To test that cash back earned is being added to cumulative cash back:
    1. note the starting amount for cumulative cash back and the total amount for the shopping cart.
    2. In the test input define a customer who is a preferred account holder, whose cumulative cash back is $10, and whose total amount (for the shopping cart) is $100.
    Note: Because you have already tested this Ruleflow’s ability to sum up the prices of each individual item to calculate a totalAmount, do not enter individual item prices again.
  3. Define the input as shown here:

    Note: When building Ruletests, if a Rulesheet’s Filters are not satisfied, they may prevent the rules from executing. This Rulesheet has a Filter expression that filters out all customers who aren’t Preferred Card members. So this test has a customer who is a preferred account holder in our test, to ensure that the Filter is satisfied, and the new rule model has a chance to execute.
  4. Run the test.


    The rule works as expected. It 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 also contains this data.

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.



The first Condition in this Rulesheet is used to identify any items purchased from department 290 (the Floral Department). For each item identified, give the customer a coupon (using the Entity operator .new) for a free balloon.

You 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 this use case. Your preferred format might be 31/12/9999 or any one of the dozen date formats defined in Corticon.

Note: While JavaScript has one output format for a dateTime, its input format for a dateTime can be any of several familiar formats.
Note: There are other ways to set an indefinite expiration date. For example, the entity CouponDefine a rule to calculate cumulative cash might have a Boolean attribute named expires, to which a true or false value could be assigned inside the .new expression.

Save the Rulesheet.

Testing the rule

  1. Create a Ruletest named coupons3.ert
  2. Define the input data.

  3. Ensure 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.
  4. 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.
  5. Run the test.


    Note: In the JavaScript product the default output format for dateTime as:

The rule has worked as expected. Department 290 has been recognized and the informational message has been posted. The 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.

The new message has been posted containing 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 three or more items from the Soda/Juice department. While determining whether any items from the Floral Department were in the shopping cart, you used the allItems alias. But to determine if three or more items were purchased from the Soda/Juice department, you do not need to count all items in a shopping cart, just those from the Soda/Juice department. You use the sodaItems alias you defined earlier in the scope section.

To reduce the collection of items in the shopping cart to only those you want to count, 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 code of 285.

Now, let’s model the rule. The Collection operator →size counts the number of elements in a collection. You use this operator to check how many soda or 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 three or more, then a $2 off coupon is issued to the customer. Define this 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 the coupon expires one year from its date of issue.

Save the Rulesheet.

Next, let’s test this rule.

  1. Create a Ruletest named coupons4.ert that uses the MyAdvancedTutorial.erf Ruleflow as its test subject.
  2. To test this rule, the shopping cart must contain three or more items from the Soda/Juice Department (department 285).
  3. The customer must be a preferred account holder so that the data passes the filter Customer.isPreferredMember=T in this Rulesheet.
  4. 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).
  5. Define the input as shown:


  6. 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 07/13/23 (which is 1 year from the date this test was run).
Note: In JavaScript, the output is in the format:

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).

Note: You should run multiple tests with different data to make sure that the rules work as expected in different scenarios. For example, you could change the department code of one of the items to 291 (liquor) and another one to 290 (floral). When you run the test with the new data, the alert to check the customer’s ID (liquor) and the free balloon coupon (floral) should be generated. However, the soda coupon should not get generated as you no longer have three soda items.

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% discount on a future gasoline purchase. The expirationDate attribute derives its value from the Date (or DateTime) operator .addMonths, set here to 3, so the coupon expires in 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.

  1. Create a new Ruletest named coupons5.ert that uses the MyAdvancedTutorial.erf Ruleflow as its test subject.
  2. 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.


  3. Run the test.


    Note: The dateTime output in the JavaScript product is in the format:

This rule has worked as expected. The items have been totaled and the amount exceeds the $75 threshold so the 10% off coupon is created.

You have now modeled all the rules in the Calculations, Promotions and Coupons substep of the Checkout process.



Here is the completed Rulesheet: