Model/backend/documents_parser
Khalim Conn-Kowlessar 598f04084a Slice 50: Summary_000480 chain pins SAP at 1e-4; Room-in-Roof + baths + party-wall + roof-none
Four mapper extensions, validated by 000480 closing to 1e-4 and large
gap reductions across 000477/000487/000516.

1. Room-in-Roof support. `ElmhurstSiteNotes` gains `RoomInRoof` +
   `RoomInRoofSurface` dataclasses; extractor parses §8.1 (Flat
   Ceiling / Stud Wall / Slope / Gable Wall / Common Wall) with
   Length × Height + insulation + gable-type + measured-U cells.
   Mapper produces a `SapRoomInRoof` with `detailed_surfaces`
   attached to the Main bp: Stud Walls / Slopes / Flat Ceilings
   route through Table 17 insulation thickness; Gable Walls split
   between `gable_wall` (Party → Table 4 U=0.25) and
   `gable_wall_external` (Sheltered → assessor-lodged U-value
   override, e.g. 000487 Gable Wall 2 at U=0.86). Empty surfaces
   (0×0 — the cohort lodges a full 5-pair table) and Common Walls
   (handled by cascade's Simplified Type 2 geometry) are dropped.
   `total_floor_area_m2` now includes the RR floor area.

2. Party-wall construction mapping. 000516 lodges "S Solid masonry /
   timber / system build" which routes to SAP10 wall_construction=3
   (Solid Brick → U=0.0 via Table 4). The previous mapper used the
   same wall-type table as `wall_construction`, which lacked the
   "S" code and fell through to None (cascade default 0.25). Split
   into a dedicated `_elmhurst_party_wall_construction_int` keyed
   on the party-wall category codes.

3. Roof "None" insulation. When the §8.0 Roofs subsection lodges
   "Insulation N None" without a separate "Insulation Thickness"
   line, treat thickness as 0 mm so the cascade picks Table 16
   row 0 (U=2.30) rather than the age-band default. Closes the
   29 W/K roof-loss gap on 000516.

4. `number_baths` lodgement. `SapHeating.number_baths` now reads
   `survey.baths_and_showers.number_of_baths`. The cascade defaults
   `None → has-bath` for the modal UK case, but explicit `0` lodged
   on 000477/000480 (bathless dwellings, rare) drops the bath HW
   demand line per Table 1b. Closes 000480's last ~0.3 SAP gap.

Cohort state after this slice (target 1e-4):

  000474   0.0000  ✓ Slice 47
  000477  +1.1161     Elmhurst floor_ach quirk (true vs false despite
                      "T Suspended timber" lodged on all certs)
  000480   0.0000  ✓ THIS SLICE
  000487  +1.1844     extractor still drops most §11 windows on this
                      layout variant
  000490   0.0000  ✓ Slice 49
  000516  +0.1774     roof-window separation by U-value heuristic

3/6 certs now closed at 1e-4. Pyright net-zero (35 baseline). Tests
756 pass (added `test_summary_000480_full_chain_sap_matches_worksheet_
pdf_exactly`).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 21:09:22 +00:00
..
handler address JTK review comments 2026-04-20 15:11:17 +00:00
tests Slice 50: Summary_000480 chain pins SAP at 1e-4; Room-in-Roof + baths + party-wall + roof-none 2026-05-24 21:09:22 +00:00
__init__.py Map to RdSapSiteNotes from site notes JSON 🟥 2026-04-16 13:54:03 +00:00
db_writer.py include updating epc_property_data to pashub to ara workflow 2026-04-29 09:55:14 +00:00
elmhurst_extractor.py Slice 50: Summary_000480 chain pins SAP at 1e-4; Room-in-Roof + baths + party-wall + roof-none 2026-05-24 21:09:22 +00:00
extractor.py Handle wall thickness "Unmeasurable" 🟩 2026-04-30 16:41:16 +00:00
local_runner.py update local runner to work for elmhurst 2026-04-24 14:01:36 +00:00
parser.py load ecmk site notes to db 2026-04-29 11:20:47 +00:00
pdf.py update local runner to work for elmhurst 2026-04-24 14:01:36 +00:00