Core Concepts

4.1 The Rule Engine Architecture

QUALIA Rule Engine implements a hierarchical architecture with four key layers: Business Rule Sets (containers), Scenarios (pre-conditions), Conditions (business rules), and Linked Tables (relationships). Understanding this structure is fundamental to creating effective business rules.

The Four-Layer Architecture:


Rule Execution Flow:

  1. Database Operation → User creates/modifies/deletes record

  2. Trigger Interception → GlobalTriggerManagement intercepts operation

  3. Rule Set Identification → Find rule sets for user's Rule Groups + trigger table

  4. Scenario Evaluation → If ANY scenario filter does NOT match, skip to next rule set

  5. Condition Evaluation → Each condition executes independently

  6. Action Execution → Actions execute when condition = TRUE

  7. Transaction Control → Error actions roll back; otherwise commit

💡 BC Consultant Tip: The architecture provides natural performance optimization. Scenarios filter out 90% of non-applicable records before expensive condition evaluation. Use this wisely—add status checks as scenarios, not conditions.

4.2 Validation Sets Explained

A Business Rule Set (also called a Validation Set) is a container that groups related business rules targeting the same trigger table.

You should create separate Business Rule Sets when your rules have different characteristics in any of the following areas:

  • Different trigger tables (for example, Customer validation versus Sales Order validation require separate rule sets)

  • Different business domains (for example, Credit Control rules versus Pricing validation rules should be organized separately)

  • Different activation schedules (for example, year-round rules versus seasonal rules should be kept separate for easier management)

  • Different user groups (for example, rules that apply only to the Sales Team versus rules that apply to all users)

You should keep rules together in the same Business Rule Set when they share the same trigger table, business purpose, activation timing, and user applicability.

Configuration Properties:

Each Business Rule Set has several configuration properties that control its behavior and define its purpose. Understanding these properties is essential for creating well-organized and maintainable business rules.

Code (Text field, 20 characters maximum): This field contains the unique identifier for your Business Rule Set. You should use a consistent naming convention that makes the purpose of the rule set immediately clear. The recommended format is AREA-PURPOSE, where AREA represents the functional area (such as SALES, PURCH, INV, FIN) and PURPOSE describes what the rules do. For example, SALES-CREDIT for sales credit limit rules, INV-QTYCHECK for inventory quantity validation, or CUST-REQFIELDS for customer required fields validation.

Name (Text field, 100 characters maximum): This field contains the display name that appears in list views and provides a more readable description than the Code field. While the Code field uses abbreviations and compact formatting, the Name field can use full words and longer descriptions. For example, the name might be Sales Order Credit Limit Validation for a rule set with the code SALES-CREDIT.

Description (Text field, 250 characters maximum): This field contains a detailed explanation of the purpose and scope of the Business Rule Set. You should use this field to document the business policy being enforced, reference any policy documents or requirements, and provide context that helps other administrators understand why the rule set exists and what it is intended to accomplish.

Enable (Boolean checkbox): This field serves as the master activation switch for the entire Business Rule Set. When the checkbox is selected (✓), all rules in the set are active and will execute when triggered. When the checkbox is cleared (☐), all rules in the set are dormant and will not execute regardless of other configuration settings. You should use this field when developing and testing new rule sets, or when you need to temporarily suspend rules without deleting them.

Trigger Table (Integer field): This field specifies which Business Central table will activate the rules in this Business Rule Set. Common trigger tables include Customer (table 18), Sales Header (table 36), Sales Line (table 37), and Item (table 27). After you create Scenarios or Conditions, you cannot change the Trigger Table because doing so would invalidate the formulas that reference fields from the original trigger table.

Trigger Field (Text field with placeholder notation): This field specifies which field changes will activate the rule execution. You can use three different patterns:

  • Specific field trigger: [37:15] triggers only when the Quantity field changes, which provides the best performance

  • Any field trigger: [37:0] triggers when any field in the record changes (FieldID 0 represents any field)

  • Multiple field trigger: [37:15,22,27] triggers when Quantity OR Unit Price OR Discount Percentage changes

