"""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