mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Phase 1 of confirming UPRNs before finalise. address2uprn matched each row independently, so one UPRN could be the best match for two distinct addresses (a coarse EPC record absorbing several real addresses, e.g. flats in a block). Those distinct addresses were then silently merged by the property identity insert, and collided in property_overrides. resolve_group_ambiguity() withholds a UPRN claimed by >=2 distinct normalised addresses within a postcode group (keeps genuine same-address re-listings), and the handler now emits an address2uprn_status column (matched | ambiguous_duplicate | unmatched | invalid_postcode | error). Withheld rows drop to a null UPRN but keep their lexiscore for triage on the (upcoming) confirmation page. Also adds the ADR-0057 backstop dedup in property_overrides upsert_all so the ON CONFLICT statement can never double-touch a row. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class PropertyOverrideInsert:
|
|
"""One ``property_overrides`` row written at Finalise (ADR-0006).
|
|
|
|
``override_value`` is the resolved enum snapshot (a denormalised text copy
|
|
from ``landlord_*_overrides``); ``original_spreadsheet_description`` is the
|
|
raw cell entry it resolved from (un-normalized).
|
|
"""
|
|
|
|
property_id: int
|
|
portfolio_id: int
|
|
building_part: int
|
|
override_component: str
|
|
override_value: str
|
|
original_spreadsheet_description: str
|
|
|
|
|
|
class PropertyOverrideRepository(ABC):
|
|
"""Writes the per-Property fact layer (``property_overrides``).
|
|
|
|
A distinct aggregate from ``property``: own table, own write semantics —
|
|
re-run = recalculate (upsert), in contrast to ``property``'s
|
|
insert-do-nothing. One repository per aggregate (ADR-0006).
|
|
"""
|
|
|
|
@abstractmethod
|
|
def upsert_all(self, rows: list[PropertyOverrideInsert]) -> int:
|
|
"""Upsert each row on ``(property_id, override_component, building_part)``,
|
|
refreshing ``override_value`` + ``original_spreadsheet_description`` +
|
|
``updated_at`` on conflict (recalculate-on-rerun). Returns the number of
|
|
rows affected; an empty list is a no-op returning 0.
|
|
|
|
Rows sharing a conflict key within one call are collapsed to the last
|
|
occurrence (last-write-wins) before writing, so a single batch never
|
|
upserts the same target row twice (ADR-0057 backstop)."""
|
|
...
|