💡 BC Consultant Tip: Use specific field triggers ([TableID:FieldID]) for better performance. Credit limit validation only needs [36:61] (Amount), not [36:0] (any field). This reduces unnecessary executions.

4.3 Understanding Trigger Types in Detail

Trigger Types determine which database operations activate rules and when they execute relative to the transaction commit.

Before Insert (Trigger Insert - ID: 1)

Execution Timing: This trigger type executes after the user has entered data for a new record but before the record is saved to the database.

Data Available at Execution: When a Before Insert trigger executes, only the No./Code field and system-generated default values are available in the record. User-entered fields such as Description, Type, and Category have not yet been populated because users typically fill in these fields after the initial record creation.

Appropriate Use Cases: You should use Before Insert triggers in the following situations:

  • When you need to validate fields that are populated immediately during record creation (for example, Sales Line Quantity is typically entered as part of the initial line creation)

  • When you need to set auto-calculated default values that depend on the primary key or other immediately available data

  • When you need to perform simple field-level validation that does not depend on fields that users fill in after record creation

Common Mistake to Avoid: A frequent error is attempting to validate required fields using Before Insert triggers. This approach fails because master data fields are not filled in until after the record is initially inserted. For example, if you try to validate that an Item Description is required on Before Insert, the validation will always fail because the Description field is empty at that point. The correct solution is to validate required fields using Before Modify triggers that check for status transitions (such as when the Blocked field changes or when the Status field indicates the record is being released for use).

Before Modify (Trigger Modify - ID: 2)

Execution Timing: This trigger type executes after the user has changed data in an existing record but before the changes are saved to the database.

Data Available at Execution: When a Before Modify trigger executes, all previously entered fields are available, and you have access to both the old values (using {TableID:FieldID} placeholder notation) and the new values (using [TableID:FieldID] placeholder notation). This dual access allows you to detect what specific changes were made.

Appropriate Use Cases: You should use Before Modify triggers in the following situations:

  • When you need to validate status transitions (for example, validating data completeness when an order changes from Open status to Released status)

  • When you need to validate required fields (for example, checking that all mandatory fields are populated when a record is being unblocked or activated)

  • When you need to perform cross-field validation that depends on multiple fields having values

  • When you need to enforce credit limits or other business policies that require access to related data

  • When you need to detect specific types of changes by comparing old values with new values

Most Common Trigger Type: Approximately 90% of all business rules use Before Modify triggers because this is when data validation is most effective—all field values are available, and you can still prevent invalid changes from being saved.

Before Delete (Trigger Delete - ID: 3)

Execution Timing: This trigger type executes when a user attempts to delete a record but before the record is actually removed from the database.

Appropriate Use Cases: You should use Before Delete triggers in the following situations:

  • When you need to perform dependency checks (for example, preventing the deletion of a Customer record if the customer has open sales orders)

  • When you need to validate that the current user has permission to delete specific types of records

  • When you need to enforce audit requirements that prevent the deletion of records after certain dates or in certain circumstances

⚠️ After Triggers Are NOT Used: QUALIA Rule Engine implements only Before triggers (1, 2, 3) because After triggers (11, 21, 31) execute after transaction commit when you can't prevent the operation. All action types (Error, Notification, Email) work on Before triggers.

Typical Trigger Combinations:

Business Rule

Insert

Modify

Delete

Rationale

Quantity > 0


Validate creation + changes

Required fields



Fields filled after creation

Credit limit


Check orders creation + modification

Status transitions



Only relevant when changing status

Deletion restrictions



Only relevant when deleting

💡 BC Consultant Tip: For master data (Item, Customer, Vendor), use Modify trigger with status-based scenarios. Validate required fields when Blocked field changes from true to false—this is when users have completed data entry and are activating the record.

4.4 Validation Formulas: The Heart of Business Rules

Formulas define the logic that determines when scenarios and conditions evaluate to true. QUALIA Rule Engine uses Business Central's native filter syntax.

CRITICAL: Use is for Equality

