Open core: don’t reinvent the wheel — build your fenestration software on ours.

Skip to main content

A matrix is a lookup table the pricing/costing engine consults during order entry:
given two inputs (a width and a height, an option answer and a dealer group, …) it returns a
value — a price, a size adjustment, a commission rate, an error or warning, or a pointer to
another matrix. This screen builds and edits those tables in a spreadsheet-style grid.
Matrices are referenced from series headers (Qty Discount), option choices, designs, and
rules.

A matrix has two parts: a Header (name, matrix type, units, series, and what its
two axes mean) and a cell grid (the value returned for each row/column
combination).

What, where, who, when, why

What The create/edit screen for matrix lookup tables: a Header
(type, units, owning series, row/column axis definitions) and the generated cell grid of
values.
Where Administration → OJ Setup → Product Setup →
Matrix.
Who Pricing staff and the rules owner — matrices are
referenced from series headers (Qty Discount), option choices, designs, and rules.
When Whenever a value varies along two dimensions instead of being
flat: size-based pricing, dealer-group×series discount grids, quantity breaks,
commission tiers. A matrix replaces dozens of per-case rules with one editable
table.
Why it matters The pricing/costing engine consults these tables
live during order entry; nothing else carries size- or group-dependent values. Editing a
cell here reprices the next quote — and a wrong axis definition silently returns
the wrong cell instead of erroring.

Layout

Left rail: a “Filter by name…” box (live filter over id - description),
a Type filter, and the matrix list with a count underneath. Right: the collapsible
Header panel, the Matrix grid panel, and a bottom action bar:
New / Edit / Copy / Save / Cancel / Delete.

The Header panel

  • ID (read-only) and Description.
  • Type — the matrix type; it controls which axis types are allowed.
    Commission-family types (Qty Discount, commissions, Sales Targets) enable the
    Commission cell type.
  • Measure — units for dimensional axes; shown only when an axis is
    dimensional.
  • Series — the owning series; also narrows series-scoped axes (opening class,
    shape, opening) to that series.
  • Row Axis / Column Axis — each has a Type, plus an Option picker
    for option axes or Start / End / Step for numeric/date axes. The column-type
    list is filtered to combinations valid for the chosen matrix type and row
    type.
  • Generate grid — builds the cell grid from the axis definition.

Axis types come in three flavors: enumerated (the rows/columns are an
existing list — option answers, opening class, shape, sealed unit, opening, SU family, grid,
partner/dealer, item type, series, price group), numeric / date (generated from
Start, End, Step), and None (a single wildcard row/column).

The cell grid

The first row and first column are band cells — the boundary each row/column stands
for (lower - upper for numeric axes, the entry’s description for enumerated
axes). The interior cells hold the returned values, color-tinted by cell type.
Right-click a cell to change its meaning:

Cell type Meaning
Price A plain value (price, adjustment, …).
SubMatrix The ID of another matrix to look up next (pick from a
list).
+Row / +Column The value is multiplied by the row / column
band value.
Error / Warning The ID of a message to raise (pick from a
list).
Title Display text.
Commission A percentage rate — only on commission-family matrices;
must be 0 or greater.

The toolbar and context menu also offer Insert Row / Delete Row / Insert Column /
Delete Column
to reshape the grid.

Worked example — a width × height price matrix

Slab doors are priced by united inches, in 6″ steps. A flat price can’t express
that; one matrix can:

Step Where Value Why
1 New → Description “Slab Door $ by W×H” The name dealers and pricing staff will recognize in the filter list.
2 Type Price A pricing lookup — the type controls
which axis types and cell types are allowed.
3 Row Axis Type = Width, Start 24, End 96, Step 6, Measure =
Imperial
Generates rows 24, 30, 36 … 96 — the numeric axis does
the typing for you.
4 Column Axis Type = Height, Start 60, End 96, Step 6 Columns 60, 66 … 96; the column list was already filtered to combinations
valid for a Price matrix with a Width row.
5 Generate grid, fill cells 24×60 = 189.00 rising to
96×96 = 512.00
Each cell is the price returned for that band; the
engine matches a 29⅝″ item into the 24–30 row.
6 Point something at it Designs tab → the slab design’s
Matrix combo
A matrix nothing references prices nothing — the
last step is always wiring it into a series, choice, design, or rule.

Workflows

  • Create a matrix: New → fill Description, pick Type and
    Series → pick the Row Type (the column types re-filter to valid
    combinations) and complete the axis → same for the column axis → Save once to
    store the header → Generate grid → type values into the interior cells, adjust
    bands, set cell types by right-clicking → Save (“Matrix saved.”).
  • Edit: select → Edit → change header and/or cells → Save. If you
    change an axis type or option, regenerate the grid with Generate grid.
  • Copy: select → Copy → the header and grid are cloned with no ID → adjust
    → Save creates it as a new matrix.
  • Delete: select → Delete → confirm.
  • Domain-drift warning: opening a matrix whose enumerated axis has changed since
    it was built (an option answer added or deleted) pops a warning that the axis now has
    n entries but the matrix was built with m — regenerate the grid to pick
    up the change.

