Merge pull request #1451 from Hestia-Homes/fix/sap-heating-optional-air-conditioning

Make nested SapHeating.has_fixed_air_conditioning optional across all RdSAP schemas
This commit is contained in:
Jun-te Kim 2026-07-03 16:34:27 +01:00 committed by GitHub
commit 838668bfdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 29 additions and 13 deletions

View file

@ -44,7 +44,9 @@ class SapHeating:
instantaneous_wwhrs: Optional[InstantaneousWwhrs]
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (already Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
# ADR-0028: cylinder_insulation_type is absent in 308/1000 17.0 certs.
cylinder_insulation_type: Optional[int] = None
cylinder_thermostat: Optional[str] = None

View file

@ -44,7 +44,9 @@ class SapHeating:
instantaneous_wwhrs: Optional[InstantaneousWwhrs]
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (also made Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
# ADR-0028: 325/1000 omit cylinder_insulation_type — default it.
cylinder_insulation_type: Optional[int] = None
cylinder_thermostat: Optional[str] = None
@ -247,7 +249,7 @@ class RdSapSchema17_1:
hot_water_cost_potential: CostAmount
renewable_heat_incentive: RenewableHeatIncentive
energy_consumption_current: int
has_fixed_air_conditioning: str
has_fixed_air_conditioning: Optional[str] = None
multiple_glazed_proportion: int
calculation_software_version: str
energy_consumption_potential: int

View file

@ -44,7 +44,9 @@ class SapHeating:
instantaneous_wwhrs: Optional[InstantaneousWwhrs]
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (also made Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
cylinder_insulation_type: Optional[int] = None
cylinder_thermostat: Optional[str] = None
secondary_fuel_type: Optional[int] = None
@ -266,7 +268,7 @@ class RdSapSchema18_0:
hot_water_cost_potential: CostAmount
renewable_heat_incentive: RenewableHeatIncentive
energy_consumption_current: int
has_fixed_air_conditioning: str
has_fixed_air_conditioning: Optional[str] = None
multiple_glazed_proportion: int
calculation_software_version: str
energy_consumption_potential: int

View file

@ -44,7 +44,9 @@ class SapHeating:
instantaneous_wwhrs: Optional[InstantaneousWwhrs]
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (also made Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
cylinder_insulation_type: Optional[int] = None
cylinder_thermostat: Optional[str] = None
secondary_fuel_type: Optional[int] = None
@ -281,7 +283,7 @@ class RdSapSchema19_0:
# 19.0-specific block, absent in 713/1000 — Optional + default.
windows_transmission_details: Optional[WindowsTransmissionDetails] = None
energy_consumption_current: int
has_fixed_air_conditioning: str
has_fixed_air_conditioning: Optional[str] = None
multiple_glazed_proportion: int
calculation_software_version: str
energy_consumption_potential: int

View file

@ -56,7 +56,9 @@ class SapHeating:
instantaneous_wwhrs: Optional[InstantaneousWwhrs]
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (already Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
cylinder_insulation_type: Optional[int] = None
cylinder_thermostat: Optional[str] = None
secondary_fuel_type: Optional[int] = None

View file

@ -63,7 +63,9 @@ class SapHeating:
water_heating_fuel: int
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (also made Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
instantaneous_wwhrs: Optional[InstantaneousWwhrs] = None
# Real-API certs carry shower_outlets as a list, not the synthetic
# single-object form; list elements are normalised to the wrapped
@ -459,7 +461,7 @@ class RdSapSchema21_0_0:
windows_transmission_details: Optional[WindowsTransmissionDetails] = None
cfl_fixed_lighting_bulbs_count: Optional[int] = None
energy_consumption_current: int
has_fixed_air_conditioning: str
has_fixed_air_conditioning: Optional[str] = None
multiple_glazed_proportion: int
calculation_software_version: str
energy_consumption_potential: int

View file

@ -1,4 +1,4 @@
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import List, Optional, Union
from .common import DescriptionV1, Measurement
@ -64,7 +64,9 @@ class SapHeating:
water_heating_fuel: int
main_heating_details: List[MainHeatingDetail]
immersion_heating_type: Union[int, str]
has_fixed_air_conditioning: str
# Nested duplicate of the outer schema's has_fixed_air_conditioning
# (also made Optional below) — some certs omit it here too.
has_fixed_air_conditioning: Optional[str] = None
instantaneous_wwhrs: Optional[InstantaneousWwhrs] = None
# Real-API certs carry shower_outlets as a list, not the synthetic single-object form;
# accept both shapes so older fixtures keep parsing. List elements
@ -510,7 +512,9 @@ class RdSapSchema21_0_1:
renewable_heat_incentive: RenewableHeatIncentive
draughtproofed_door_count: int
energy_consumption_current: int
has_fixed_air_conditioning: str
# kw_only on just this field: the class isn't kw_only overall, and several
# required fields (calculation_software_version etc.) already follow it.
has_fixed_air_conditioning: Optional[str] = field(default=None, kw_only=True)
calculation_software_version: str
energy_consumption_potential: int
environmental_impact_current: int