Commit graph

778 commits

Author SHA1 Message Date
Jun-te Kim
80ccec9b68 added floats helper 2026-06-12 14:28:41 +00:00
Jun-te Kim
ff4a2e4242
Merge pull request #1198 from Hestia-Homes/feature/bill-derivation
Feature/bill derivation
2026-06-12 14:44:30 +01:00
Daniel Roth
26d34c345c get last_submission_date from hubspot 2026-06-10 14:45:25 +00:00
Daniel Roth
5178cd02c5 UploadedFile, FileTypeEnum, FileSourceEnum importable from infrastructure.postgres.uploaded_file_table 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 11:50:51 +00:00
Jun-te Kim
0ccb0e0bf9
Merge pull request #1196 from Hestia-Homes/feautre/additional_properties_for_tracking
Feautre/additional properties for tracking
2026-06-08 16:19:34 +01:00
Jun-te Kim
a1b4bf4e98 added 4 deal proeprties 2026-06-08 14:42:06 +00:00
Khalim Conn-Kowlessar
24492aa4ba Merge origin/main into feature/bill-derivation (calculator + mapper fixes)
Pulls in 42 commits of calculator/mapper accuracy fixes from the per-cert
mapper-validation and floor/roof/heating fronts.

Conflict resolutions:
- mapper `_is_elmhurst_roof_window`: main dropped the branch's "wall location →
  vertical" guard (it broke cert 000516's rooflight), but that re-broke cert
  001431's two External-wall U>3.0 windows (which must stay vertical). The two
  certs lodge a BYTE-IDENTICAL §11 row, so neither location nor U separates
  them — the real discriminator is the room-in-roof context. Replaced the
  unconditional U>3.0 backstop with one gated on the BP having a room-in-roof
  (`_elmhurst_bp_has_room_in_roof`): 000516's Main BP has a "Room in roof type
  1" (→ rooflight), 001431's does not (→ vertical). Validated against BOTH —
  full Elmhurst worksheet suite 1038 pass + the 001431 window-extraction pin.
- property_postgres_repository: kept main's `ids_by_uprn` method + the branch's
  `_restrictions_of` helper.
- sap_fuel.py: the branch relocated it to domain/billing/ (already carrying
  main's to_table_32_code normalization), so kept the old path deleted.

Fallout from main's fabric fixes (validated by the boiler-3 real-cert pin which
still reproduces at delta 0):
- re-pinned the boiler-1 + boiler-instant-hw ASHP snapshot scores;
- main's §14.2 gas-boiler main-fuel derivation resolved the BGB/102 baseline
  gap, so `test_gas_boiler_instant_hw_before_baselines` is now a passing test
  (was an xfail tripwire).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 13:12:21 +00:00
