Carry full-SAP lodged PV arrays through to the domain 🟩

Full-SAP certs lodge measured PV under sap_energy_source.pv_arrays, but the
SAP-Schema-17.1 SapEnergySource modelled only wind, so from_dict dropped it at
parse and the mapper hardcoded no PV. A new SapPvArray schema field + the
_sap_17_1_pv_arrays mapper helper carry it to the domain photovoltaic_arrays the
Appendix-M generation credit reads — without it an all-electric dwelling the
array lifts to A/B is mis-modelled down a band or more.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-29 21:59:21 +00:00
parent 4393812638
commit ea7f4f4329

View file

@ -869,6 +869,7 @@ class EpcPropertyDataMapper:
meter_type=_sap_17_1_meter_type(
schema.sap_energy_source.electricity_tariff
),
photovoltaic_arrays=_sap_17_1_pv_arrays(schema),
pv_battery_count=0,
wind_turbines_count=schema.sap_energy_source.wind_turbines_count or 0,
gas_smart_meter_present=False,
@ -2934,6 +2935,31 @@ def _sap_dwelling_on_mains_gas(schema: SapSchema17_1) -> bool:
)
def _sap_17_1_pv_arrays(
schema: SapSchema17_1,
) -> Optional[List[PhotovoltaicArray]]:
"""Map a full-SAP cert's lodged PV (`sap_energy_source.pv_arrays`) to the
domain `PhotovoltaicArray` list the calculator's Appendix-M generation
credit reads. Without this the PV is dropped and an all-electric dwelling
that the array lifts to A/B is mis-modelled down a band or more. An array
with no peak power generates nothing, so it's skipped; orientation honours
the ND/NA sentinel (None zero-generation array)."""
arrays = schema.sap_energy_source.pv_arrays
if not arrays:
return None
mapped = [
PhotovoltaicArray(
peak_power=array.peak_power,
pitch=array.pitch if array.pitch is not None else 0,
overshading=array.overshading if array.overshading is not None else 0,
orientation=_pv_orientation(array.orientation),
)
for array in arrays
if array.peak_power is not None
]
return mapped or None
def _sap_17_1_meter_type(electricity_tariff: Optional[int]) -> str:
"""Translate a full-SAP ``energy_tariff`` code into the RdSAP ``meter_type``
value the calculator's Table 12a tariff resolver consumes.