Docs‎ > ‎

Live Logic Tutorial

  • Key element in the Training Ramp for Reactive Logic.
  • Recommended Pre-Requisites
  • Skim the advanced examples to scan the logic.  The logic is complex,  but a quick scan will give you a good sense of how Reactive Logic can address complex problems.

Using a Case Study approach of a familiar but complex database, this Tutorial explains the approach for using Espresso Logic.  It progresses from simple (and typical) examples, to very complex examples.

The Tutorial is designed to illustrate the key design patterns for Reactive Logic.  These are called out explicitly in the sections below.

Process Overview

The sub-sections below provide a summary of the steps to use Business Logic.  For further background, see the Overview and the Architecture.  

Create a Project

You begin by using the Logic Designer - accessed via the Browser - to create a project and register a database.

Logic Designer: REST Resources

The next typical step is to define some REST Resources to enable client development to begin.  Espresso Logic enables parallel development of client applications and business logic.

Logic Designer: Business Logic

Use the Logic Designer to declare your business logic.

The complete logic for the Sample is shown here, and described in the following sections.  Observe this is both...
  • Database Bound - your logic is bound to database tables and columns, so that it can be re-used over all transactions that affect the data.

  • Unordered - while this listing is organized by table, you can enter the logic in any order.  Execution will be ordered by the system based on dependencies.

  • Filterable - you can enter a search term in the upper left box of the Logic Designer.  This will filter the list of rules by table or word used in the description.  We use this service extensively to focus in on the rules relevant for a given transaction (Use Case) in this tutorial.

Sample Database

Click the image at right to view the structure of the Sample Database in a new window.  It is a small and familiar, but with sufficiently complex structures to enable us to explore several interesting Use Cases below.

Loading this Project

You can load this project into your account as described here.

Key Concept: Think Spreadsheet

Like many systems, Espresso provides an Event model, wherein you can write JavaScript event handlers to handle table updates.  Experienced programmers will understand them instantly.

The key to getting the value out of Espresso is to use events in conjunction with spreadsheet-like Reactive Logic.  We call it Think Spreadsheet, and a good way to understand it is via the examples below.

Going a bit further, these examples illustrate several of the Key Logic Patterns.  We recommend you review these concepts, so you have them at your disposal when addressing complex logic.  You'll find the rules to be deceptively simple - they are quite powerful.

You might want to keep a list handy of the rules.

Basic Examples

The following examples are "typically" complex, and are a great place to start learning about Business Logic.  The next section examines some more complex examples.

How you review these examples might depend on your objectives:

  • I am evaluating - I want to see some code, and understand solutions to a range of Use Cases
You can simply review the problems / solutions  (Note: these examples are provided in the download, although we have removed some comments here so things fit in a screen shot).
  • I am about to do a project - I need to see how to solve problems, and document my work
We suggest you have a window / sheet of paper for the data model and for the rules;
then try to solve each problem, and compare your solution to the sample

Quick note: the Home Page video was built upon the LogicDemo database.  The following examples are built upon the Sample (similar but larger).  

Place Order

Place Order has a number of different requirements that illustrate the most common business logic patterns.  

Requirement: Check Credit

When the client inserts an Order and some Lineitems, the business logic must check that the balance < creditLimit.  This requires that we derive the Customer's balance from the Order.amountUnPaid, a rollup of the Lineitem amounts.

The logic for Check Credit is declared as shown above.

The logic triggered by each LineItem insertion is summarized as follows (you can explore it here):
  1. the lineitem logic derives the amount

  2. this adjusts Order.amountTotal per its derivation rule; this automatically Forward Chaining to other Orders logic, which derives amountUnPaid 

  3. this adjusts Customer balance per its derivation rule, and verifies the check credit validation

That looks pretty simple, right?  But it is important to understand how rules fit into the overall process:

  • How were they devised?
You may have arrived at this design from a familiar "step-wise definition of terms" approach, where Analysts work with Business Users to formalize the definition of terms... these often introduce new terms (e.g., balance introduces the notion of amountUnPaid), until all terms are defined.
  • How are they managed - communicated to others (e.g., maintenance), and revised?

