mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Pins behavior delivered with the tracer slice (the group key is (landlord_property_id, document_type)) — no red phase; discriminating: a global-by-type dedupe would drop one property's file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
"""The Download Package plan (ADR-0060) — pure layout of the ZIP from resolved
|
|
documents: one folder per property, latest file of each Document Type,
|
|
null-Document-Type rows skipped and reported."""
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
|
|
from domain.bulk_document_download.package_plan import (
|
|
ResolvedDocument,
|
|
plan_download_package,
|
|
)
|
|
|
|
|
|
def _doc(
|
|
*,
|
|
landlord_property_id: str = "LP1",
|
|
address: str = "12 Oak Street",
|
|
document_type: Optional[str] = "site_note",
|
|
s3_key: str = "a.pdf",
|
|
uploaded_at: datetime = datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
) -> ResolvedDocument:
|
|
return ResolvedDocument(
|
|
landlord_property_id=landlord_property_id,
|
|
address=address,
|
|
document_type=document_type,
|
|
s3_bucket="src-bucket",
|
|
s3_key=s3_key,
|
|
uploaded_at=uploaded_at,
|
|
)
|
|
|
|
|
|
def test_keeps_only_the_latest_file_of_a_document_type_in_the_property_folder() -> None:
|
|
# Arrange — two site_note files for the same property, uploaded at
|
|
# different times; only the newest should be packaged.
|
|
older = _doc(
|
|
s3_key="old.pdf", uploaded_at=datetime(2026, 1, 1, tzinfo=timezone.utc)
|
|
)
|
|
newer = _doc(
|
|
s3_key="new.pdf", uploaded_at=datetime(2026, 6, 1, tzinfo=timezone.utc)
|
|
)
|
|
|
|
# Act
|
|
plan = plan_download_package([older, newer])
|
|
|
|
# Assert — one entry, the newer file, foldered under the property.
|
|
assert len(plan.entries) == 1
|
|
entry = plan.entries[0]
|
|
assert entry.s3_key == "new.pdf"
|
|
assert entry.zip_path.startswith("12 Oak Street (LP1)/")
|
|
|
|
|
|
def test_skips_and_reports_a_document_with_no_document_type() -> None:
|
|
# Arrange — one packable file and one row whose Document Type is null
|
|
# (file_type is nullable on uploaded_files).
|
|
packable = _doc(document_type="site_note", s3_key="note.pdf")
|
|
untyped = _doc(document_type=None, s3_key="mystery.bin")
|
|
|
|
# Act
|
|
plan = plan_download_package([packable, untyped])
|
|
|
|
# Assert — the untyped row is left out of the archive and reported instead.
|
|
assert [e.s3_key for e in plan.entries] == ["note.pdf"]
|
|
assert len(plan.skipped) == 1
|
|
skipped = plan.skipped[0]
|
|
assert skipped.s3_key == "mystery.bin"
|
|
assert skipped.landlord_property_id == "LP1"
|
|
|
|
|
|
def test_packaged_filename_is_the_document_type_with_the_original_extension() -> None:
|
|
# Arrange — a photo pack stored under a prefixed key with a .zip extension;
|
|
# the file inside the archive should be named by type but stay openable.
|
|
doc = _doc(document_type="photo_pack", s3_key="surveys/2026/pack.zip")
|
|
|
|
# Act
|
|
plan = plan_download_package([doc])
|
|
|
|
# Assert
|
|
assert plan.entries[0].zip_path == "12 Oak Street (LP1)/photo_pack.zip"
|
|
|
|
|
|
def test_latest_per_type_is_scoped_per_property_each_gets_its_own_folder() -> None:
|
|
# Arrange — two DIFFERENT properties, each with a site_note. Latest-per-type
|
|
# must not dedupe across properties: both survive, in their own folders.
|
|
first = _doc(landlord_property_id="LP1", address="12 Oak Street", s3_key="a.pdf")
|
|
second = _doc(landlord_property_id="LP2", address="9 Elm Road", s3_key="b.pdf")
|
|
|
|
# Act
|
|
plan = plan_download_package([first, second])
|
|
|
|
# Assert
|
|
assert {e.zip_path for e in plan.entries} == {
|
|
"12 Oak Street (LP1)/site_note.pdf",
|
|
"9 Elm Road (LP2)/site_note.pdf",
|
|
}
|