The ASHP bundle sizes the heat pump to the dwelling's design heat loss 🟩

_ashp_option now selects the aroTHERM plus PCDB record matching the
threaded design heat loss (floor-area proxy fallback), so the overlay's
efficiency anchor is sized to the dwelling instead of a fixed 5 kW unit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-03 10:28:08 +00:00
parent df38dda7b0
commit 2dd637a657
2 changed files with 16 additions and 3 deletions

View file

@ -12,6 +12,7 @@ boiler bundles land in later slices. Detection + pricing only — impact is
produced by scoring (ADR-0016).
"""
from dataclasses import replace
from typing import Optional
from datatypes.epc.domain.epc_property_data import EpcPropertyData, MainHeatingDetail
@ -743,6 +744,16 @@ def _ashp_option(
``design_heat_loss_kw`` (ADR-0049), falling back to the floor-area proxy."""
if not _ashp_eligible(epc, restrictions):
return None
# Size the pump to the dwelling: the calculator's design heat loss when the
# caller threaded it, else the floor-area proxy (ADR-0049).
heat_loss_kw: float = (
design_heat_loss_kw
if design_heat_loss_kw is not None
else epc.total_floor_area_m2 * _KW_PER_M2
)
sized_overlay: HeatingOverlay = replace(
_ASHP_OVERLAY, main_heating_index_number=select_ashp_pcdb_id(heat_loss_kw)
)
# Cost is composed per-dwelling from the rate sheet (ADR-0025), not the
# single catalogue scalar; the catalogue row is read only for its id, so an
# absent ASHP row must not suppress the bundle — it just carries no id.
@ -754,7 +765,7 @@ def _ashp_option(
"Replace the heating with an air-source heat pump, time-and-"
"temperature-zone controls and a heat-pump hot-water cylinder"
),
overlay=EpcSimulation(heating=_ASHP_OVERLAY),
overlay=EpcSimulation(heating=sized_overlay),
cost=cost,
material_id=product.id if product is not None else None,
)

View file

@ -203,8 +203,10 @@ def test_gas_boiler_house_yields_an_ashp_bundle() -> None:
# bungalow regardless of current system or efficiency (ADR-0024).
baseline: EpcPropertyData = _gas_boiler_house()
# Act
recommendation: Recommendation | None = recommend_heating(baseline, _StubProducts())
# Act — a ~4 kW design heat loss sizes to the 5 kW aroTHERM plus (110257).
recommendation: Recommendation | None = recommend_heating(
baseline, _StubProducts(), design_heat_loss_kw=4.0
)
# Assert — the ASHP bundle carries the absolute heat-pump end-state.
assert recommendation is not None