Skip to content

Logic: Rule Types, Patterns

💡 TL;DR - Logic: multi-table derivations and constraints, using Rules and Python

Logic addresses multi-table derivations and constraints, using Rules and Python. Rules are:

  1. Declared with WebGenAI or IDE and Code Completion - 40X more concise
  2. Activated on server start
  3. Executed - automatically - on updates (using SQLAlchemy events)
  4. Debugged in your IDE, and with the console log

For more on WebGenAI, click here.

Rule Types

The table shows excerpts only; see the ApiLogicProject (Northwind) sample for full syntax.

Rule Summary Example Notes
Constraint Boolean function must be True
else transaction rolled back
row.Balance <= row.CreditLimit

row.Salary >= Decimal('1.20') * old_row.Salary
Multi-field
old_row
Formula Function computes column value row.UnitPrice * row.Quantity

row.OrderHeader.ShippedDate
lambda, or function
Parent (OrderHeader) references
Sum Derive parent-attribute as sum of designated child attribute; optional child qualification Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal,where=lambda row: row.ShippedDate is None) Parent attribute can be hybrid (virtual)
scalable: pruning, adjustment
Count Derive parent-attribute as count of child rows; optional child qualification Rule.count(derive=Order.OrderDetailCount, as_count_of=OrderDetail) counts are useful as child existence checks
Copy Child value set from Parent OrderDetail.ProductPrice = copy(Product.Price) Unlike formula references, parent changes are not propagated
e.g, Order totals for Monday are not affected by a Tuesday price increase
Event Python Function on insert, call congratulate_sales_rep See Extensibility for a information on early, row and commit events
Parent Check Ensure Parent row exists Orders must have a Customer See Referential Integrity
Allocation Allocate a provider amount to recipients allocate a payment to outstanding orders See Allocation for an example
Copy Row Create child row by copying parent audit Employee Salary changes to EmployeeAudit See Rule Extensibility

 

Declaring Rules

The table below illustrates that:

  • You can declare rules in Natural Language using WebGenAI and/or Python.
  • Rules are stored in your project depending on how they were defined


Rules Declared In Rules are stored in
WebGenAI, using Natural Language * logic/wg_rules - see WebGenAI Rules and IDE Rules
Your IDE, using Python (as a DSL) * logic/declare_logic.py
* logic/logic_discovery - see here

 

GenAI: Natural Language Logic

You can use Natural Language to create logic during project creation, or for existing projects. For example: The Customer's balance is the sum of the Order amount_total where date_shipped is null.

Think of Natural Language Logic as a translation process down onto underlying rules -- not a code generator.

It is important to learn the rules described here, and to verify proper translation of Natural Language Logic.

 

IDE: With Code Completion

You can also use your IDE with Code Completion to add rules, and their arguments.

Add Rules Code Completion

 

IDE: Natural Language

You can use Natural Language in your IDE. See IDE: Natural Language.  

Iterative Rules

Logic definition is an incremental process. You can start with a few rules, and add more as needed. There is no need to define all rules at once, or rebuild the project.

Note rules are automatically ordered and invoked, so you can add new ones in any location.

Similarly, you can change rules without worrying about the order of execution.

 

Learning Rules

Inside the larger process above, here is the best way to learn how to use rules:

  1. Rule Summary: review the Rule Types table above; there are a small number of rules, since their power lies in chaining

    • Alert: Logic consists of rules and Python. You will quickly learn to use logic events; focus on the rules as the preferred approach, using Python (events, etc) as a fallback.
  2. Review the Rule Patterns, below

  3. Use the case study approach to learn about using rules, by exploring the examples in the report, below.

  4. Be aware of Rule Extensibility.

Pre-req: before learning rules, use the Tutorial to familiarize yourself with basic capabilities and procedures.

  

Rule Patterns

Rules support chaining: a rule may change a value that triggers other rules, including across tables. Mastering such multi-table logic is the key to using rules effectively. The most typical examples are described below.

Pattern Notes Example
Chain Up parent sums and counts mean that child row changes can adjust parents Derive Balance
Constrain a Derived Result constraints may require derived values Balance < creditLimit
Chain Down child copy and parent references mean that parent row changes can cascade to children Ship Order
State Transition Logic old_row useful comparing old/current values Meaningful Raise
Counts as Existence Checks Use counts to check if any children exist Don't Ship Empty Orders
Auditing Note the Copy Row rule (and alternatives) Salary Audit
Ready Flag Multi-session editing, then , when ready...
adjust related data / enforce constraints
Make Order Ready
Events for Lib Access Events enable Python, use of standard libs (e.g., Kafka) Ship Order

 

Rules Case Study

The best way to learn the rules is by a Case Study approach:

  1. Print this page, for reference

  2. Print the Database Diagram

    • Most of the examples are drawn from this database
  3. For each Rule Pattern, above:

    • Click the Example link in the table above to open the Behave Logic Report

      • Aside: later, you can prepare such documentation for your own projects, (like this).
    • Review the Scenario -- take these as your requirements

    • Spend 5 minutes (perhaps in pairs) and cocktail-napkin design your solution, using

      • The data model diagram
      • List of Rule Types, and
      • Rule Patterns
    • Reveal the solution: open the disclosure box: "Tests - and their logic - are transparent.. click to see Logic"

 

