mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-07-27 22:45:03 +00:00
fix(reporting): interim guard — don't count already-at-target homes as upgraded
The modelling engine emits costed plans for homes already at a scenario's target EPC band (e.g. ~£300–600 of low-energy lighting / system tune-ups on effective-C homes in a "Reach EPC C" scenario). Counting them inflated "Homes upgraded" and its costs, and stopped the KPI reconciling with the below-target band distribution (portfolio 796 / scenario 1268: 9492 upgraded vs 9039 homes below C). Add an interim guard to the scenario metrics upgrade aggregate (count + cost): for Increasing-EPC scenarios, drop any home whose effective band already meets the target (effective band <= goal_value; lexical, A best). Unknown/NULL effective band is kept. Verified against the DB: scenario 1268 goes 9492 → 8871 upgraded, −£282k of works on compliant homes. This is a reporting-only band-aid; the root cause is in the engine — tracked in Hestia-Homes/Model#1652. The default/recommended view has no single target band, so the guard doesn't apply there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
32da5bf079
commit
41b89c0d8f
1 changed files with 28 additions and 0 deletions
|
|
@ -7,6 +7,7 @@ import {
|
|||
carbonSql,
|
||||
billsSql,
|
||||
effectiveSapSql,
|
||||
effectiveEpcBandSql,
|
||||
isNewApproachSql,
|
||||
lodgedSapSql,
|
||||
} from "@/lib/services/epcSources";
|
||||
|
|
@ -199,6 +200,30 @@ export async function GET(
|
|||
? EPC_MIN_SAP[scenario.goal_value]
|
||||
: null;
|
||||
|
||||
// The scenario's target band, for Increasing-EPC scenarios only (other goals
|
||||
// have no band target). Used by the interim already-at-target guard below.
|
||||
const targetBand =
|
||||
scenario.goal === "Increasing EPC" ? scenario.goal_value : null;
|
||||
|
||||
/**
|
||||
* INTERIM guard for a backend bug (Hestia-Homes/Model#1652): the modelling engine
|
||||
* emits costed plans for homes that are ALREADY at the scenario's target band
|
||||
* — e.g. ~£300–600 of low-energy lighting / system tune-ups on effective-C
|
||||
* homes in a "Reach EPC C" scenario. Those aren't upgrades toward the target,
|
||||
* so counting them inflates "Homes upgraded" (and its costs) and stops the KPI
|
||||
* reconciling with the below-target band distribution. Until the engine stops
|
||||
* recommending works on already-compliant homes, exclude any home whose
|
||||
* EFFECTIVE band already meets the target from the upgrade aggregate. Bands
|
||||
* compare lexically (A best), so "still needs work" = effective band > target.
|
||||
* Unknown/NULL effective band is kept (can't prove compliant). Only bites for
|
||||
* Increasing-EPC scenarios; NULL targetBand ⇒ no-op.
|
||||
*/
|
||||
const stillNeedsUpgradeSql = sql`(
|
||||
${targetBand}::text IS NULL
|
||||
OR (${effectiveEpcBandSql}) IS NULL
|
||||
OR (${effectiveEpcBandSql})::text > ${targetBand}::text
|
||||
)`;
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
The three data queries below are independent — they only need `minSap`
|
||||
(from the scenario definition above), not each other's results — so they
|
||||
|
|
@ -307,6 +332,9 @@ export async function GET(
|
|||
-- (target-level post_sap on already-compliant homes) — not real upgrades.
|
||||
-- COALESCE keeps rows we can't compare. See ADR-0002.
|
||||
AND COALESCE(lp.post_sap_points >= (${effectiveSapSql}), true)
|
||||
-- INTERIM: drop homes already at the scenario target band (backend bug —
|
||||
-- see stillNeedsUpgradeSql above, Hestia-Homes/Model#1652).
|
||||
AND ${stillNeedsUpgradeSql}
|
||||
AND (
|
||||
${useLodgedBaseline} = false
|
||||
OR ${minSap}::float IS NULL
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue