diff --git a/domain/modelling/products.py b/domain/modelling/products.py index 99d10b0b..4fa6ee31 100644 --- a/domain/modelling/products.py +++ b/domain/modelling/products.py @@ -29,6 +29,11 @@ _ASHP_MEASURE_TYPE = "air_source_heat_pump" # Decommission an existing electric-storage system, by property size band. _DECOMMISSION_ELECTRIC_STORAGE_SMALL = 570.0 _DECOMMISSION_ELECTRIC_STORAGE_LARGE = 840.0 +# Decommission an existing wet (boiler) system — flat across property size for +# gas and oil; LPG carries the extra tank/fuel removal (ECOHT06-08, 03-04). +_DECOMMISSION_GAS = 720.0 +_DECOMMISSION_OIL = 720.0 +_DECOMMISSION_LPG = 960.0 # Heat-pump install (MONOBLOC, brand-neutral), by kW size band — design heat # loss is rounded up to the next band (ECOHT09-13). @@ -112,11 +117,19 @@ class Products: return _PUMP_TOP_PRICE def _decommission(self, inputs: AshpCostInputs) -> float: - return ( - _DECOMMISSION_ELECTRIC_STORAGE_SMALL - if inputs.is_small_property - else _DECOMMISSION_ELECTRIC_STORAGE_LARGE - ) + if inputs.existing_system is AshpExistingSystem.ELECTRIC_STORAGE: + return ( + _DECOMMISSION_ELECTRIC_STORAGE_SMALL + if inputs.is_small_property + else _DECOMMISSION_ELECTRIC_STORAGE_LARGE + ) + if inputs.existing_system is AshpExistingSystem.GAS: + return _DECOMMISSION_GAS + if inputs.existing_system is AshpExistingSystem.OIL: + return _DECOMMISSION_OIL + if inputs.existing_system is AshpExistingSystem.LPG: + return _DECOMMISSION_LPG + raise ValueError(f"no decommission rate for {inputs.existing_system}") def _distribution(self, inputs: AshpCostInputs) -> float: radiators: int = max(_MIN_RADIATORS, min(_MAX_RADIATORS, inputs.radiator_count)) diff --git a/tests/domain/modelling/test_products.py b/tests/domain/modelling/test_products.py index 799d8a46..964ee7e5 100644 --- a/tests/domain/modelling/test_products.py +++ b/tests/domain/modelling/test_products.py @@ -37,3 +37,29 @@ def test_ashp_bundle_cost_composes_an_electric_storage_full_distribution_dwellin # (7 rads) 3618 = 16290.60, with the separate 25% ASHP contingency. assert abs(cost.total - 16290.60) <= 1e-9 assert abs(cost.contingency_rate - 0.25) <= 1e-9 + + +def _large_no_reuse(system: AshpExistingSystem) -> AshpCostInputs: + """A large dwelling, 8 kW band, 8 radiators, no reusable wet system — so the + only thing varying with ``system`` is the decommission line.""" + return AshpCostInputs( + existing_system=system, + is_small_property=False, + design_heat_loss_kw=8.0, + radiator_count=8, + has_reusable_wet_system=False, + ) + + +def test_decommission_cost_varies_by_existing_system() -> None: + # Arrange — common: pump (8 kW) 9840 + cylinder 2382.60 + distribution (8 + # rads) 4152 = 16374.60; only decommission differs by system. + products = Products() + common = 16374.60 + + # Act / Assert — gas and oil are flat 720; LPG 960; electric-storage large + # 840 (small 570 is pinned by the tracer above). + assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.GAS)).total - (common + 720.0)) <= 1e-9 + assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.OIL)).total - (common + 720.0)) <= 1e-9 + assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.LPG)).total - (common + 960.0)) <= 1e-9 + assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.ELECTRIC_STORAGE)).total - (common + 840.0)) <= 1e-9