Channel Letters — configurable product engine

3 min read

Status Current
Last verified 2026-10-07 (matches Git at import; content not re-reviewed)
Source Git
Source file docs/CHANNEL_LETTERS.md — view on GitHub
Article language original from Git
Git repository git@github.com:advertech/signage-estimator.git (server: /root/signage-estimator)
Git commit d22587c1f7e3add9efd54c7ffc0be0a01b296fa3 (master)
File last changed 6ac6f354d0d8 on 2026-09-26
Last imported 2026-10-07T09:14:19+02:00
Note Source of truth: Git. Edit the file in the repository and re-run /root/wiki-sign-expert/import_git_docs.py; edits made here will be overwritten by the next import.

The Channel Letters prototype is built on the generic product configuration engine in backend/app/products.py. A ProductType has Technology choices; each technology owns immutable published TechnologyVersion definitions. A calculation stores its selected technology-version ID, manual parameter inputs, frozen price/rate snapshots, component nesting summaries, and calculated result. Revision snapshots include that configuration, so old revisions keep their exact definition and price basis.

Rules and estimate fields #

TechnologyParameter rows define the UI fields, input type, default, visibility condition, bounds, and whether the field is automatic. TechnologyRule rows evaluate a whitelist of geometry properties in priority order. Effective values prefer a valid manual override; otherwise an automatic field uses its first matching rule, then its configured default. The result stores each field’s automatic value, effective value, source (auto, default, or manual), and rule reason. The configuration stores manual inputs only; reset removes an override and re-evaluates the rule.

The current aluminium rules select 1.5 mm backing up to 800 mm letter height and 2.0 mm above it; return depth is 60 mm up to 600 mm and 100 mm above. These are prototype rules and should be confirmed by production. Composite backing uses ACP 3 mm and has its own pre-painted return profile. Switching technology keeps only parameter keys available in the target version, which preserves the LED supplier quote while dropping painting-only choices.

Components, routes, and costing #

TechnologyMaterial describes each cost component and its calculation method: NESTED_SHEET, PERIMETER_LENGTH, AREA, LENGTH_INPUT, or MANUAL_COST. Sheet components choose from canonical materials and reuse the existing contour nesting engine. BACK and FACE are nested independently using their chosen material’s own sheet dimensions. Linear and area components use the normalized calculation geometry.

TechnologyOperation routes an operation to an estimate driver and cost category. Conditional routes can inspect estimate fields. Drivers include fixed, piece, meter, square meter, sheet, minute, LED, and machine-time quantities. Materials and operation/master rates are snapshotted by catalog identity on first calculation. Refreshing prices is explicit. Product breakdown categories are converted into existing calculation rows, which continue to feed the existing markup, sales price, and margin totals; per-part rows are removed while the configured product is active to prevent double-counting.

Selective nesting cache #

Each nested component caches a key made from normalized geometry identity, the selected material ID, that material’s sheet width/height, gap, and edge margin. Recalculation compares keys independently by component code. Changing only LED cost, painting selection/rate, or another non-geometric route does not schedule nesting. Changing back thickness/material invalidates BACK when its material/key changes; changing face thickness/material invalidates FACE when its material/key changes. A geometry, gap, or margin change invalidates each nested component that uses those inputs. The cache is a calculation-result cache, not a shared/global cache.

The calculation commits before isolated nesting starts so it does not hold a database connection while the subprocess runs. The result records which component jobs actually ran; the details view labels other component layouts as reused.

Technology lifecycle and extending the catalog #

DRAFT versions can be edited through Settings → Product Types. Publishing archives the prior published version; published and archived versions reject changes. Create a new draft from the published version to make edits. A calculation stays pinned to its original version until an estimator explicitly upgrades/reselects it.

To add the next product technology without changing core code:

  1. Create or select a Product Type and add a Technology.
  2. Create a draft version; add parameters and deterministic rules using the supported geometry properties.
  3. Add material components, choosing an existing catalog material or an explicitly demo-marked one. Configure each component’s selector/family, method, waste factor, and cost group.
  4. Add operation routes with supported drivers, conditions, and cost categories; configure master rates and machine profiles.
  5. Set estimate markup and notes, then publish the version. Verify it against representative geometry before quoting.

Only new geometry-derived metrics, calculation methods, operation drivers, or rule operators require a core engine extension. Supplier-specific business logic and individual product definitions belong in version data.

Demo and incomplete commercial rates #

All starter values created as demo data are marked is_demo. Estimates surface a non-commercial warning whenever a snapshotted line uses a demo rate. Zero-valued routes additionally produce “no rate configured” warnings when used. The starter set deliberately leaves powder coating, painting transport, and frame painting at zero pending real supplier/production rates. Replace every demo material and operation rate before issuing a commercial quote.

The handoff’s referenced “section 33” test list was not present in the repository, branch history, documentation, or test skeletons. The implementation adds 12 named acceptance tests in backend/tests/test_channel_letters_products.py for the recovered minimum behaviors.

Updated on 07.10.2026