Model/datatypes
Khalim Conn-Kowlessar ca39d072be Slices 66+67: Elmhurst mapper surfaces country_code + heating ints + has_draught_lobby
Closes 9 mapper-side load-bearing field gaps surfaced by the cohort
000474 mapper-vs-hand-built diff (was 12, now 5 remaining):

**Slice 66 — country code + draught-lobby fix:**
- Set `country_code="ENG"` in `from_elmhurst_site_notes`. The Elmhurst
  U985 / P960 surveyor toolchain operates on English certs only; the
  Summary doesn't lodge country explicitly but the cascade's `u_floor`
  / `u_basement_floor` / `u_door` read it for table selection. Cohort
  hand-builts already encode 'ENG' so the cascade was tolerating the
  None default; matching the canonical value closes the diff.
- `_map_elmhurst_ventilation` now sets `has_draught_lobby=True` only
  when Summary lodges "Yes"/"Present". The cohort's modal lodgement
  "Unable to determine" maps to `False` — matching the cohort hand-
  built convention (conservative no-lobby cascade path). The legacy
  `draught_lobby` field is unchanged; the cascade reads
  `has_draught_lobby` in preference.

**Slice 67 — heating field surfacing:**
- `boiler_flue_type`: Add `_ELMHURST_FLUE_TYPE_TO_SAP10` map (Open=1,
  Balanced=2, Fan-assisted balanced=3, Room-sealed=4). Cohort 000474's
  "Balanced" Summary §14 lodgement → 2, matching hand-built.
- `emitter_temperature`: `_elmhurst_emitter_temperature_int` parses
  the Summary §14 "Design flow temperature" string to int (≥45 °C →
  1, lower → 0; "Unknown" defaults to 1 per Table 4d worst-case).
- `central_heating_pump_age`: dual-encode int alongside the existing
  `_str` field via `_elmhurst_pump_age_int` (Unknown → 0, Pre 2013 →
  1, otherwise → 2). The cascade reads `_str`; the int is for cross-
  mapper field parity only.
- `main_heating_number=1`: default single main heating.
- `water_heating_fuel`: parse Summary §15 "Water Heating Fuel Type"
  via the existing `_elmhurst_main_fuel_int` map. Cohort 000474's
  "Mains gas" → 26.

All 11 newly-surfaced fields are metadata-only on the SAP cascade
(grep confirms none feature in `packages/domain/src/domain/sap/`
outside test fixtures). All 66 cohort cascade pins remain GREEN at
1e-4. Pyright 35-error baseline preserved on mapper.py.

Diff count for cohort 000474:
  Slice 63 baseline: 50
  Slice 64 (Cat A bulk):    14
  Slice 65 (HW handbuilt):  12
  Slice 66 (country+lobby): 10
  Slice 67 (heating ints):  **5**

Remaining 5 diffs:
- 3× `sap_building_parts[*].party_wall_construction`: None vs 0
  (cohort sentinel convention — needs mapper-side fix to surface 0
  when no party wall is lodged, OR hand-built update to drop sentinel)
- `sap_heating.main_heating_details[0].central_heating_pump_age_str`:
  mapped='Unknown' vs handbuilt=None (hand-built should populate the
  str dual)
- `sap_windows: LEN 7 vs 5` (Cat C structural — cohort hand-built
  collapsed by glazing-type group, mapper extracts 1:1 with §11 table)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 16:59:34 +00:00
..
epc Slices 66+67: Elmhurst mapper surfaces country_code + heating ints + has_draught_lobby 2026-05-25 16:59:34 +00:00
magicplan typing and renaming 🟪 2026-05-07 13:26:49 +00:00
__init__.py further breaking up code 2023-07-20 12:24:34 +01:00
datatypes.py further breaking up code 2023-07-20 12:24:34 +01:00
enums.py completed build of new demo portfolio - some fixed required still 2023-11-20 14:42:16 +00:00