Daniel Roth
41a40c9ba0 Fix Pylance unknowns in SQLModel table tests and correct pytest paths 2026-06-08 09:56:54 +00:00
Daniel Roth
198d2afdb1 Merge branch 'main' into feature/handle-new-magicplan-response-structure 2026-06-05 14:35:56 +00:00
Daniel Roth
b3b4ae2191 Convert Door.width_mm to store actual millimetres (multiply size.x by 1000)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 13:30:54 +00:00
Jun-te Kim
b07db1ef6b property override 2026-06-05 12:18:13 +00:00
Khalim Conn-Kowlessar
2c36a8e1d6 Merge remote-tracking branch 'origin/main' into feature/bill-derivation
# Conflicts:
#	repositories/property/property_postgres_repository.py
#	tests/orchestration/fakes.py
2026-06-05 11:09:00 +00:00
Daniel Roth
ebd6f1623f Merge branch 'main' into feature/handle-new-magicplan-response-structure 2026-06-05 10:16:14 +00:00
Daniel Roth
761962e991 add ECO_SHAREPOINT_ID env var 2026-06-04 15:40:26 +00:00
Daniel Roth
6bcb695771 rename mcs_certificate to mcs_compliance_certificate to match existing db enum value 2026-06-04 15:40:26 +00:00
Daniel Roth
1af1d4a82c MCS cert identified by evidence_category in get_core_file_type 🟥 2026-06-04 15:40:25 +00:00
Daniel Roth
098f60ecfd Upload other files to S3 when get_other_files is True 🟥 2026-06-04 15:40:25 +00:00
Jun-te Kim
384e3da92a
Merge pull request #1172 from Hestia-Homes/feature/landlord_data
Feature/landlord data
2026-06-04 16:14:39 +01:00
Jun-te Kim
dfd05ba28b tests files 2026-06-04 11:47:42 +00:00
Daniel Roth
df0c8f69b1 Merge branch 'main' into feature/handle-new-magicplan-response-structure 2026-06-04 10:52:32 +00:00
Daniel Roth
eb72b0223f add ECO_SHAREPOINT_ID env var 2026-06-04 09:11:08 +00:00
Khalim Conn-Kowlessar
6f0dcc0455 test(modelling): characterise the portfolio aggregation over plan_id
Pin the FE-facing aggregate_portfolio_recommendations (previously untested): it
sums a Scenario's default Recommendations onto the Scenario row, joining
Recommendation → Plan on recommendation.plan_id. Locks the m2m→plan_id read cut
for the FE-critical path, now testable thanks to the full-parity ScenarioModel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 22:54:15 +00:00
Khalim Conn-Kowlessar
c18968ba3c refactor(modelling): consolidate scenario + installed_measure into the subpackage
Move the scenario and installed_measure tables into
infrastructure/postgres/modelling/ as full-parity SQLModel definitions
(ScenarioModel, InstalledMeasureModel + MeasureType), completing the cluster
consolidation. backend/app/db/models/recommendations.py is now a pure
re-export shim.

ScenarioModel.goal is the PortfolioGoal enum (legacy planning branches on it),
sourced from domain/modelling/portfolio_goal.py; the repo's to_domain maps it to
its value string, so domain Scenario.goal is now the value ("Increasing EPC")
consistent with the orchestrator's check — fixing the latent name-vs-value
inconsistency the old str column masked (the scenario repo test stored the enum
*name*). Parity columns are nullable (mirror convention; live NOT-NULLs owned by
Drizzle).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 22:52:35 +00:00
Khalim Conn-Kowlessar
2fbd7147b7 refactor(modelling): move PortfolioGoal to domain/modelling/
PortfolioGoal is domain vocabulary (a Scenario's goal — legacy planning branches
on PortfolioGoal.INCREASING_EPC), so it belongs in domain/ co-located with
scenario.py, mirroring how domain/epc/wall_type.py holds an enum that
infrastructure/ imports. This lets the consolidated ScenarioModel (next slice)
source the goal enum from domain without an infra→backend dependency.
portfolio.py keeps a re-export so every existing
`from ...portfolio import PortfolioGoal` caller is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 22:44:48 +00:00
Khalim Conn-Kowlessar
01c2c3910e refactor(modelling): rename the cluster SQLModel classes …Row → …Model
Standardise the modelling persistence classes on the …Model suffix (PlanModel,
RecommendationModel, RecommendationMaterialModel) — matching the epc_property
precedent and the legacy names the rest of backend/ already imports, so the
shim's plan re-export becomes literal (no alias) and the eventual shim deletion
needs zero renames. The …Row→…Model sweep for the non-cluster tables
(Property/Task/Material/…) waits until their live legacy …Model counterparts
are retired, to avoid reintroducing dual-definition collisions. No behaviour
change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 22:42:21 +00:00
Khalim Conn-Kowlessar
b97d06882f feat(modelling): drop the plan_recommendations m2m
Stop writing the m2m (remove create_plan_recommendations + its call, the bulk
link insert and the now-dead plan_ids_by_index, and the plan_recommendations
delete in delete_property_batch) and remove the PlanRecommendationRow model +
its shim alias and the test_export fixture inserts. Measures now link to their
Plan solely via recommendation.plan_id (writers set it, readers join on it).