Special cases and cautions

  • Lookup matrices (SQL-driven) and sub-matrices (derived from another
    matrix via an operator) have no editable cells — the screen shows a read-only
    explanation and Save is disabled.
  • Deleting is not blocked even if rules, options, or other matrices reference the
    matrix — check usage first.
  • Saving is blocked when Description or Type is missing; when a numeric axis has Start ≥
    End, Step ≤ 0, or non-numeric values; or when a dimensional band cell is not numeric.
    A Commission cell only accepts a non-negative number.
  • The Dealer Group axis type is not currently wired — matrices built on it render
    an empty grid. Avoid it for now.

Tables behind this screen

matrix_header (tenant) — one row per matrix: id, description, the matrix
type, the two axis definitions (axis type, option picker or start/end/step), units,
owning series, and flags marking lookup (SQL-driven) and sub-matrices. This is the Header
panel.

matrix (tenant) — one row per grid cell, keyed by a composite
(id, cell_no) where id is the header id. Each cell stores its
band bounds (rowL/rowU/colL/colU — member ids for enumerated axes, scaled
numbers for dimensional ones; the engine range-matches lower ≤ value ≤ upper), a cell type,
and a polymorphic price column (plain value, matrix id, message id, factor,
percent, or text, depending on the cell type). cell_no is the 1-based,
row-major layout ordinal — the engine never reads it, so reshaping rows and columns
in the editor is safe. Saving is a header upsert plus a delete-all/re-insert of the cells
in one transaction.

Matrix types — type_matrix

Global dictionary powering the Type combo and the list filter (all 28 rows;
ids 3 and 24–29 do not exist):

id Name What it is
1 Valid Products Pricing matrix for valid product
combinations.
2 Options/Answers Prices option answers.
4 Sealed Units Sealed-unit pricing.
5 Standard Grids Standard grid pricing.
6 Custom Grids Custom grid pricing; adds the Spokes ↔ Radii axis
pairing.
7 Grid Templates Same Spokes ↔ Radii addition as type 6.
8 Couplers/Mullions Profile pricing; adds the Length axis with
restricted pairings.
9 Designs Design pricing.
10 Standard Products Standard-product pricing.
11 SubMatrix Grids-type-code × grids-type-code matrix used as a
SubMatrix target.
12 Matrix For V Width-driven matrix (Width axis
required).
13 Matrix For H Mirror of 12 with Height.
14 Product Type None × Product Type only.
15 Part Matrix Part selection/pricing; full axis set.
16 Profile Matrix Profile pricing; full axis set.
17 Area Matrix Area pricing; values stored raw — not
unit-scaled.
18 Segment Matrix Segment (sub-routine) pricing; full axis
set.
19 AnswerId Matrix Returns an answer id; full axis set.
20 Qty Matrix Quantity lookup.
21 Warning Warning-message matrix.
22 Error Error-message matrix. ⚠ No define rows → empty axis
combos for new matrices.
23 Adjustments Size-adjustment matrix — the only type whose Value
cells are unit-scaled. ⚠ No define rows → empty axis combos.
30 Part Cost Part costing.
31 Part Price Part pricing.
32 Qty Discount Commission-family type (Commission cells
allowed). ⚠ No define rows → empty axis combos.
33 commissions Commission rate matrix; Commission cells
allowed.
34 Sales Targets Sales-target matrix; Commission cells allowed.
⚠ No define rows → empty axis combos.
35 Price Include None × Prod. Series only.

Axis types — type_matrix_dictionary

Global dictionary powering the Row Type / Col Type combos. Kinds:
enumerated (the bands are an existing list), numeric (generated from
Start/End/Step — dimensional ones are unit-scaled), date, and
None.