Learning Natural Language

As noted above, it is important to be clear on the rules generated for logic. Use the examples below to test your understanding.

WebGenAI provides the Logic Editor so you can see/edit the translation:

logic Editor

Natural Language Patterns

Pattern Notes Example
Formal vs Informal You can: Customer.balance = Sum(Order.amount_total where date_shipped is null) Or, more simply: The Customer's balance is the sum of the Order amount_total where date_shipped is null
Integration Logic Kafka Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None
Multi-rule Logic See Multi-rule Logic - Generated Rules, below Sum of employee salaries cannot exceed department budget
Conditional Derivations See Conditional Derivation - Generated Rules, below Provide a 10% discount when buying more than 10 carbon neutral products
The Item carbon neutral is copied from the Product carbon neutral
Cardinality Patterns
- Qualified Any
See Cardinality Patterns - Generated Rules, below Products have Notices, with severity 0-5.
Raise and error if product is orderable == True and there are any severity 5 Notices, or more than 3 Notices.
Multi-rule Logic - Generated Rules
Logic Recognizes "conditional derivations"
# Aggregate the total salaries of employees for each department.
Rule.sum(derive=Department.total_salaries, as_sum_of=Employee.salary)

# Ensure the sum of employee salaries does not exceed the department budget
Rule.constraint(validate=Department, as_condition=lambda row: row.total_salaries <= row.budget, error_msg="xxx")
# End Logic from GenAI

 

Conditional Derivation - Generated Rules
Logic Recognizes "conditional derivations"
# Provide a 10% discount when buying more than 10 carbon neutral products.
Rule.formula(derive=Item.amount,
             as_expression=lambda row: 0.9 * row.unit_price * row.quantity \
                if row.Product.is_carbon_neutral and row.quantity > 10
                else row.unit_price * row.quantity)
# End Logic from GenAI

 

Cardinality Patterns - Generated Rules
Logic Recognizes "qualified any"
    # Logic from GenAI: (or, use your IDE w/ code completion)

    # Derive product notice count from related notices.
    Rule.count(derive=Product.notice_count, as_count_of=Notice)

    # Derive count of severity 5 notices for products.
    Rule.count(derive=Product.class_5_notice_count, as_count_of=Notice, where=lambda row: row.severity == 5)

    # Ensure product is not orderable if conditions on notices are met.
    Rule.constraint(validate=Product,
    as_condition=lambda row: not (row.orderable and (row.class_5_notice_count > 0 or row.notice_count > 3)),
    error_msg="Orderable product contains severity 5 or excessive notices.")

    # End Logic from GenAI

 

Natural Language Examples

WebGenAI was trained to understand the Natural Language Logic problems shown below. These automate many of the rule patters described above.

Please see Natural Language Logic.

Example Notes
Airport - at least 10 tables
A flight's passengers must be less than its Airplane's seating capacity
System for Departments and Employees.
Sum of employee salaries cannot exceed department budget
Create a system with Employees and their Skills.
More than One Employee can have the same Skill.
EmployeeSkill.rating = Skill.rating
An Employee's skill-rating is the sum of the Employee Skills rating, plus 2 * years of service.
Students have probations and sick days.
Signal an error if a Student's can-graduate is True, and there are more 2 probations, or more than 100 sick days.
Applicant have felonies and bankruptcies.
Signal error if is-hirable is true and there are more than 3 bankruptcies, or 2 felonies.
Students have Grades and belong to Clubs.
Copy the name from Club to Student Club
The student's service activity is the count of Student Clubs where name contains 'service'.
Signal error if student is eligible for the honor society == True, and their grade point average is under 3.5, or they have less than 2 service activities
Products have Notices, with severity 0-5.
Raise and error if product is orderable == True and there are any severity 5 Notices, or more than 3 Notices.
Create a system with customers, orders, items and products.
Include a notes field for orders.

Use Case: enforce the Check Credit for ready orders:
1. Customer.balance <= credit_limit
2. Customer.balance = Sum(Order.amount_total where date_shipped is null and ready is True)
3. Order.amount_total = Sum(Item.amount)
4. Item.amount = quantity * unit_price
5. Store the Item.unit_price as a copy from Product.unit_price

Use Case: Compute Products ordered
1. Item.ready = Order.ready
2. Product.total_ordered = sum(Item.quantity) where ready == True
3. Product.reorder_required = quantity_on_hand <= total_ordered

Use Case: No Empty Orders
1. Order.item_count = Count(Items)
2. When setting the date_shipped, item_count must be > 0.
Ready Flag
Teachers, courses which have offerings, and students who have offerings.

Use Case: capacity
teachers cannot be assigned to more than 5 courses
students cannot have more enrollments than 6

Use Case: budget control
courses have a charge, which is copied to enrollments charge
a student's total enrollment charges cannot exceed their budget