Bill room-in-roof surfaces with the surveyed roof insulation, stud-wall commons 🟩

Two dig-confirmed defects in the fresh RIR mapping (499617935574 overshot
-9): the roof-space-level insulation (Joists/200mm) was never threaded into
the RIR surfaces, so slopes/commons/flat ceilings fell to the Table 18
"unknown" full-uninsulated 2.30 default; and common walls were mislabeled
"common_wall" (a Simplified-Type-2-only concept) instead of the Detailed-mode
stud_wall every worksheet-validated fixture uses. 44.0 -> ~50.3 on the target
fixture; harness MAE 1.748 -> 1.726.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-14 22:29:20 +00:00
parent 25c3f0b2a0
commit 6f1ba4be25

View file

@ -6003,9 +6003,22 @@ def _pashub_room_in_roof(
if not roof.rooms_in_roof or rir is None:
return None
surfaces: List[SapRoomInRoofSurface] = []
# PasHub lodges roof insulation ONCE at roof-space level, not per RIR
# surface. Thread it into the roof-going surfaces (slope / stud_wall /
# flat_ceiling — Table 17) so they aren't billed at the Table 18 col(4)
# "unknown" full-uninsulated default while the same survey records an
# insulated roof. Gables keep None — they are walls, priced by wall
# fields, and their consumer branches ignore the thickness anyway.
roof_thickness = (
roof.insulation_thickness_mm
if isinstance(roof.insulation_thickness_mm, int)
else None
)
def _add(
details: Optional[List[RoomInRoofSurfaceDetail]], kind: Optional[str]
details: Optional[List[RoomInRoofSurfaceDetail]],
kind: Optional[str],
insulation_thickness_mm: Optional[int] = None,
) -> None:
for d in details or []:
if d.length_m is None or d.height_m is None:
@ -6022,13 +6035,19 @@ def _pashub_room_in_roof(
kind=surface_kind,
area_m2=d.length_m * d.height_m,
u_value=d.u_value,
insulation_thickness_mm=insulation_thickness_mm,
)
)
_add(rir.gables, None)
_add(rir.slopes, "slope")
_add(rir.common_walls, "common_wall")
_add(rir.flat_ceilings, "flat_ceiling")
_add(rir.slopes, "slope", roof_thickness)
# "Common wall" lodges as a Detailed-mode stud wall (Table 17 col 3):
# kind="common_wall" is a §3.9.2 Simplified-Type-2-only concept (different
# area formula, billed at the main-wall U); every worksheet-validated
# Detailed §3.10 fixture (000516/000487/000477/000480) uses stud_wall for
# this low internal wall.
_add(rir.common_walls, "stud_wall", roof_thickness)
_add(rir.flat_ceilings, "flat_ceiling", roof_thickness)
if rir.floor_area_m2 is None:
return None
return SapRoomInRoof(