> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alforse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pricing rules and overrides

> How Alforse resolves the price on a line, from base price through overrides and rules.

Alforse resolves the unit price for each quote or sales order line. It starts with a base price, selects an applicable price override, applies matching pricing rules, and stores a trace of the calculation on the line. Overrides define negotiated prices and quantity breaks; rules define company-wide discounts and markups.

## Pricing rules

A **pricing rule** is a company-scoped rule that adjusts a price up or down. Each rule is a `Discount` or a `Markup`, expressed as either a `Percentage` or a `Fixed` amount, or a `Configuration` rule that prices a configured part's options (below). A rule only fires when the line matches its conditions.

FieldType

<details>
  <summary>**Name**required`text`</summary>

  A label for the rule.
</details>

<details>
  <summary>**Rule type**required`enum`</summary>

  `Discount` (lowers the price), `Markup` (raises it), or `Configuration` (prices a configured part's options).
</details>

<details>
  <summary>**Amount type**required`enum`</summary>

  `Percentage` or `Fixed`. A percentage is stored as a fraction from 0 to 1 (10% is `0.10`), so the form caps it at 100%.
</details>

<details>
  <summary>**Amount**required`number`</summary>

  The discount/markup value. For a percentage, the fraction of the running price; for fixed, an absolute amount.
</details>

<details>
  <summary>**Priority**`number`</summary>

  Higher priority wins among discounts and orders the markup stack. Defaults to `0`.
</details>

<details>
  <summary>**Min / max quantity**`number`</summary>

  The line quantity range the rule applies to.
</details>

<details>
  <summary>**Customers / customer types**`list`</summary>

  Restrict the rule to specific customers or customer types. Empty means all.
</details>

<details>
  <summary>**Items / item posting group**`list`</summary>

  Restrict to specific items or an item posting group. Empty means all.
</details>

<details>
  <summary>**Valid from / valid to**`date`</summary>

  The date window the rule is active in. Empty bounds are open-ended.
</details>

<details>
  <summary>**Active**`boolean`</summary>

  Inactive rules are skipped without being deleted, preserving them for audit.
</details>

A rule matches a line only when every set condition holds: the quantity is within `min`/`max`, the date is inside the valid window, and the item and customer fall inside the item/customer restrictions (empty restriction means no restriction). Only matching, active rules go into the calculation.

NOTE

**Percentages are fractions, not whole numbers**

A `Percentage` amount is a fraction between 0 and 1 (`0.10` for 10%). The rule form rejects anything above 1. If you enter 15 expecting 15%, that's a 1500% adjustment.

### Configuration rules

A `Configuration` rule has no amount or item scope of its own. Instead you pick one **configured part** (only parts that require configuration are listed), and the form shows a **Configuration Prices** section listing that part's configuration parameters. Each amount is a per-unit surcharge added to the line's unit price when the line's configuration matches:

* **List** parameters take an amount per option (`Color = Red → 10`).
* **Boolean** parameters take an amount for when the value is true.
* **Numeric** parameters take an amount per unit of the value (`0.50 × Length`).

Text, date and material parameters can't be priced. Amounts are signed, so a negative amount gives a credit. The surcharges from every matching Configuration rule stack. They are added before the discount and markup rules, so a discount also applies to the surcharges. Each one appears in the price trace as a `Configuration` step labelled with the parameter's name. The customer scope, dates, quantity range and priority work as on any other rule. A price override that doesn't apply rules on top still takes the configuration prices, because they price the chosen options rather than the part.

Configuration prices apply wherever the line has a configuration: quote lines, which reprice when a line is configured or reconfigured, and sales order lines, which have their own **Configure** button.

## Price overrides

A **price override** pins a negotiated price for a specific item, optionally with quantity breaks. Unlike a rule, an override replaces the base price outright rather than adjusting it. Overrides are scoped one of three ways, and a single override targets exactly one scope:

* **Customer** — this item, this customer.
* **Customer type** — this item, everyone of this customer type.
* **All customers** — this item, every customer (both customer and customer type left blank).

An override can't set both a customer and a customer type; the database enforces the exclusive scope. Each override carries a list of **quantity breaks** — rungs of `quantity` → `override price`. For a given line quantity Alforse picks the highest break whose quantity is at or below the ordered quantity. Order eight when the rungs are 1, 5, and 10, and you get the price on the 5-rung.

FieldType

<details>
  <summary>**Item**required`reference`</summary>

  The item this override prices.
</details>

<details>
  <summary>**Customer**`reference`</summary>

  Scope to one customer. Mutually exclusive with customer type.
</details>

<details>
  <summary>**Customer type**`reference`</summary>

  Scope to a customer type. Mutually exclusive with customer.
</details>

<details>
  <summary>**Quantity breaks**required`list`</summary>

  One or more `quantity` → `override price` rungs. Duplicate quantities are rejected.
</details>

<details>
  <summary>**Apply rules on top**`boolean`</summary>

  When on (the default), pricing rules still layer onto the override price. When off, the override price is final and rules are skipped.
</details>

<details>
  <summary>**Valid from / valid to**`date`</summary>

  The date window the override is active in.
</details>

<details>
  <summary>**Active**`boolean`</summary>

  Inactive overrides are skipped but retained for history.
</details>

You can seed one customer's or type's price list from another with **Duplicate price list**, choosing a `skip` or `overwrite` strategy for items the target already prices.

NOTE

**An override is a price list, not a discount**

An override sets the starting price directly. Whether rules then adjust it is governed by the override's `Apply rules on top` flag, per override — not a global setting.

## How the engine picks a price

Resolution runs top to bottom. The result, plus every step, is stored on the line as a **price trace**, and the line records which `pricing rule` (if any) drove the final number.

**Start from the base price.** The item's unit sale price, or the cost-rollup price the quote already computed. Trace source: `Base`.

**Apply the best-matching override, if any.** Alforse checks the three scopes in strict precedence and commits to the first that yields a break: **customer override, then customer-type override, then all-customers override.** Once a scope matches, it never falls through to a lower one. If the ordered quantity is below the override's smallest break, that scope doesn't match and Alforse tries the next. The winning override sets the starting price. Trace source: `Override`, `Type Override`, or `All Override`.

**Layer on pricing rules**, unless the winning override set `Apply rules on top` to off. All matching active rules apply here, in the order below. Trace source: `Rule`.

**Clamp and record.** A negative result is floored at zero, and the final price is written to the line along with the full trace.

So the precedence is: **customer override > customer-type override > all-customers override > base price**, and then rules run on top of whichever starting price won.

### What wins when rules collide

Discounts and markups combine differently, and this is the part that surprises people:

* **Discounts don't stack — the single highest-priority discount wins.** When several discount rules match, Alforse ranks them by priority (ties broken by the larger effective amount) and applies **only the top one**. The rest are discarded. You never get two discounts on the same line.
* **Markups stack and compound.** Every matching markup rule applies, in priority order, each computed against the already-adjusted running price. A 10% markup after a 20% markup compounds, it doesn't simply add.

Configuration prices are added first, then the discount, then the markup stack, then the zero floor.

HEADS UP

**Two discounts never combine**

If a customer qualifies for both a 10% and a 15% discount rule, they get 15% only — never 25%, and never both applied in sequence. Markups are the opposite: all of them apply, compounding.

NOTE

**Price resolution is a value, not a lock**

Resolution runs when the item or quantity changes on a line and fills in the unit price. It's a starting point you can still edit by hand; the trace records how the suggested number was reached.

## Where it applies

The same engine prices both surfaces. On a **quote line** it runs during cost rollup and re-price. On a **sales order line** the line form calls the same resolution as you pick an item or change the quantity, filling the unit price and storing the trace. Both line types carry the resolved price and its provenance, so a price traces back to the exact override and rule that produced it.

Alforse has no separate price-list document. A price list is the set of overrides scoped to a customer or customer type. The application resolves prices; the database does not.

## Related

**Quotes**

Where negotiated pricing is first recorded, with quantity breaks per line.

[Open](/docs/reference/quotes.md)

**Sales orders**

The confirmed order whose lines carry the resolved unit price.

[Open](/docs/reference/sales-orders.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.