Note that the design and the implementation are the same.  So, the listing above is both communication, what runs, and what is altered during maintenance / iterative development.

Business Logic Pattern

This illustrates the most common Business Logic Pattern: Constraining a Derived Result.

It also illustrates the Replicate Junction Pattern.

Requirement: no Empty Orders

Since it makes no business sense to place an order with no line items, we implement the noEmptyOrder requirement using the following logic:

This example illustrates a number of concepts:

  1. Counts as existence checks - the itemCount indicates whether the order has any items
  2. Commit time validations - the validation is executed after item logic has adjusted the itemCount
  3. Constrain derived result
The last item bears some note.  As explained in Commit validations, using a "regular" validation would have the effect that all orders are rejected.  Not popular with the VP Sales.  Since Commit Validations run after all the rows are processed, the itemCount will reflect the Lineitems (if any), so the logic will operate as intended.

Make Order Ready

Placed Orders are typically placed in a "Shopping Cart" state (order.is_ready == false), where they do not affect Customer balance and Product quantities until a subsequent Make Order Ready transaction is executed.  So, we need to devise logic that, when an Order is "made ready" (PUT a purchase order, setting order.is_ready == true)...

  1. increases the customer balances and 

  2. adjusts Product quantities, and if reorderQuantity is exceeded, set reorderRequired

We solve this transaction by declaring the following logic:

Since the Customer has a Sum:

Derive customers.balance as sum(ordersList.amount_un_paid) where is_ready = true

The Balance is increased due to the Qualification Condition Change (is_ready) now being met.

Similarly, we don't want to reduce Product inventory, and set reorder flags, until Purchaseorders are marked as ready. So, we need to define logic to make this happen.

This is a bit more challenging, since the Product is not directly related to Orders, so that the qualification condition cannot reference orders.is_ready.  So, we introduce Lineitem.is_ready, enabling us to define the following logic:

Implementation Notes:
  1. The LineItems.isReady Lineitems.is_ready Formula is a Parent Reference, so changes are Forward Chain altered Parent References to Children to each Lineitem
  2. That activates Lineitem logic, where the change to the Qualification Condition adjusts the Product.totalQtyOrdered
  3. That activates Product Logic, which computes products.is_reorder_required

Business Logic Pattern

This illustrates a highly recommended and common Business Logic Pattern: the Ready Flag.

Integration Example

RESTful APIs are an excellent mechanism for interacting with other systems, both as a receiver and as a sender.  To understand how this example operates, please review this Integration Example, based on JavaScript Extensibility.

The following business logic builds on the MakeOrder logic (above) to send the Regulatory Reporting Message:

It operates in conjunction with the following Request Event, using SysUtility.getResource to retrieve the JSON for the designated Resource.

Resources for partner mapping

This illustrates a useful logic patterns: Resources to define partner column mappings.

Resources provide column projection and aliasing.

You can define Resources that map to partner names, which can be used to receive or send REST/JSON messages.

Advanced Examples

The patterns above illustrate the most common patterns we see in logic design. The sub-sections below describe the more complicated cases we have seen through extensive experience.

You will see that the solutions are remarkably short. So the coding to deliver complex problems is small. The solutions, on the other hand, are dense. This illustrates the power of logic to address complexity, and also that the real job centers on the design and approach instead of low level coding. Exactly where it should be.

Add Payment - allocate to orders

This is a classic example of the providing an allocation re-usable service via Business Logic Extensibility.  Here we add a Payment to a Customer, and its amount is allocated to that Customers' outstanding unpaid orders. 

Please see the database structure (excerpted above):
  • The allocateFromTo rule creates payment_order_allocation rows that represent the amount of the payment disbursed to each recipient Order.  

  • payment_order_allocation logic determines the exact amount allocated, 

  • Which then increments the orders.amount_paid 

  • Which in turn affects the orders.amount_un_paid, which adjusts the customers.balance.

The full logic (6 rules) is shown here:


The full payments event logic (summarized above) is shown here:

You can explore allocation using the Rest Lab, here.

Business Logic Pattern

Study this example carefully - Allocation is a very prevalent pattern.