⚠️ There is NO = operator. Use the keyword is between field and value:

✅ CORRECT: [18:35] is 'US'
❌ WRONG:   [18:35] = 'US'
❌ WRONG:   [18:35]

Filter Operators:

Operator

Syntax

Example

Meaning

Equals

is value

[18:35] is 'US'

Country = US

Not equal

is <>value

[27:4] is <>'Inventory'

Type ≠ Inventory

Greater

is >value

[36:61] is >10000

Amount > 10,000

Less

is <value

[37:15] is <0

Quantity < 0

Greater/equal

is >=value

[18:20] is >=5000

Credit Limit ≥ 5,000

Less/equal

is <=value

[37:27] is <=10

Discount % ≤ 10%

Range

is low..high

[36:61] is 1000..5000

1,000 ≤ Amount ≤ 5,000

Multiple values

is 'A'|'B'

[27:4] is 'Inventory'|'Service'

Type = Inventory OR Service

Placeholder Formats:

Current Value: [TableID:FieldID]

  • Example: [37:15] = Sales Line Quantity (current value)

Old Value (Modify triggers only): {TableID:FieldID}

  • Example: {37:15} = Sales Line Quantity (before modification)

  • Compare: [37:15] is >{37:15} (new > old - quantity increased)

System Placeholders: QUALIA Rule Engine provides several special placeholders that provide access to system-level values that are not stored in specific table fields:

  • [USERID] returns the user ID of the current user who is executing the operation

  • [TODAY] returns the current system date

  • [W] returns the work date that is currently set in Business Central (which may differ from the actual calendar date)

  • [CDT] returns the current date and time as a DateTime value

Aggregate Placeholders: When you use Linked Tables to establish relationships with other tables, you can use aggregate placeholders to calculate values across filtered sets of related records:

  • MIN[TableID:FieldID] returns the minimum value of the specified field across all filtered records

  • MAX[TableID:FieldID] returns the maximum value of the specified field across all filtered records

  • FIR[TableID:FieldID] returns the first value of the specified field based on the table's primary key sorting

  • LAS[TableID:FieldID] returns the last value of the specified field based on the table's primary key sorting

  • SUM[TableID:FieldID] returns the sum of all values of the specified field across all filtered records

Combining Tests: Multiple Scenarios vs Multiple Conditions

NO AND/OR Operators: QUALIA Rule Engine doesn't support AND/OR keywords.

For AND Logic → Use Multiple Scenarios:

Scenario 1: [36:61] is >5000
Scenario 2: [18:35]

ALL scenario filters must MATCH (implicit AND logic - each filter requirement must be met).

For OR Logic → Use Multiple Conditions:

Condition 1: [36:61] is >5000
  └─ Action: Send notification
  
Condition 2: [18:39]

Each condition executes independently (implicit OR).

4.4 Understanding the Counter-Intuitive Scenario Logic (Critical Concept)

Scenarios cause confusion because the underlying CheckConditions function uses inverted boolean return logic. Understanding this prevents configuration errors.

The Code Behind Scenarios

From Cod72777800.QUACheckValidations.al:

// CheckConditions function evaluates scenario filters
// Returns FALSE when filters match (counter-intuitive!)
// Returns TRUE when filters don't match

// ApplyRules procedure uses this:
if CheckConditions(...) then
    TobeValidated := false;  // TRUE result = STOP processing
else
    TobeValidated := true;   // FALSE result = CONTINUE processing

Why This Design?

The inverted logic exists for performance optimization:

  • FALSE return = "conditions met, continue" = fast path (no branching needed)

  • TRUE return = "conditions not met, stop" = exit immediately

Mental Model for Correct Configuration

WRONG Mental Model (causes errors):

"Scenarios must evaluate to TRUE to continue processing"

This thinking causes users to write scenarios backwards.

CORRECT Mental Model:

"Write filters that MATCH the records I want to process. When filters match, the scenario 'passes' and processing continues."

Practical Examples - Correct vs Incorrect

Requirement: Validate credit limit for Open sales orders only

WRONG Configuration (from incorrect mental model):

