Home/ News/ v3.6.0 / v3.6.1 — Multi-level BOQ hierarchy
Release 2026-05-18 ~4 min read

v3.6 — BOQs that nest as deep as a real project does.

Real construction estimates do not stop at two levels. v3.6.0 raises the hard cap to MAX_NESTING_DEPTH=8, teaches the BOQ editor a recursive parent_id tree walk and adds a resource-code dedup pass. v3.6.1 closes the rendering loop so the new depth is actually visible in the AG Grid tree.

BOQ editor showing nested hierarchy with ordinals, units, quantities, unit rates and totals

The Bill of Quantities is the load-bearing screen of the entire estimating flow. Until v3.6, OpenConstructionERP capped BOQ depth at two levels — enough for a textbook example, not enough for a real tender package where Building › Substructure › Foundations › Strip footings › Concrete › C30/37 is a perfectly ordinary path. v3.6.0 lifts the cap to eight and makes the editor respect it end-to-end. v3.6.1 is the small follow-up that fixed the one rendering branch where depth > 2 still flattened to a list.

What changed

MAX_NESTING_DEPTH = 8

The validator and the FastAPI schema both moved to a single shared constant MAX_NESTING_DEPTH = 8. Anything deeper raises a structured 422 with the failing ordinal path included — no more silent flattening when an import file went two levels past the old cap.

Recursive parent_id tree walk

The BOQ editor now builds the visible tree by recursively walking parent_id in a single query, instead of joining a fixed number of levels. Ordinals (01.02.003.04) regenerate on the way back up. The same walk powers totals roll-up and validation rule scoping.

Resource-code dedup (#133)

Cost catalogues from different sources used to land duplicate resource_code rows once a project imported from two regional catalogues. v3.6.0 added a one-pass dedup keyed on (catalogue_id, resource_code) with a deterministic winner so re-imports stop growing the table.

v3.6.1 — the visible-tree fix

v3.6.0 stored the deeper rows correctly but one render path in BoqGridContainer still trimmed at depth 2 because the group-row builder used a static column join. v3.6.1 switched it to the same recursive walk the service layer uses. Without it, deep rows were invisible — with it, they expand cleanly.

Why it matters

Eight levels is not an arbitrary number. It is what a typical DIN 276 cost-group tree wants once you keep both the standard’s three-level hierarchy and the project-specific subdivision underneath it. Anything shallower forces estimators to either fold work-packages together (lossy) or store the structure in the description column (untyped). Neither plays well with downstream GAEB export or roll-up reporting.

The dedup pass closes related issue #133. Until v3.6.0 every re-import of the same catalogue created another copy of every row; after, the catalogue table is stable across re-imports and the unique constraint is enforced at write-time.

Upgrade

pip install --upgrade openconstructionerp==3.6.1

Alembic head moves to v3037. Existing two-level BOQs are unchanged — the migration only adds index support for deeper trees. No data backfill is required.

See the BOQ editor in action.

Live demo in your browser, or self-host in five minutes. AGPL-3.0, no signup required.