diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index 26b424e70..80a650515 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -986,7 +986,15 @@ class EpcPropertyDataMapper: pv_battery_count=0, wind_turbines_count=schema.sap_energy_source.wind_turbines_count or 0, gas_smart_meter_present=False, - is_dwelling_export_capable=False, + # Top-level full-SAP export flag (SAP 10-era lodgements; None + # on the SAP 2012 family → False, unchanged). Appendix M1 zeroes + # the PV export credit without the flag, under-rating any + # export-capable PV cert (PRD #1435 WS3). `pv_connection` is NOT + # carried — the full-SAP enum disagrees with the RdSAP one the + # calculator's connection gate reads (see SapSchema17_1). + is_dwelling_export_capable=( + schema.is_dwelling_export_capable == "true" + ), wind_turbines_terrain_type=str( schema.sap_energy_source.wind_turbine_terrain_type or "" ), diff --git a/datatypes/epc/schema/sap_schema_17_1.py b/datatypes/epc/schema/sap_schema_17_1.py index e4f41d9e9..656a28b25 100644 --- a/datatypes/epc/schema/sap_schema_17_1.py +++ b/datatypes/epc/schema/sap_schema_17_1.py @@ -247,3 +247,13 @@ class SapSchema17_1: has_hot_water_cylinder: Optional[str] = None # Present for flat-type dwellings; absence means not a flat. sap_flat_details: Optional[SapFlatDetails] = None + # Top-level PV export-capability flag (lodged by the SAP 10-era full-SAP + # schemas; absent on the SAP 2012 family, where SEG export did not exist). + # SAP 10.2 Appendix M1 zeroes the PV export credit unless the dwelling is + # connected to an export-capable meter, so dropping the flag under-rates + # any export-capable PV cert (~3 SAP on cert 0380-3044-6070-2305-5925). + # The sibling top-level `pv_connection` is deliberately NOT parsed: the + # full-SAP enum disagrees with the RdSAP/gov-API one the calculator gates + # on (full-SAP certs lodge 1 with a PV credit included; RdSAP 1 = "not + # connected" = no credit), so carrying it across would zero real arrays. + is_dwelling_export_capable: Optional[str] = None diff --git a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py index 5604b8015..70a93637b 100644 --- a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py +++ b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py @@ -303,11 +303,16 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = ( # the schema dropped at parse, so the Appendix-M generation credit was lost. # Carrying it (mapper `_sap_17_1_pv_arrays`) credits the generation and lifts # this flat 82→84, closing most of the gap to the lodged 85 the array explains. + # WAS 84 until the full-SAP export-capable mapping landed (PRD #1435 WS3): + # this cert lodges `is_dwelling_export_capable: true`, which the mapper + # hardcoded False, so Appendix M1 zeroed the array's export credit. Carrying + # the lodged flag restores it and the engine now reproduces the lodged 85 + # EXACTLY — the last −1 was the missing export credit, not a methodology gap. RealCertExpectation( schema="SAP-Schema-19.1.0", sample="uprn_10096028301", cert_num="0390-3321-6060-2405-7985", - sap_score=84, + sap_score=85, ), # UPRN 10094615101 → cert 0380-3044-6070-2305-5925. SAP-Schema-19.1.0 — a # FULL-SAP TOP-FLOOR FLAT (2023 new build, St Leonards-on-Sea, TFA 76 m²,