Scenario: [36:120]

CORRECT Configuration:

Scenario: [36:120]

The Truth Table

Scenario Filter

Record Value

Filter Matches?

CheckConditions Returns

Processing

is '0'

Status = 0 (Open)

YES

FALSE

CONTINUES ✓

is '0'

Status = 1 (Released)

NO

TRUE

STOPS

is <>'0'

Status = 0 (Open)

NO

TRUE

STOPS

is <>'0'

Status = 1 (Released)

YES

FALSE

CONTINUES ✓

Key Insight: The "Filter Matches?" column tells you what will be processed. Focus on that, not the TRUE/FALSE values.

Best Practice: Test Your Scenarios

When configuring scenarios, always test with sample data:

  1. Identify a record you WANT to process (e.g., Open order)

  2. Check if your scenario filter would MATCH that record

  3. If yes, configuration is correct

  4. If no, invert your filter

Example Test:

  • Want to process: Open orders (Status=0)

  • Scenario: [36:120] is '0'

  • Test: Does filter is '0' match Status=0? YES ✓

  • Conclusion: Configuration correct

Example Test:

  • Want to process: Open orders (Status=0)

  • Scenario: [36:120] is <>'0'

  • Test: Does filter is <>'0' match Status=0? NO ✗

  • Conclusion: Configuration WRONG - will process Released orders instead

Common Mistake Patterns

Mistake 1: Double Negative Logic

❌ Wrong: Scenario: [36:120] is <>'0'  (thinking "not Released")
✓ Right: Scenario: [36:120]

Mistake 2: Exclusion Thinking


Mistake 3: Boolean Thinking


Text Patterns with Wildcards:

Pattern

Example

Matches

Contains

[18:2] is '*Ltd*'

"ABC Ltd", "Ltd Company", "Holding Ltd"

Starts with

[18:1] is 'CUST*'

"CUST001", "CUST-ABC"

Ends with

[18:2] is '*Inc.'

"Company Inc.", "Holdings Inc."

Case-insensitive

[18:2] is '@*ltd*'

"Ltd", "LTD", "ltd"

Single character

[18:1] is 'C???001'

"CUST001", "COMP001"

Calculated Expressions:

Wrap calculations in curly braces {}:

