"""The ModellingOrchestrator threads the dwelling's SAP design heat loss into the heating Recommendation Generator so the ASHP is sized to the dwelling (ADR-0049), mirroring how planning_restrictions and the solar potential are threaded. Tests the candidate-wiring seam directly; the end-to-end run-through- repos path is covered by the DB integration tests. """ from datatypes.epc.domain.epc_property_data import EpcPropertyData from domain.geospatial.planning_restrictions import PlanningRestrictions from domain.modelling.measure_type import MeasureType from domain.modelling.product import Product from domain.modelling.recommendation import Recommendation from orchestration.modelling_orchestrator import ( _candidate_recommendations, # pyright: ignore[reportPrivateUsage] ) from repositories.product.product_repository import ProductRepository from tests.domain.modelling._elmhurst_recommendation import ( parse_recommendation_summary, ) class _StubProducts(ProductRepository): def get(self, measure_type: str) -> Product: return Product( measure_type=measure_type, unit_cost_per_m2=0.0, contingency_rate=0.15, id=909, ) def _ashp_eligible_house() -> EpcPropertyData: epc = parse_recommendation_summary( "ashp_from_system_boiler_with_cylinder_001431_before.pdf" ) epc.property_type = "House" return epc def test_candidate_recommendations_sizes_the_ashp_to_the_threaded_design_heat_loss() -> ( None ): # Arrange — an ASHP-eligible house and a high (17.5 kW) design heat loss. epc = _ashp_eligible_house() # Act recommendations: list[Recommendation] = _candidate_recommendations( epc, _StubProducts(), PlanningRestrictions(), None, None, design_heat_loss_kw=17.5 ) # Assert — the ASHP is sized to the load (capped 12 kW aroTHERM plus 110281), # not the fixed 5 kW / floor-area-proxy unit. heating = next(r for r in recommendations if r.surface == "Heating & Hot Water") ashp = next( o for o in heating.options if o.measure_type == MeasureType.AIR_SOURCE_HEAT_PUMP ) assert ashp.overlay.heating is not None assert ashp.overlay.heating.main_heating_index_number == 110281