id Name Kind Notes
1 Opening Class enumerated, series-scoped Opening types
of the header series. Fully wired.
2 None none Single synthetic wildcard band; always
matches.
3 Shape enumerated, series-scoped Shapes of the header
series. Fully wired.
4 Options and Answers enumerated Answers of the option
chosen in the Option combo; numeric instead when the option’s type ≥ 3. Fully
wired.
6 SU Type enumerated Sealed-unit types. Fully
wired.
7 User Def Opening Name enumerated, series-scoped The
series’ opening/shape records (band shows the abbreviation). Fully wired.
8 SU Family enumerated Sealed-unit families. Fully
wired.
11 Grids type-code enumerated Grid definitions. Fully
wired.
12 Partner enumerated Partners; engine probes the current
customer. Fully wired.
13 Partner Group ID enumerated ⚠ Editor gap: the
engine honors this axis at runtime, but the screen cannot enumerate partner groups —
the grid renders empty.
14 Design enumerated (engine-only) Runtime-only; the grid
renders empty in the editor.
15 Std Product enumerated (engine-only) Runtime-only;
grid renders empty.
22 Width numeric, dimensional Fully wired.
23 Height numeric, dimensional Fully wired.
24 UI numeric, dimensional United inches; imperial-only
in practice. Fully wired.
25 Area numeric, raw Never unit-scaled. Fully
wired.
26 No. Grid W numeric, raw Grid bars across. Fully
wired.
27 No. Grid H numeric, raw Grid bars high. Fully
wired.
28 Date date String-range compare, not numeric. Fully
wired.
29 No. Spokes numeric, raw Fully wired.
30 No. Radii numeric, raw Fully wired.
31 Product Type enumerated Order-item types. Fully
wired.
32 length numeric, dimensional Profile length. Fully
wired.
34 Quantity numeric, raw Wired; meaningful mainly in cart
contexts.
35 Volume numeric, raw Same cart-context caveat as
34.
36 Prod. Series enumerated Editor wired; the engine probe
is a stub.
40 LeftTopOpening — Unused/dead — no editor domain, no
engine case, not in define rows.
41 rightBotOpening — Effectively dead, though one stray
define row offers it as a column type (commissions).
42 Pricing Category enumerated ⚠ The editor enumerates
price groups, but the engine has no case for it — no runtime support.
43 Net List Ratio numeric, raw The realized net÷list
discount factor (commission matrices). Fully wired.
44 Parent UI numeric, dimensional Frame UI. Fully
wired.
45 Weight numeric, raw Engine-wired but in no define rows
— not selectable in the editor.
50 Inertia — Engine-only; not selectable.
51 Tributary (Inertia) — Engine-only; not
selectable.

Cell types — type_matrix_cell

Global dictionary behind the right-click Cell Type submenu (all 8 rows):

id Name Submenu label What the engine does
1 Value Price Returns the cell value as the result. The
only unit-scaled type, and only in Adjustments (type 23) matrices.
2 Matrix SubMatrix The value is another matrix id; the
engine recurses into it.
3 Error Error The value is an error-message id; raises
the message and returns 0.
4 Warning Warning Same, with a warning message.
5 Title Title Display text.
6 xC +Column Returns value × the column band
value.
7 xR +Row Returns value × the row band value.
8 Commission Commission A percent rate (7.5 = 7.5%),
never unit-scaled; authored only in matrix types 32/33/34.

Allowed axis combinations — type_matrix_define

Global table of (matrix_type, row_type, col_type) rows — “for this matrix
type, this row axis may pair with this column axis”. It is what re-filters the Col
Type
combo when you change the Row Type. Summary of the live combinations
(axis ids per the table above):

Matrix type Row types offered Column rule
Most pricing types (1, 2, 4, 5, 9, 10, 15–21, 30, 31) 1, 2, 3, 4, 6, 7, 11, 13, 14, 15, 22–28 Nearly free pairing; exceptions: row 1 (Opening Class) excludes column 4
(Option), and row 28 (Date) excludes column 28 (no Date × Date).
6, 7 (Custom Grids / Grid Templates) Base set + 29, 30 Spokes (29) pairs only with Radii (30) and vice versa; other rows pair
freely.
8 (Couplers/Mullions) Base set + 32 (Length) Length (32) pairs only with None (2), Partner Group (13), Date (28); those pair
only within {2, 13, 28, 32}.
11 (SubMatrix) 11 only 11 only — grids-type-code ×
grids-type-code.
12 (Matrix For V) 1, 2, 22 Rows 1/2 → column Width (22) only;
row 22 → columns 1/2 only.
13 (Matrix For H) 1, 2, 23 Mirror of 12 with Height
(23).
14 (Product Type) 2, 31 2 ↔ 31 only.
33 (commissions) 2, 4, 12, 13, 14, 15, 28, 34, 36, 42 Restricted cross-product of the same set, each row excluding itself. (Live data
quirk: row 2 offers column 41 instead of 42 — a seeding error, as 41 has no
support.)
35 (Price Include) 2, 36 2 ↔ 36 only.
22, 23, 32, 34 — No rows at all → empty axis combos for
new matrices of these types.

⚠ Cautions:

  • Matrix types 22 (Error), 23 (Adjustments), 32 (Qty Discount), 34 (Sales
    Targets)
    have no define rows — a new matrix of one of those types shows
    empty Row/Col Type combos. Existing matrices of those types still load and work
    fine.
  • The Dealer Group axis (13) has no editor support — the engine honors it, but
    the grid renders empty.
  • The Pricing Category axis (42) has no engine support — the editor enumerates
    it, but the runtime cannot probe it.
  • The matrix_series link table is legacy — this screen uses the
    header’s Series field directly and never reads or writes it.