# Rule Authoring

> A functional description of how an admin builds rules — the conditional logic that decides whether a question or answer is shown/active in the configurator. …

Source: CBX documentation, version 3.x (released). Canonical page: https://docs.configbox.at/docs/functional/rule_authoring. Last updated 2026-08-01.

---
A **functional** description of how an admin builds **rules** — the conditional logic that decides
whether a question or answer is shown/active in the configurator. This is the authoring/usage view:
what you can express and how you build it. For *how* rules are stored and evaluated, see
`technical/com_configbox_rule_engine.md`.

> A rule answers one yes/no question: "given the customer's current selections (and group), does this
> apply?" When it applies, the question/answer is shown (or, with negation, hidden). Rules are what make
> a configurator dynamic — options appear, disappear or grey out as the customer chooses.

The whole decision in one picture:

```mermaid
flowchart TD
    C["Customer's current selections<br>(and customer group)"] --> R{"Do the rule's<br>conditions hold?"}
    R -- "Yes" --> Y["Show-if rule: item is shown<br>Hide-if rule: item is hidden"]
    R -- "No" --> N["Show-if rule: item is hidden or greyed out<br>Hide-if rule: item is shown"]
```

---

## 1. What a rule is attached to

Rules are authored in two places:
- **On a Question** — controls whether the whole question is shown to the customer.
- **On an Answer (Option Assignment)** — controls whether that individual answer/option is available
  within its question.

A question/answer with no rule always shows. Add a rule to make it conditional.

---

## 2. The Rule Editor (authoring UX)

Opened from the question's or answer's form (the "Rule" field → **Change**). It's a visual builder:

1. **Show-if vs Hide-if** — a selector at the top chooses the rule's meaning:
   - *Show … if these conditions are met* (normal), or
   - *Hide … if these conditions are met* (negated).
2. **Drop area** — the rule you're building. You **drag conditions** into it from the condition-type
   tabs below.
3. **Condition-type tabs** — one tab per condition type (below); each lists the available conditions
   to drag in.
4. **Combinators** — drag **AND** / **OR** between conditions to combine them.
5. **Brackets** — select conditions and "make parentheses" to group them (controls precedence, e.g.
   `A AND (B OR C)`).
6. **Operators** — click a condition's operator to pick how it compares (see §4).
7. **Values** — type the value each condition compares against (numbers are locale-aware).
8. **Save** — writes the rule back onto the question/answer.

You can also **copy/paste** a rule between questions/answers, and **delete** it (reverting to
"always show").

> Verified live: the Show/Hide selector reads *"Show the question if these conditions are met:"* /
> *"Hide the question if these conditions are met:"*; combinators are **AND** / **OR**; and the toolbar
> buttons are **Put in parentheses**, **Remove selected**, **Limit condition width**, **Save**,
> **Cancel**. The condition-type tabs are labelled **"Answers to questions"**, **"Customer"**, and
> **"Results of calculations"** (mapping to the three condition types in §3).

---

## 3. Condition types (the building blocks)

### "Answers to questions" (the most common)
Compare something about **another question** to a value. You pick the question and which aspect:
- **Answer in …** — the customer's chosen answer (for choice questions you pick a *specific answer*,
  e.g. "Answer in 'Material' is 'Oak'"); for value questions it's the entered value/selection.
- **Price of …** / **Recurring Price of …** — that question's computed price.
- **Answer custom field in …** / **Global answer custom field in …** — a custom field of the selected
  answer (assignment-level or option-level), under your configured labels.
…then choose an operator and a value.

### "Results of calculations"
Compare a **calculation's result** to a value (e.g. "Result of 'Total weight' is above 50"). This is
how rules react to computed numbers, including anything you built in the calculation editors.

### "Customer"
Compare a **customer-group field** to a value (e.g. show trade-only options when the group's flag is
set). Lets rules depend on *who* the customer is rather than what they selected.

### Custom condition types
A developer can add custom condition types (e.g. "stock level", "external availability"); they appear
as additional tabs with their own conditions. (How to add them: technical rule-engine doc.)

Choosing the right condition type is usually this simple:

```mermaid
flowchart TD
    Q{"What should the<br>rule react to?"}
    Q --> A["Another question's answer,<br>entered value or price"] --> T1["Answers to questions"]
    Q --> B["A computed number<br>(weight, total, dimension)"] --> T2["Results of calculations"]
    Q --> C["Who the customer is<br>(their group)"] --> T3["Customer"]
    Q --> D["Something else<br>(stock, external data)"] --> T4["A custom condition type"]
```

---

## 4. Operators

Each condition compares its subject to your value using one of:
- **is below** (`<`)
- **is or below** (`≤`)
- **is** (`=`)
- **is not** (`≠`)
- **is or above** (`≥`)
- **is above** (`>`)

