mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Flag works bought for no real SAP gain 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
08d2b874d5
commit
31be36cca5
1 changed files with 43 additions and 3 deletions
|
|
@ -26,6 +26,11 @@ be justified against the real distribution, not guessed.
|
|||
Read-only: this script never writes to the DB.
|
||||
"""
|
||||
|
||||
# Every check is reached through `_REGISTRY` via the `@check` decorator, never by
|
||||
# name, so pyright sees each one as an unused function. That is the design, not a
|
||||
# defect — suppress it for the module rather than tagging a dozen definitions.
|
||||
# pyright: reportUnusedFunction=false
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
|
@ -42,6 +47,11 @@ from scripts.e2e_common import build_engine, load_env
|
|||
# A..G, A best — index is the rank (lower = better) for band comparisons.
|
||||
_BANDS = "ABCDEFG"
|
||||
|
||||
# The smallest SAP movement that counts as a real improvement. The effective
|
||||
# baseline is a rounded integer, so anything at or under half a point is within
|
||||
# the rounding the published band already absorbs — invisible on a certificate.
|
||||
_MIN_REAL_SAP_GAIN = 0.5
|
||||
|
||||
|
||||
def _band_rank(band: Optional[str]) -> Optional[int]:
|
||||
if band is None or band not in _BANDS:
|
||||
|
|
@ -189,7 +199,34 @@ def _already_meets_goal_with_works(a: PropertyAudit) -> Optional[str]:
|
|||
|
||||
@check("costed-plan-without-real-gain", Severity.HIGH)
|
||||
def _costed_plan_without_real_gain(a: PropertyAudit) -> Optional[str]:
|
||||
raise NotImplementedError
|
||||
"""Money was spent but the modelled post-retrofit SAP barely moves off the
|
||||
effective baseline — works that buy no real improvement.
|
||||
|
||||
Provenance: #1652 / #1655. This closes a coverage hole rather than adding a
|
||||
new opinion: `plan-score-below-baseline` only fires on a *drop* beyond 0.5,
|
||||
and `zero-works-post-differs` only on £0 plans, so a **costed** plan landing
|
||||
flat against the baseline was caught by neither. It is what the 112
|
||||
"no real improvement" homes in portfolio 796 looked like — priced plans whose
|
||||
post-retrofit SAP sat ~0.2 *below* the effective baseline — and what the
|
||||
band-boundary defect (#1654) produced at scale: 630 homes each sold ~1 SAP
|
||||
point of works toward a band they had already reached.
|
||||
|
||||
The 0.5 threshold is the same "within rounding is not a real move" line the
|
||||
published banding uses: the effective baseline is a rounded integer, so a
|
||||
sub-half-point shift is not a change anyone can see on a certificate. Spend
|
||||
that buys less than that is not a retrofit."""
|
||||
if a.effective_sap is None or a.post_sap is None:
|
||||
return None
|
||||
cost = a.cost_of_works or 0.0
|
||||
if cost <= 0.0:
|
||||
return None
|
||||
gain = a.post_sap - a.effective_sap
|
||||
if gain > _MIN_REAL_SAP_GAIN:
|
||||
return None
|
||||
return (
|
||||
f"£{cost:.0f} of works for {gain:+.1f} SAP "
|
||||
f"(effective {a.effective_sap:.1f} → post {a.post_sap:.1f})"
|
||||
)
|
||||
|
||||
|
||||
@check("plan-stops-short-of-goal", Severity.HIGH)
|
||||
|
|
@ -555,11 +592,14 @@ def _load(
|
|||
rollups = {
|
||||
m["property_id"]: (m["solar_sap"], m["solar_bill"], m["n_measures"])
|
||||
for m in (
|
||||
row._mapping for row in conn.execute(_ROLLUP_QUERY, params)
|
||||
# `Row._mapping` is public API in SQLAlchemy 2.0; only the
|
||||
# stub marks it protected.
|
||||
row._mapping # pyright: ignore[reportPrivateUsage]
|
||||
for row in conn.execute(_ROLLUP_QUERY, params)
|
||||
)
|
||||
}
|
||||
for r in conn.execute(_QUERY, params):
|
||||
m = r._mapping
|
||||
m = r._mapping # pyright: ignore[reportPrivateUsage]
|
||||
solar_sap, solar_bill, n_measures = rollups.get(m["id"], (None, None, 0))
|
||||
out.append(
|
||||
PropertyAudit(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue