from dataclasses import dataclass from typing import List from domain.condition.records.calico.calico_property import CalicoProperty @dataclass(frozen=True) class LoadReport: """The reconciliation a Calico load emits so nothing vanishes silently (ADR-0064): how many observations were loaded versus dropped, and why. ``loaded``, ``unmatched_to_portfolio`` and ``blank_placeholder`` account for the Calico rows. ``null_uprn`` is a portfolio-wide data-quality canary — the count of properties in the portfolio whose UPRN is null (expected: zero) — *not* a per-row drop reason, so it does not partition with the others: a Calico reference pointing at a null-UPRN property is reported both here and under ``unmatched_to_portfolio``. """ loaded: int unmatched_to_portfolio: int null_uprn: int blank_placeholder: int @classmethod def from_calico_load( cls, properties: List[CalicoProperty], blank_placeholder_count: int, unmatched_reference_count: int, null_uprn_references: List[str], ) -> "LoadReport": loaded = sum(len(prop.assets) for prop in properties) return cls( loaded=loaded, unmatched_to_portfolio=unmatched_reference_count, null_uprn=len(null_uprn_references), blank_placeholder=blank_placeholder_count, )