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.
Probably the most common pattern is defining a validation that requires a series dependent derivations to produce the data used in the validation. The most familiar example is Check Credit, where the Customer's balance is derived by a series of derivations over 3 Domain Objects.
Business Logic services enable you to access data from related Domain Objects:
Automatic adjustment processing occurs when child rows are changed in such a manner
The count derivation can produce a count of related child rows, optionally qualified by a condition. In many cases, the objective is to know whether the count is 0 or non-zero - that is, are there any [qualified] children. For example:
You introduce Junction Tables for many-to-many relationships between 2 end-point objects. It is often a requirement that an end-point object needs to sum/count an attribute from the other end-point. Since sums/count operate on 1:n relationships - and not n:m relationships, you will need to replicated the summed attribute into the Junction.
The replicate can take two forms, depending on whether the sum should reflect changes in the summed attribute. The Tutorial illustrates both, as discussed in the sub-sections below.
The Bill of Materials Price Rollup example illustrates is a many to many relationship between Product objects, informally referred to as Kits and Components.
The classic request pattern is to invoke behavior from the construction of Command Objects. Such objects can be maintained in a list and used for undo, for example.
The same pattern can be used in data processing applications. The request object is inserted, representing a transaction requesting some behavior such as a Credit Request, or an Employee raise. Instead of code, you declare logic to implement the desired behavior.
This pattern can be extended to non-database Use Cases, for example commands.
It is a very common requirement to drive Form flow based on derivation results. For example, you might define a Wizard for Document Processing, with tab sheets enabled/activated on the basis of whether restricted Products are ordered, or the customers credit history. Derivations are excellent mechanisms to compute the data used to drive such conditional transitions.
Recall that derivations fire only when a transaction is saved. We therefore recommend using the Ready Pattern, as described below.
Imagine an interactive transaction where the End User proceeds through a set of screens. When screen-1 is complete:
Of course, it is highly undesirable to hold an open database transaction (and blocking locks) over screen transitions. Given that you need the Business Logic derivation results as noted above, this suggests that you should submit - and commit - changes at the completion of screen-1.
But this presents a problem: it might not be appropriate to "post" this incomplete transaction (e.g., adjust General Ledger, the Customer Balance, Product stock) until all the screens are complete.
The Best Practice approach is to:
Be aware that logic processing occurs in two phases: logic phase (initial row processing), and commit phase (after all rows are processed). Counts of inserted child rows are always 0 during the logic phase, so requirements such as No Empty Order (which depend on the count value) need to use Commit Validations.
It is often necessary to enable Business Users to alter data used in formulas. For example, you might apply a
You can achieve this easily as follows:
Create a "scalar" Domain Object (e.g.,
2 - Provide
Define your Logic Classes to extend3 - Use LogicBase in formulas
You can store subtotals that are incrementally maintained as updates occur, using the Group By Pattern. For example, you might wish to maintain total sales for each sales rep for each month, as explained here.
The following sections describe patterns implemented by the extension package provided with the product. These are critically important, both for use (they are very common patterns), and as illustrations of how to provide logic extensions.
Put differently, the system receives a quantity of things (money, goods), and allocates them to a set of recipients. Some examples:
It is common for logic to require searching lists to verify whether or not objects are present, for example:
For example, an Employee might have 2 child collections of languages: spokenLanguage and translatesLanguage. It is reasonable to ensure that each spoken language has a row for that user / language in spokenLanguage.
We therefore provide a set of logic services for FindWhere, that enable you to search through a list to find rows that match a specified criteria. You can search for the first row that matches, or the only row (which throws an exception if there are multiple matches).