The live drop of the plan_recommendations table is the FE-owned Drizzle
migration documented in docs/migrations/recommendation-plan-id.md, sequenced
after the read-cut + backfill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 21:13:00 +00:00
Khalim Conn-Kowlessar
af5dbe325d feat(modelling): cut plan→recommendation readers onto plan_id
Rewrite the three structurally-identical m2m-join readers
(portfolio_functions.aggregate_portfolio_recommendations,
Outputs.get_recommendations_from_db, export get_recommendations) to join
PlanModel directly via recommendation.plan_id, dropping the plan_recommendations
join and its now-unused import. The writers set plan_id (prior slice), so the
rows resolve. test_export pins the export reader through the cut (its fixtures
now set recommendation.plan_id). A portfolio_functions DB characterization test
lands with the scenario consolidation (which provides the full-parity scenario
table the aggregation writes to).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 21:09:43 +00:00
Khalim Conn-Kowlessar
27fcc5b184 feat(modelling): legacy writers set recommendation.plan_id (dual-write)
upload_recommendations and bulk_upload_recommendations_and_materials now set
plan_id on each recommendation row (the plan id is already in scope), while
still writing the plan_recommendations m2m — the dual-write that lets readers
move onto plan_id with no breakage during the transition (ADR-0017 amendment /
docs/migrations/recommendation-plan-id.md). The m2m write is removed in a later
slice once no reader depends on it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 21:01:56 +00:00
Khalim Conn-Kowlessar
c1c7b06f09 refactor(modelling): consolidate plan/recommendation models into infrastructure
Move the live plan, recommendation, recommendation_materials and (retiring)
plan_recommendations tables into a new infrastructure/postgres/modelling/
subpackage as single SQLModel definitions (the epc_property pattern), absorbing
the rebuild's partial PlanRow/RecommendationRow mirrors and carrying full
legacy column parity plus recommendation.plan_id. Out-of-cluster references are
plain indexed ints (mirror convention); the live FKs are owned by the Drizzle
schema. backend/app/db/models/recommendations.py becomes a re-export shim
(ScenarioModel/InstalledMeasure stay for a later slice).