Group By - total sales by month and salesrep

It is common to sub-total object by grouping them.  For example, we might to group orders by year, month and salesrep, to monitor sales activity.  These totals are maintained in the table empsales.

But, since empsales rows are not real entities (just sub-totals), it is cumbersome to create them.  For that, we can use Managed Parent to create them automatically.  The result is we can implement our Group By with the following:

The derivations to compute the foreign key and total_sales are straight-forward.

Bill Of Materials Price Rollup

Consider when a Product price is changed, and that product is a component of a kit.  The Requirement must be that each of the kits reflect the price change (e.g., if a bolt increases in price, so do all the kits that use bolts: wings, fuselages, etc). 

Recall the database structure:

The logic below illustrates the solution: 4 rules.  

They operate as follows when an End User changes a Products.price:

  1. The Product.price is referenced by product_billofmaterials.value.  So, when products.price is changed, parent references cascade (Forward Chain) to the product_billofmaterials rows to refire the referencing logic (value) for all the Kits using this component Product

  2. The product_billofmaterials.value value is referenced by Product.sum_components_value, so the system performs automatic adjustment processing for each kit using the component

  3. The products.price references the sum_components_value, so this recurses on steps 1 and 2 for each kit using the component

This example illustrates key rule behaviors:

Business Logic Pattern

This example illustrates Replicate Junction pattern, reflecting end-point changes.

Bill of Materials Kit Explosion

While described here as a separate topic, this is a requirement within Place Order.  When ordering a Product that is a kit (i.e., composed of other Parts, such as a plane with Wings etc), we want to reduce inventory for each of the components of the kit.

The key requirement is to populate the SubItems for a kit-based Lineitem.  See the database structure - subItems are a child of LineItem objects, representing the bill of materials explosion.  

The solution is to utilize the Insert Into From rule extension: see first action rule below.  The qtyOrdered rule computes computes the item quantity for kits (for non-kits, it simply returns / defaults the entered value).

The entire solution requires 4 rules:

Some of the lines above are summaries; we show the full logic here.  First, the complete event definition is shown below (this recursively creates the sub-items from each item):
The complete definition of quantity_ordered is a good illustration of conditional logic, here depending on whether the lineitem is a sub-item:

Click here to explore Bill of Materials Explosion.

Budget Rollup

Here is how to roll a budget up an org chart (database structure here).  2 rules:

Audit Salary Changes

This creates an audit by creating child rows on designated parent changes, with control over which attributes are copied into the audit trial.  1 rule:
Auditing is the simplest example of a family of Insert Into From rule extension.

Give Raise - transaction parameters

Most updates are updates (Posts, Puts or Deletes) to rows, processed per logic as shown in the example above.  Sometimes, however, transactions require arguments.  Consider giving an employee a raise, supplying the percent raise as a argument.

You can issue a POST like this:

Which is handled by your logic like this, by reference to the Request Object:

Ignore Extra Attributes in a POST

The ability to pass arguments to your rules on the URL (arg.ArgName1=1) can be accessed using the req.getUserProperties().get("ArgName1")
One special argument main:customer?arg.IgnoreExtraAttributes=1 will allow you to pass additional attributes in your JSON during a POST or PUT that are not part of the database structure. This can be helpful in passing values from your client system that are useful for updates or special logic processing. 

Under Construction

This sample is currently under development.  Please contact us if this Use Case is critical to you.

Deep Copy Purchaseorder and Items

Copy services are provided for cloning business objects, including provisions for copying related child data such as the Lineitems for a Purchaseorder.  These are typically called via a single action rule, so cloning a Purchaseorder is 1 rule

The Logic Method is shown below, based on the Insert logic extension:

var arg = req.getUserProperties().get("clone");
log.debug("cloneXX: checking request arg.clone parameter was provided: " + arg);
if (arg !== null && logicContext.logicNestLevel < 1) {
    log.debug("cloning: " + row);
    var deepCopy = ["lineitemsList"];
    SysLogic.copyTo("orders", logicContext, deepCopy, false); 

To activate the copy function in the RESTlab, GET the first order, paste it to the request, and PUT with the following url argument, like this: