test(modelling): ASHP from a system gas boiler with an existing cylinder

Pins the cylinder-OVERWRITE path the earlier ASHP pins did not exercise:
boiler-1/boiler-2 added a cylinder where none existed, whereas boiler-3's
before is a mains-gas regular boiler (SAP code 101) that already heats its
own cylinder (size 2 / insulation type 2 / 80 mm). The fixed _ASHP_OVERLAY
overwrites it to the heat-pump cylinder (size 4 / insulation type 1 / 50 mm)
and switches the dwelling off mains gas (fuel 26->30, code 101->index 101413
+ category 4). The existing overlay reproduces the re-lodged after at delta 0
on SAP / CO2 / primary energy -- no overlay change needed; immersion_heating_
type is None in both, so that field (the electric-with-cylinder case) is
untouched here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-06 18:20:58 +00:00
parent ec76acc3d8
commit d9c7638b3c
3 changed files with 26 additions and 0 deletions

View file

@ -666,6 +666,32 @@ def test_ashp_overlay_reproduces_the_relodged_after_from_a_gas_boiler_instant_hw
_assert_overlay_reproduces_after(before, after, option.overlay)
def test_ashp_overlay_reproduces_the_relodged_after_from_a_system_boiler_with_cylinder() -> None:
# Arrange — a mains-gas *regular/system* boiler (SAP code 101, not a combi)
# that already heats its own hot-water cylinder (size 2 / insulation type 2 /
# 80 mm) re-lodged as an ASHP. This exercises the cylinder OVERWRITE path that
# boiler-1/boiler-2 didn't: those added a cylinder where none existed, whereas
# here the overlay must overwrite the existing cylinder to the fixed heat-pump
# cylinder (size 4 / insulation type 1 / 50 mm). The dwelling also goes off
# mains gas (fuel 26 -> 30, code 101 -> index 101413 + category 4, control
# 2113 -> 2210).
before: EpcPropertyData = parse_recommendation_summary(
"ashp_from_system_boiler_with_cylinder_001431_before.pdf"
)
after: EpcPropertyData = parse_recommendation_summary(
"ashp_from_system_boiler_with_cylinder_001431_after.pdf"
)
recommendation: Recommendation | None = recommend_heating(before, _AnyProduct())
assert recommendation is not None
option = next(
o for o in recommendation.options if o.measure_type == "air_source_heat_pump"
)
# Act / Assert — the absolute overlay overwrites the existing cylinder and
# reproduces the after exactly.
_assert_overlay_reproduces_after(before, after, option.overlay)
_BOILER_INSTANT_HW_FUEL_REASON: Final[str] = (
"Blocked on the Elmhurst mapper deriving main_fuel_type for a gas boiler "
"lodged with EES code 'BGB' / Main Heating SAP code 102: it currently maps "