Skip to main content
All Docs
FeaturesagentOS Block ManagerUpdated April 13, 2026

Building Fabric: Section-by-Section Replacement Forecasting

Building Fabric: Section-by-Section Replacement Forecasting

Available from: v0.13.16

Building Fabric assets now support per-section replacement forecasting. Instead of modelling a whole-asset replacement as a single event, each discrete section of a building fabric asset (e.g. North elevation render, Flat roof — main block, Guttering — east wing) can carry its own install date, lifespan estimate, and auto-calculated replacement year.

This means partial replacement events — where one section is replaced while others remain intact — can be planned and tracked accurately without creating duplicate top-level asset records.


How It Works

Per-Section Fields

When editing a Building Fabric asset, each section now includes three additional fields:

FieldDescription
Section Install / Last Replaced DateThe date this specific section was installed or last replaced. Accepts a calendar date.
Section Lifespan (years)The expected service life for this section in years.
Projected Replacement YearAutomatically calculated from the install date + lifespan. Displayed as a read-only badge but stored for timeline and reporting use.

These fields are stored in the existing fabricSections JSON column — no database changes are required and existing section data is unaffected.

Auto-Calculation

The projected replacement year is recalculated automatically whenever the install date or lifespan changes:

Projected Replacement Year = Year(installDate) + estimatedLifespanYears

For example, a section installed in March 2010 with a 25-year lifespan will show a projected replacement year of 2035.


Section Replacement Timeline

The Building Fabric read view now includes a Section Replacement Timeline — a vertical chronological view of all scheduled section replacements.

Colour Coding

StatusColourCondition
Overdue🔴 RedProjected year ≤ current year
Due soon🟡 AmberProjected year within 5 years
Future🔵 Blue / defaultProjected year > 5 years away

Each year group shows:

  • The projected replacement year and a status label (Overdue, This Year)
  • Aggregated cost for all sections due that year
  • Individual section cards with condition rating and estimated cost

Sections that have no install date or lifespan are listed separately at the bottom of the timeline with a prompt to add the missing data.


Section Read View

Each section card in the read view now shows additional metadata at a glance:

  • Installed date
  • Lifespan (e.g. 25-year lifespan)
  • Replace YYYY badge — colour-coded by urgency
  • Section lifespan progress bar — fills from green to red as the section ages through its estimated lifespan

Statistics Panel

The statistics panel above the section list now includes a fourth card: Scheduled Replacements, showing X / Y sections — how many of the total sections have a projected replacement year recorded.


Reserve Fund Integration

The per-section replacement year and cost data feeds directly into the reserve fund projection. Section-level capex is aggregated by replacement year and surfaced in the 10-year capital expenditure forecast.

The fabricSectionsSummary API endpoint provides this aggregated data programmatically. See the API Reference below.


fabricSectionsSummary Endpoint

The asset.fabricSectionsSummary tRPC query returns aggregated section-level data for reserve fund and reporting use.

Input

{
  blockId?: string  // Optional. Scopes results to a single block.
}

Output

{
  totalBuildingFabricAssets: number;
  totalSections: number;
  scheduledSections: number;         // Sections with a projected replacement year
  totalSectionCostPence: number;
  avgSectionCondition: number | null; // 1–5 scale, rounded to 1 decimal place
  poorSections: number;               // Sections rated condition 1 or 2
  overdueSectionCount: number;        // Replacement year ≤ current year
  dueSoonSectionCount: number;        // Replacement year within 5 years
  sectionCostsByYear: Record<number, number>; // { [year]: totalCostPence }
  sections: Array<{
    assetId: string;
    assetName: string;
    blockId: string;
    section: string;
    condition: number | null;
    estimatedCostPence: number | null;
    projectedReplacementYear: number | null;
    installDate: string | null;
    estimatedLifespanYears: number | null;
  }>;
}

Usage Example

const summary = await trpc.asset.fabricSectionsSummary.query({
  blockId: "block_abc123",
});

// Cost aggregated by replacement year — suitable for reserve fund charts
console.log(summary.sectionCostsByYear);
// e.g. { 2027: 1250000, 2031: 4800000, 2035: 720000 }

// Sections needing immediate attention
console.log(summary.overdueSectionCount);
console.log(summary.dueSoonSectionCount);

Data Model

Section data is stored as a JSON array in the fabricSections column of the assets table. Each section object may now include:

{
  "section": "North elevation render",
  "condition": 3,
  "estimatedCostPence": 1250000,
  "quantityM2": 320.5,
  "installDate": "2012-06-01",
  "estimatedLifespanYears": 25,
  "projectedReplacementYear": 2037,
  "notes": "Repointed 2019, minor cracking noted south corner"
}

All new fields are optional. Existing section records without these fields continue to work as before.


Tips

  • Partial replacements: When one section is replaced but others are not, update only that section's installDate. The projected replacement year recalculates automatically. The other sections retain their original dates.
  • Unscheduled sections: Any section without an install date and lifespan appears in the timeline's unscheduled list. Work through these to ensure complete reserve fund coverage.
  • Overdue sections: Sections where the projected replacement year has already passed are flagged in red throughout the UI. Review and update these to confirm whether replacement has occurred or is still pending.