Aggregate regional bathymetry partitions
This commit is contained in:
@@ -106,6 +106,56 @@ def test_current_vector_map_result_uses_authoritative_selection_export(monkeypat
|
||||
assert captured["limit"] == 1000
|
||||
|
||||
|
||||
def test_partitioned_vector_map_result_uses_governed_partition_export(monkeypatch) -> None:
|
||||
project_id = uuid4()
|
||||
dataset_id = uuid4()
|
||||
dataset = Dataset(
|
||||
id=dataset_id,
|
||||
project_id=project_id,
|
||||
name="vha-municipality.geojson",
|
||||
dataset_type="vector",
|
||||
source="VHA",
|
||||
source_name="vmm_vha_bathymetry_profiles",
|
||||
status="ready",
|
||||
)
|
||||
db = FakeSession({(Dataset, dataset_id): dataset})
|
||||
expected = ExportCreateResponse(
|
||||
export_id=uuid4(),
|
||||
path="storage/exports/bathymetry-profile-selection.geojson",
|
||||
status="ready",
|
||||
export_type="partitioned_vector_selection_geojson",
|
||||
)
|
||||
captured: dict = {}
|
||||
|
||||
def fake_partition_export(*args, **kwargs):
|
||||
captured["dataset"] = args[1]
|
||||
captured.update(kwargs)
|
||||
return expected
|
||||
|
||||
monkeypatch.setattr(
|
||||
ExportService,
|
||||
"export_partitioned_vector_selection_geojson",
|
||||
fake_partition_export,
|
||||
)
|
||||
response = ExportService.export_map_result(
|
||||
db,
|
||||
MapResultExportRequest(
|
||||
project_id=project_id,
|
||||
mode="current",
|
||||
dataset_id=dataset_id,
|
||||
bbox=bbox_payload(),
|
||||
partitioned=True,
|
||||
partition_scope_key="flanders",
|
||||
theme_id="bathymetry",
|
||||
),
|
||||
)
|
||||
|
||||
assert response is expected
|
||||
assert captured["dataset"] is dataset
|
||||
assert captured["partition_scope_key"] == "flanders"
|
||||
assert captured["limit"] == 1000
|
||||
|
||||
|
||||
def test_raster_map_result_is_recomputed_and_persisted(tmp_path, monkeypatch) -> None:
|
||||
project_id = uuid4()
|
||||
dataset_id = uuid4()
|
||||
|
||||
@@ -10,7 +10,9 @@ from urllib.error import URLError
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
from geoalchemy2.shape import from_shape
|
||||
import pytest
|
||||
from shapely.geometry import MultiPolygon, Polygon
|
||||
|
||||
from app.core.config import Settings
|
||||
from app.core.errors import AppError
|
||||
@@ -20,6 +22,7 @@ from app.models import Area, Dataset, DatasetVersion, Project
|
||||
from app.schemas.bathymetry import BathymetryPartitionFinalizeRequest
|
||||
from app.services.bathymetry_profile_acquisition_service import BathymetryProfileAcquisitionService
|
||||
from app.services.mdk_bathymetry_probe_service import MdkBathymetryProbeService
|
||||
from app.services.vector_feature_service import VectorFeatureService
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
@@ -247,6 +250,117 @@ def test_partition_finalization_requires_complete_area_accounting_and_updates_ve
|
||||
assert exc_info.value.code == "BATHYMETRY_PARTITION_MANIFEST_INCOMPLETE"
|
||||
|
||||
|
||||
def test_partition_selection_uses_latest_complete_manifest_without_duplicates() -> None:
|
||||
project_id = uuid4()
|
||||
source_name = BathymetryProfileAcquisitionService.PROVIDER
|
||||
|
||||
def partition(area_id, manifest, observed_at, data_partition_count):
|
||||
return Dataset(
|
||||
id=uuid4(),
|
||||
project_id=project_id,
|
||||
area_id=area_id,
|
||||
name="vha.geojson",
|
||||
dataset_type="vector",
|
||||
source="VHA",
|
||||
source_name=source_name,
|
||||
source_metadata={
|
||||
"regional_partitions_complete": True,
|
||||
"partition_scope_key": "flanders",
|
||||
"partition_manifest_sha256": manifest,
|
||||
"partition_manifest_observed_at": observed_at,
|
||||
"data_partition_count": data_partition_count,
|
||||
},
|
||||
status="ready",
|
||||
)
|
||||
|
||||
old = [partition(uuid4(), "a" * 64, "2026-07-16T00:00:00+00:00", 1)]
|
||||
new_area_ids = [uuid4(), uuid4()]
|
||||
new = [
|
||||
partition(area_id, "b" * 64, "2026-07-17T00:00:00+00:00", 2)
|
||||
for area_id in new_area_ids
|
||||
]
|
||||
incomplete = [partition(uuid4(), "c" * 64, "2026-07-18T00:00:00+00:00", 2)]
|
||||
|
||||
selected = VectorFeatureService._latest_complete_partition_manifest(
|
||||
[*old, *new, *incomplete],
|
||||
source_name=source_name,
|
||||
partition_scope_key="flanders",
|
||||
)
|
||||
|
||||
assert {dataset.area_id for dataset in selected} == set(new_area_ids)
|
||||
assert all(dataset.source_metadata["partition_manifest_sha256"] == "b" * 64 for dataset in selected)
|
||||
|
||||
|
||||
def test_partition_selection_route_uses_exact_municipality_and_canonical_envelope(monkeypatch) -> None:
|
||||
project_id, area_id, dataset_id = uuid4(), uuid4(), uuid4()
|
||||
area_geometry = MultiPolygon(
|
||||
[
|
||||
Polygon(
|
||||
[
|
||||
(5.0, 51.0),
|
||||
(5.2, 51.0),
|
||||
(5.2, 51.2),
|
||||
(5.0, 51.2),
|
||||
(5.0, 51.0),
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
area = Area(
|
||||
id=area_id,
|
||||
project_id=project_id,
|
||||
name="Gemeente Mol - officiele grens",
|
||||
geometry=from_shape(area_geometry, srid=4326),
|
||||
)
|
||||
db = SimpleNamespace(get=lambda model, row_id: area if model is Area and row_id == area_id else None)
|
||||
captured = {}
|
||||
|
||||
def select_partitions(_db, **kwargs):
|
||||
captured.update(kwargs)
|
||||
return {
|
||||
"selection_bbox": kwargs["bbox"],
|
||||
"selection_area_id": area_id,
|
||||
"feature_count": 1,
|
||||
"total_feature_count": 1,
|
||||
"limit": kwargs["limit"],
|
||||
"truncated": False,
|
||||
"geojson": {"type": "FeatureCollection", "features": []},
|
||||
"partition_count": 1,
|
||||
"available_partition_count": 269,
|
||||
"partition_scope_key": "flanders",
|
||||
"source_name": BathymetryProfileAcquisitionService.PROVIDER,
|
||||
"dataset_ids": [dataset_id],
|
||||
}
|
||||
|
||||
monkeypatch.setattr(VectorFeatureService, "select_partitioned_features_by_bbox", select_partitions)
|
||||
app.dependency_overrides[get_db] = lambda: db
|
||||
try:
|
||||
response = TestClient(app).post(
|
||||
f"/api/v1/projects/{project_id}/datasets/bathymetry/profiles/partitions/select",
|
||||
json={
|
||||
"bbox": {
|
||||
"min_x": 5.0,
|
||||
"min_y": 51.0,
|
||||
"max_x": 5.2,
|
||||
"max_y": 51.2,
|
||||
"crs": "EPSG:4326",
|
||||
},
|
||||
"area_id": str(area_id),
|
||||
"limit": 1000,
|
||||
},
|
||||
)
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
assert response.status_code == 200
|
||||
assert set(response.json()) == {"data"}
|
||||
assert response.json()["data"]["partition_count"] == 1
|
||||
assert response.json()["data"]["available_partition_count"] == 269
|
||||
assert captured["partition_area_id"] == area_id
|
||||
assert captured["source_name"] == BathymetryProfileAcquisitionService.PROVIDER
|
||||
assert captured["partition_scope_key"] == "flanders"
|
||||
|
||||
|
||||
def test_flanders_scope_discovery_uses_complete_unique_vrbg_inventory() -> None:
|
||||
features = [
|
||||
{
|
||||
@@ -333,3 +447,22 @@ def test_frontend_labels_flanders_scope_without_kempen_mislabeling() -> None:
|
||||
assert "'Grens Vlaanderen'" in dataset_display
|
||||
assert "coverageScope === 'flanders' && layer === 'municipality_boundaries'" in dataset_display
|
||||
assert "'Gemeentegrenzen Vlaanderen'" in dataset_display
|
||||
|
||||
|
||||
def test_frontend_uses_partitioned_bathymetry_selection_for_regional_scope() -> None:
|
||||
map_workspace = (
|
||||
ROOT / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx"
|
||||
).read_text(encoding="utf-8")
|
||||
theme_hook = (
|
||||
ROOT / "frontend" / "src" / "hooks" / "useMapThemeSelectionInsights.ts"
|
||||
).read_text(encoding="utf-8")
|
||||
dataset_api = (
|
||||
ROOT / "frontend" / "src" / "services" / "api" / "datasets.ts"
|
||||
).read_text(encoding="utf-8")
|
||||
|
||||
assert "isPartitionedBathymetry" in map_workspace
|
||||
assert "regionalPartitionedThemeActive" in map_workspace
|
||||
assert "datasetAvailabilityLabel(dataset, partitions)" in map_workspace
|
||||
assert "activeSelectionResult?.geojson ?? null" in map_workspace
|
||||
assert "selectBathymetryProfilePartitions" in theme_hook
|
||||
assert "datasets/bathymetry/profiles/partitions/select" in dataset_api
|
||||
|
||||
Reference in New Issue
Block a user