Prefer current orthophoto source version
This commit is contained in:
@@ -81,6 +81,21 @@ def _latest_dataset(datasets: list[Dataset]) -> Dataset:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _latest_source_version(policy: SourcePolicy, datasets: list[Dataset]) -> str | None:
|
||||||
|
versioned = [item for item in datasets if item.source_version]
|
||||||
|
if not versioned:
|
||||||
|
return None
|
||||||
|
if policy.refresh_policy == "rolling_snapshot":
|
||||||
|
named_current = [
|
||||||
|
item
|
||||||
|
for item in versioned
|
||||||
|
if any(token in (item.source_version or "").lower() for token in ("most_recent", "latest", "current"))
|
||||||
|
]
|
||||||
|
if named_current:
|
||||||
|
return _latest_dataset(named_current).source_version
|
||||||
|
return _latest_dataset(versioned).source_version
|
||||||
|
|
||||||
|
|
||||||
def _is_local_storage_path(storage_path: str) -> bool:
|
def _is_local_storage_path(storage_path: str) -> bool:
|
||||||
normalized = storage_path.strip().lower()
|
normalized = storage_path.strip().lower()
|
||||||
return bool(normalized) and "://" not in normalized and not normalized.startswith("/vsi")
|
return bool(normalized) and "://" not in normalized and not normalized.startswith("/vsi")
|
||||||
@@ -225,7 +240,6 @@ class SourceFreshnessService:
|
|||||||
next_review_at = None
|
next_review_at = None
|
||||||
reason = "Voor deze bron is nog geen expliciete publicatie- of controlecyclus vastgelegd."
|
reason = "Voor deze bron is nog geen expliciete publicatie- of controlecyclus vastgelegd."
|
||||||
recommended_action = "Classificeer de bron eerst als snapshot, jaargang, vaste editie, scenario, archief of lokaal."
|
recommended_action = "Classificeer de bron eerst als snapshot, jaargang, vaste editie, scenario, archief of lokaal."
|
||||||
latest = _latest_dataset(source_datasets)
|
|
||||||
observed_values = {value for item in source_datasets if (value := _as_utc(item.observed_at)) is not None}
|
observed_values = {value for item in source_datasets if (value := _as_utc(item.observed_at)) is not None}
|
||||||
temporal_keys = {item.temporal_series_key for item in source_datasets if item.temporal_series_key}
|
temporal_keys = {item.temporal_series_key for item in source_datasets if item.temporal_series_key}
|
||||||
items.append(
|
items.append(
|
||||||
@@ -237,21 +251,7 @@ class SourceFreshnessService:
|
|||||||
version_count=sum(len(versions_by_dataset.get(item.id, [])) for item in source_datasets),
|
version_count=sum(len(versions_by_dataset.get(item.id, [])) for item in source_datasets),
|
||||||
latest_imported_at=_latest_datetime(item.imported_at for item in source_datasets),
|
latest_imported_at=_latest_datetime(item.imported_at for item in source_datasets),
|
||||||
latest_observed_at=_latest_datetime(item.observed_at for item in source_datasets),
|
latest_observed_at=_latest_datetime(item.observed_at for item in source_datasets),
|
||||||
latest_source_version=next(
|
latest_source_version=_latest_source_version(policy, source_datasets),
|
||||||
(
|
|
||||||
item.source_version
|
|
||||||
for item in sorted(
|
|
||||||
source_datasets,
|
|
||||||
key=lambda value: (
|
|
||||||
_as_utc(value.observed_at) or datetime.min.replace(tzinfo=timezone.utc),
|
|
||||||
_as_utc(value.imported_at) or datetime.min.replace(tzinfo=timezone.utc),
|
|
||||||
),
|
|
||||||
reverse=True,
|
|
||||||
)
|
|
||||||
if item.source_version
|
|
||||||
),
|
|
||||||
latest.source_version,
|
|
||||||
),
|
|
||||||
refresh_policy=policy.refresh_policy,
|
refresh_policy=policy.refresh_policy,
|
||||||
review_interval_days=policy.review_interval_days,
|
review_interval_days=policy.review_interval_days,
|
||||||
next_review_at=next_review_at,
|
next_review_at=next_review_at,
|
||||||
|
|||||||
@@ -133,6 +133,30 @@ def test_source_freshness_requires_dataset_version_and_marks_temporal_series() -
|
|||||||
assert item.integrity.missing_version_count == 1
|
assert item.integrity.missing_version_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_rolling_orthophoto_prefers_explicit_current_snapshot_over_historical_observation() -> None:
|
||||||
|
current = _dataset(
|
||||||
|
"digitaal_vlaanderen_orthophoto",
|
||||||
|
imported_at=NOW - timedelta(days=2),
|
||||||
|
observed_at=None,
|
||||||
|
source_version="most_recent_at_2026-07-14",
|
||||||
|
)
|
||||||
|
historical = _dataset(
|
||||||
|
"digitaal_vlaanderen_orthophoto",
|
||||||
|
imported_at=NOW - timedelta(days=1),
|
||||||
|
observed_at=datetime(2020, 6, 1, tzinfo=timezone.utc),
|
||||||
|
source_version="2020",
|
||||||
|
)
|
||||||
|
|
||||||
|
report = SourceFreshnessService.build_report(
|
||||||
|
current.project_id,
|
||||||
|
[current, historical],
|
||||||
|
[_version(current), _version(historical)],
|
||||||
|
now=NOW,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert report.items[0].latest_source_version == "most_recent_at_2026-07-14"
|
||||||
|
|
||||||
|
|
||||||
def test_source_freshness_route_returns_canonical_envelope(monkeypatch) -> None:
|
def test_source_freshness_route_returns_canonical_envelope(monkeypatch) -> None:
|
||||||
from app.api.routes import datasets as dataset_routes
|
from app.api.routes import datasets as dataset_routes
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user