Condition 1: {[37:15] * [37:22]

Calculates Quantity × Unit Price, compares to 1,000.

With comparison in filter string:

Condition 1: [36:61] is >{[18:20] - [18:59]

Compares Amount to (Credit Limit - Balance).

💡 BC Consultant Tip: Start simple. Test each placeholder individually before combining. Use the field lookup (F6) to insert placeholders—this prevents typos and ensures correct table/field IDs.

4.5 Actions: What Happens When Rules Fire

Actions define what happens when conditions evaluate to TRUE. Each condition can have multiple actions that execute sequentially.

11 Action Types (Enum values 0-10):

  1. Empty/None (0): Placeholder, no action

  2. Error Message (1): Blocks transaction, displays error

  3. Message (2): Non-blocking informational popup

  4. Confirmation (3): Yes/No dialog with conditional actions

  5. Notification (4): Non-blocking banner notification

  6. Send Email (5): Automated email to recipients

  7. Assign (6): Automatically populate field values

  8. URL (7): Open web page/application

  9. Custom Action (8): Execute custom codeunit

  10. Power Automate Flows (9): Trigger Power Automate

  11. Insert (10): Create new record automatically

Most Common Actions:

Error Message (Use: Prevent invalid data)

  • Blocks transaction (rollback)

  • User cannot proceed until issue resolved

  • Example: "Order exceeds credit limit"

Send Email (Use: Notify stakeholders)

  • Non-blocking (transaction proceeds)

  • Example: "Notify manager of high discount"

Notification (Use: Alert without blocking)

  • Banner at top of page

  • User can continue working

  • Example: "Customer on credit hold"

Assign (Use: Auto-populate fields)

  • Set field values automatically

  • Example: "Set priority = High when amount > 10,000"

Action Execution Order:

Actions execute in the order defined. For a condition with multiple actions:

Condition 1: [36:61]

All three actions execute sequentially when condition is TRUE.

⚠️ Error Actions Stop Execution:

If an Error action executes, the transaction rolls back immediately. Subsequent actions in the same condition do NOT execute, and no other conditions evaluate.

💡 BC Consultant Tip: Put Error actions LAST if you want other actions (Email, Assign) to execute first. However, remember that Error actions roll back the transaction—Assign actions will be reverted. Use Email/Notification before Error to preserve communication even when transaction fails.

4.6 Linked Tables: Accessing Related Data

Linked Tables (Source References) define relationships between your trigger table and other tables, enabling formulas to access data beyond the trigger table.

Why Linked Tables Are Needed:

Your Business Rule Set triggers on one table (e.g., Sales Header), but you need data from related tables (e.g., Customer credit limit). Linked Tables establish the relationship.

Configuration:

Reference Table No.: The table you want to access (e.g., 18 = Customer)

Reference Filters: Define the join condition

  • Reference Field No.: Field in reference table (e.g., 1 = Customer."No.")

  • Filter Type: Field (join to trigger table field)

  • Filter Value: Field in trigger table (e.g., 2 = Sales Header."Sell-to Customer No.")

Example: Sales Header → Customer


This establishes: Customer."No." = Sales Header."Sell-to Customer No."

Using Linked Table in Formula:

After configuring the linked table, reference Customer fields:

Condition 1: [36:61] is >[18:20]

Compares Sales Header Amount [36:61] to Customer Credit Limit [18:20].

QUALIA Rule Engine automatically follows the relationship to retrieve the correct Customer record.

Multiple Linked Tables:

You can define multiple linked tables to access several related tables:


Now formulas can reference Sales Header, Item, and Customer fields.

Chained Relationships:

You can chain relationships through intermediate tables:

  1. Link Sales Line to Sales Header

  2. Link Sales Header to Customer

  3. Access Customer fields from Sales Line rules

Performance Considerations:

Each linked table requires database lookups at runtime. For optimal performance:

  • Define only the linked tables you actually use

  • Use Scenarios to filter out records early before expensive lookups

  • Test rule execution time with real-world data volumes

💡 BC Consultant Tip: Configure linked tables using the field lookup tool (F6) to ensure correct field IDs. After setup, test thoroughly—incorrect join conditions can cause rules to retrieve wrong data or fail silently.

4.7 The Rule Execution Lifecycle

Understanding the complete execution lifecycle helps you design efficient rules and troubleshoot issues.

Complete Execution Flow:


Scenario Short-Circuit Optimization:


Condition Independence:


Conditions 2 and 3 execute regardless of Condition 1 result.

Error Action Impact:


💡 BC Consultant Tip: Design rules to fail fast. Put the most restrictive validations (Error actions) in early conditions. If they trigger, remaining conditions don't execute—saving processing time and providing immediate, clear feedback to users.

4.8 Best Practices for Rule Design

1. Use Scenarios for Filtering, Conditions for Business Logic

Good:

Scenario 1: [36:120] is '0'  (Status = Open)
Scenario 2: [18:39] is ''    (Customer not blocked)

Condition 1: [36:61] is >[18:20]

Bad:

Condition 1: [36:120] is '0'  (Status as condition)
  └─ No action attached
  
Condition 2: [18:39] is ''  (Blocked status as condition)
  └─ No action attached
  
Condition 3: [36:61] is >[18:20]

Why: Scenarios short-circuit—filtering 95% of records before condition evaluation. Using conditions for filtering wastes processing time.

2. Optimize Trigger Fields for Performance

Good:

Business Rule: Credit Limit Validation
Trigger Field: [36:61]

Bad:

Business Rule: Credit Limit Validation
Trigger Field: [36:0]

Why: Specific field triggers execute only when that field changes. Any field triggers execute on every field change (Customer Name, Order Date, etc.)—wasting processing for non-amount changes.

3. Use Meaningful Naming Conventions

Good:


Bad:


Why: Descriptive names make rules easy to find, understand, and maintain. Include policy references for compliance tracking.

4. Test in Sandbox Before Production

Process:

  1. Create rule in sandbox environment

  2. Test with real-world scenarios

  3. Verify Validation Log entries

  4. Document test results

  5. Export from sandbox, import to production

  6. Test again in production with limited users

  7. Activate for all users

Anti-pattern:

  • Create rules directly in production

  • "It should work" → Enable for all users

  • Users encounter unexpected errors

  • Emergency hotfix required

5. Document Business Policies in Descriptions

Good:

Bad:

Why: Months later, when someone asks "Why do we have this rule?", the description provides the answer without requiring tribal knowledge.

6. Use Rule Groups Strategically

Good:


Bad:


Why: ALL group rules execute for every user, including admins doing data cleanup. Department-specific rules should target only affected users.

7. Monitor the Validation Log Regularly

Practice:

  • Weekly review of Validation Log

  • Filter by "Errors" to identify problematic rules

  • Analyze execution frequency

  • Identify rules that never trigger (might be obsolete)

Anti-pattern:

  • Set rules and forget

  • No monitoring

  • Users complain about "weird errors"

  • No data to diagnose issues

8. Keep Formulas Simple and Readable

Good:

Condition 1: [37:15]

Bad:

Condition 1: {([37:15] * [37:22]) - ([37:27] * 0.01 * [37:22] * [37:15]

Why: Simple formulas are easier to understand, test, and maintain. Complex calculations should be documented or broken into multiple conditions.

9. Use Error Actions Sparingly

Good:

  • Error: Prevent negative quantities (data integrity)

  • Error: Prevent orders exceeding credit limit (business policy)

  • Notification: Warn about unusual discount (advisory)

Bad:

  • Error: Customer name contains "Ltd" (informational)

  • Error: Order date is today (trivial)

  • Error: Salesperson not assigned (not critical)

Why: Error actions block users and roll back transactions. Use them for true validation failures, not advisories.

10. Version Control Your Rules

Practice:

  • Export rule configuration to JSON/XML

  • Store in version control system

  • Document changes in commit messages

  • Maintain development → test → production pipeline

Anti-pattern:

  • Modify rules directly in production

  • No backups

  • "What did we change last week?" → Unknown

  • Can't roll back to previous configuration

💡 BC Consultant Recommendations:

  1. Start Simple: Create one rule set with one condition before building complex multi-rule systems

  2. Test Incrementally: Test each condition individually before combining

  3. Document Everything: Future you (and your colleagues) will thank you

  4. Monitor Actively: Rules are not "set and forget"—they require ongoing maintenance

  5. Plan for Scale: Design naming conventions and organization structure that scale to hundreds of rules

Get Your FREE Dynamics 365 Demo

Transform your business operations with Microsoft Dynamics 365 Business Central

Experience the transformative power of Microsoft Dynamics 365 Business Central for yourself! Request a free demo today and see how our solutions can streamline your operations and drive growth for your business.

Our team will guide you through a personalized demonstration tailored to your specific needs. This draft provides a structured approach to presenting Qualia Tech's offerings related to Microsoft Dynamics 365 Business Central while ensuring that potential customers understand the value proposition clearly.

Areas Of Interest

Please read and confirm the following:

*Note: Fields marked with * are mandatory for processing your request.

*Note: Fields marked with * are mandatory for processing your request.

© 2024 Qualia. All rights reserved

QUALIA Technik GmbH

info@qualiatechnik.de

17, Heinrich-Erpenbach-Str. 50999 Köln

© 2024 Qualia. All rights reserved

QUALIA Technik GmbH

info@qualiatechnik.de

17, Heinrich-Erpenbach-Str. 50999 Köln

© 2024 Qualia. All rights reserved

QUALIA Technik GmbH

info@qualiatechnik.de

17, Heinrich-Erpenbach-Str. 50999 Köln

© 2024 Qualia. All rights reserved

QUALIA Technik GmbH

info@qualiatechnik.de

17, Heinrich-Erpenbach-Str. 50999 Köln