Numeric subjects compare numerically; text subjects compare as text for *is*/*is not*. (For
choice questions, "Answer … is/is not <a specific answer>" is the typical form.)

---

## 5. Combining conditions: AND / OR and brackets

- **AND** — all combined conditions must hold.
- **OR** — any one suffices.
- **Brackets** group conditions so you can express things like
  `(Material is Oak OR Material is Walnut) AND Finish is Lacquer`.

That example, seen as the condition tree the brackets create:

```mermaid
flowchart TD
    AND(("AND")) --> OR(("OR"))
    AND --> C3["Answer in 'Finish'<br>is 'Lacquer'"]
    OR --> C1["Answer in 'Material'<br>is 'Oak'"]
    OR --> C2["Answer in 'Material'<br>is 'Walnut'"]
```

Build arbitrarily complex logic by nesting brackets and mixing AND/OR.

---

## 6. Show-if vs Hide-if (negation)

The top selector flips the whole rule's meaning:
- **Show-if** — the question/answer appears only when the conditions are met (the default).
- **Hide-if** — the question/answer is hidden when the conditions are met (and shown otherwise).

Pick whichever reads more naturally for the case; they're logically complementary.

---

## 7. What happens when the outcome changes (companion behaviors)

A rule only decides *applies / doesn't apply*. **What the configurator does** when that changes is set
by companion fields on the question/answer — part of authoring conditional behavior:

- **Display while disabled** (question & answer) — when the rule isn't met, **hide** the item or show
  it **greyed-out** (visible but not selectable). Use grey-out to keep the customer aware of options
  they could unlock.
- **Behavior on activation** (question) — what to do when the question *becomes* applicable, e.g.
  auto-select its default/first answer so it's never left empty.
- **Behavior on inconsistency** (question) — what to do when the current answer becomes invalid because
  of other changes, e.g. deselect it, or replace it with the default/any valid answer.
- **Behavior on changes** (question) — whether such automatic changes happen silently or **prompt the
  customer to confirm**.

How the pieces fit together when a rule's outcome flips:

```mermaid
flowchart TD
    E["Rule outcome changes"] --> NA["Item no longer applies"]
    E --> BA["Item becomes applicable"]
    NA --> H["Display while disabled:<br>hide, or grey out"]
    NA --> I["Its selected answer is now invalid:<br>Behavior on inconsistency<br>(deselect / replace with a valid one)"]
    BA --> A["Behavior on activation:<br>e.g. auto-select the default answer"]
    I --> C{"Behavior on changes"}
    A --> C
    C -- "Silent" --> S["Change is applied quietly"]
    C -- "Confirm" --> P["Customer is asked first"]
```

These turn a static condition into smooth live behavior (options cascade, invalid choices self-correct,
the customer is asked before surprising changes).

---

## 8. Worked examples

- **Dependent question:** On the question "Engraving text", Show-if **Answer in "Add engraving" is
  "Yes"**. The text field only appears when engraving is chosen.
- **Segment-gated options:** On a premium answer, Show-if **Customer group field "is_trade" is "1"** —
  only trade customers see it.
- **Either/or grouping:** Show-if **(Answer in "Use" is "Indoor" OR Answer in "Use" is "Covered") AND
  Answer in "Material" is "Steel"**.
- **React to a calculation:** On a "Reinforcement required" answer, Show-if **Result of "Total span" is
  above "4"**.
- **Hide on condition:** On the "Color" question, Hide-if **Answer in "Finish" is "Raw"** (raw finish
  has no color choice).

---

## 9. What the customer experiences (runtime)

As the customer makes selections, CBX re-evaluates all rules **live on every change**:
non-applying questions/answers hide or grey out, newly-applicable questions can auto-select defaults,
and selections that became invalid are corrected (silently or with a confirmation prompt) per the
companion behaviors. The effect is a configurator that continuously reshapes itself to valid, relevant
choices.

The live loop, as the customer sees it:

```mermaid
sequenceDiagram
    participant Customer
    participant CBX as CBX configurator
    Customer->>CBX: Changes a selection
    CBX->>CBX: Re-evaluates all rules in the product
    CBX-->>Customer: Hides / greys out items that no longer apply
    CBX-->>Customer: Shows newly applicable items (auto-selecting defaults)
    CBX-->>Customer: Corrects invalid selections (silently, or after a confirmation prompt)
```

---

## 10. Practical notes & limits

- **A rule yields visibility only.** Anything beyond show/hide/grey-out (auto-select, deselect,
  confirm) comes from the §7 behaviors, not the rule itself.
- **Rules can reference calculations**, so numeric thresholds (weight, total, dimensions) are
  expressible — pair the two editors.
- **Performance:** rules are evaluated on every selection change across the product; very large/deep
  rule sets add cost. Keep conditions focused.
- **Copy/paste** rules to reuse logic across similar questions/answers; product copy re-points rule
  references automatically.

---

## 11. Notes for the refactor (functional observations)

- **Rules express visibility; behaviors express reaction.** These are two coupled concerns the current
  UI splits across the rule editor and several question fields. A refactor could present them together
  as one "conditional behavior" model (condition → effect: show/hide/grey/require/auto-select), which is
  closer to how admins think.
- **The condition vocabulary is small and clear** (answers-to-questions, calculation-results,
  customer-group) and **extensible** with custom types — worth preserving as an open condition set.
- **Show-if/Hide-if is just negation** of the same condition tree; a refactor might offer an explicit
  effect dropdown instead (Show / Hide / Disable / Require…).
- **Rules + calculations are complementary engines** (boolean logic vs numeric); keeping them as two
  composable systems (rules can read calc results) is a good separation to retain.
- **Live cascade + inconsistency resolution** is a genuine UX feature (not just a side effect) — the
  refactor should treat the auto-select/inconsistency/confirm behavior as a first-class part of the
  rules subsystem, with clear, testable semantics.
