mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Calico Asset References don't match our landlord_property_id, so the runner now resolves UPRNs from the address-matched CSV (UprnLookupS3) uploaded to S3, not the property-table PropertyUprnLookup. run_calico_load accepts any UprnLookup (null_uprn count applies only to the property-table lookup). Adds a dry_run option to reconcile without writing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
"""One-off runner for the Calico stock-condition (roof-covering) load.
|
|
|
|
Calico is a bulk one-off import, not a recurring feed, so it runs through this
|
|
runner rather than the SQS-Lambda path Peabody/LBWF use (ADR-0064). The raw
|
|
export and the Asset-Reference->UPRN lookup both live in S3.
|
|
|
|
Not exercised by the unit suite -- it is S3 + Postgres wiring around the
|
|
unit-tested ``run_calico_load``; run it where a database and S3 are available.
|
|
|
|
Calico Asset References do not match our stored ``landlord_property_id``, so the
|
|
UPRN is resolved from an address-matched CSV lookup (built against portfolio 824
|
|
and uploaded to S3), not the property table. Pass ``dry_run=True`` to reconcile
|
|
without writing.
|
|
"""
|
|
|
|
from io import BytesIO
|
|
from typing import List
|
|
|
|
from applications.condition.calico_load import run_calico_load
|
|
from applications.condition.load_report import LoadReport
|
|
from domain.condition.property_condition_survey import PropertyConditionSurvey
|
|
from infrastructure.condition.lookups.uprn_lookup_s3 import UprnLookupS3
|
|
from repositories.condition.condition_postgres import ConditionPostgres
|
|
from utils.logger import setup_logger
|
|
from utils.s3 import read_io_from_s3
|
|
|
|
logger = setup_logger()
|
|
|
|
# The export date the Calico file was generated (Roof Covering 2.6.26); anchors
|
|
# renewal years so they don't drift on re-run (ADR-0064).
|
|
CALICO_EXPORT_YEAR = 2026
|
|
CALICO_BUCKET = "condition-data-dev"
|
|
CALICO_KEY = "input/calico/Roof Covering 2.6.26.xlsx"
|
|
CALICO_UPRN_LOOKUP_KEY = "input/calico/uprn-lookup/calico_reference_to_uprn.csv"
|
|
|
|
|
|
class _NoOpWriter:
|
|
"""Discards surveys -- used for a dry run so the load can be reconciled
|
|
without touching the database."""
|
|
|
|
def bulk_insert_surveys(
|
|
self, surveys: List[PropertyConditionSurvey]
|
|
) -> None:
|
|
logger.info(f"[calico_runner] dry run -- would persist {len(surveys)} surveys")
|
|
|
|
|
|
def run_calico_s3_load(
|
|
bucket: str = CALICO_BUCKET,
|
|
key: str = CALICO_KEY,
|
|
uprn_lookup_key: str = CALICO_UPRN_LOOKUP_KEY,
|
|
export_year: int = CALICO_EXPORT_YEAR,
|
|
dry_run: bool = False,
|
|
) -> LoadReport:
|
|
file_bytes: BytesIO = read_io_from_s3(bucket_name=bucket, file_key=key)
|
|
lookup = UprnLookupS3(bucket=bucket, key=uprn_lookup_key)
|
|
writer = _NoOpWriter() if dry_run else ConditionPostgres()
|
|
|
|
report = run_calico_load(
|
|
file_stream=file_bytes,
|
|
uprn_lookup=lookup,
|
|
export_year=export_year,
|
|
writer=writer,
|
|
)
|
|
logger.info(f"[calico_runner] {'(dry run) ' if dry_run else ''}{report}")
|
|
return report
|