Fix the export conftest to create SQLModel-first (so Base funding_package's FK
to the now-SQLModel plan resolves) and skip the redundant drop_all on its
function-scoped throwaway DB (the epc enum type is now shared across both
metadatas). Resolves the pre-existing dual-definition collision: the rebuild
and legacy export suites are now co-runnable. No behaviour change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 21:00:14 +00:00
Daniel Roth
174ef26075 refactor magicplan in ddd structure 2026-06-03 17:20:20 +00:00
Daniel Roth
19e40ff049 rename mcs_certificate to mcs_compliance_certificate to match existing db enum value 2026-06-03 09:00:01 +00:00
Daniel Roth
ca224515f9 MCS cert identified by evidence_category in get_core_file_type 🟥 2026-06-02 14:20:35 +00:00
Daniel Roth
1a1f9f2e6a Upload other files to S3 when get_other_files is True 🟥 2026-06-02 09:35:12 +00:00
Khalim Conn-Kowlessar
559616d3bb feat(epc): EPC persistence round-trip fidelity + JSONB code columns (Slice 1 #1129)
Relocate EpcPropertyModel + child tables from the dying backend/ tree to
infrastructure/postgres/epc_property_table.py (re-export shim keeps
documents_parser working). Add EpcRepository port + EpcPostgresRepository with
a full reverse mapper (epc_property tables -> EpcPropertyData).

Round-trip test surfaced two fidelity gaps:
 1. Union[int,str] SAP code fields were str()-coerced on save, losing the int
    (API) vs str (Site Notes) distinction. Now stored as JSONB (type-preserving).
 2. The schema was a partial projection. Closed the cheap gaps on the model
    (heating shower/bath counts, roof_construction_type, curtain_wall_age,
    addendum, mechanical_vent_duct_insulation_level, SAP 10.2 §2 ventilation
    fields + a ventilation_present flag). Structural gaps tracked as follow-ups;
    renewable_heat_incentive (P0, #1137) excluded from the assertion until landed.

Round-trip passes for RdSAP-Schema-21.0.0 and 21.0.1; pyright strict clean.
Migration inventory for the DB: docs/migrations/epc-property-round-trip-fidelity.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 16:28:48 +00:00
Jun-te Kim
d5ac70947d booking status 2026-06-01 16:28:47 +00:00
Jun-te Kim
b72a0c2be4 hubspot projects data is scraped 2026-06-01 16:28:47 +00:00
Jun-te Kim
99614820b9 made landlord overrides sqs 2026-05-29 10:41:46 +00:00
Jun-te Kim
0a99c92eb4 added batch description and nonfunded measures 2026-05-27 10:30:19 +00:00
Khalim Conn-Kowlessar
87b6045c97 fixed merge conflicts from main 2026-05-26 11:21:09 +00:00
Khalim Conn-Kowlessar
883028c89e P6.1 follow-on: unbox BuildingPartIdentifier at backend boundaries
Threads the strict BuildingPartIdentifier type (introduced in a8b443f6)
through the two remaining backend touchpoints:

- EpcBuildingPartModel.from_*: SQLModel column expects a string, so
  unbox the enum with .identifier.value before binding to the DB.
- documents_parser end-to-end tests: swap bare-string equality
  ("main" / "extension_1") for identity checks against the enum
  members (BuildingPartIdentifier.MAIN / EXTENSION_1).

Documents_parser test pack passes (105/105). No dedicated SQLModel test
covers EpcBuildingPartModel.from_*; the .value line is exercised
transitively via db_writer.py / local_runner.py in production.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 09:58:23 +00:00
Daniel Roth
dc3543ac5f Coordination Hub fallback stores correct file_source in DB 🟥 2026-05-19 11:07:41 +00:00
Daniel Roth
4cd59768c3 Wire coordination account fallback into config and handler, remove token-refresh retry 🟩 2026-05-18 09:22:32 +00:00
Khalim Conn-Kowlessar
0ffda529ec slice 15a: add wall/floor/roof + demand scalar features for retrofit simulation
15 new features wired through schema -> domain -> mapper -> transform:

Main Dwelling fabric (11):
  - wall_insulation_type, wall_insulation_thickness_mm, wall_dry_lined,
    wall_thickness_mm, party_wall_construction
  - roof_insulation_location, roof_insulation_thickness_mm
  - floor_construction, floor_insulation, floor_insulation_thickness_mm,
    floor_heat_loss

Dwelling-level scalars (4):
  - multiple_glazed_proportion, number_baths, number_baths_wwhrs,
    extract_fans_count

Thickness strings like '50mm'/'NI'/'ND' parsed via _parse_thickness_mm; NI
(no insulation) lands as 0mm so the model sees the physical zero rather than
a missing value. Categorical sentinels ('NA'/'NI'/'ND') become None.

Also fixed long-standing typo `multiple_glazed_propertion` -> `_proportion`
in domain dataclass + its lone DB-model usage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 22:08:27 +00:00
Daniel Roth
c98fc8452f
Merge pull request #1086 from Hestia-Homes/feature/pashub-additional-files
Fetch coordination and design documents from pashub
2026-05-14 11:59:43 +01:00
Daniel Roth
cc6b64ee2b
Merge pull request #1080 from Hestia-Homes/feature/magicplan_uploaded_file_id
Include uploaded file ID on MagicPlan plan
2026-05-14 10:23:33 +01:00
Daniel Roth
5ff740d192 Merge branch 'main' into feature/pashub-additional-files 2026-05-13 15:27:04 +00:00
Jun-te Kim
27b5602608 remove pandas 2026-05-13 15:08:06 +00:00
Jun-te Kim
51460d1cd3 route at th ebeginnign 2026-05-13 14:47:24 +00:00
Jun-te Kim
54864bf102 resolve merge conflict 2026-05-13 14:22:04 +00:00
Daniel Roth
e315966565 add coordination and design document types to enums 2026-05-13 12:29:25 +00:00