feat: add external observation review queue
This commit is contained in:
@@ -4,13 +4,14 @@ from datetime import datetime, timedelta, timezone
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import create_engine, select
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.pool import StaticPool
|
||||
|
||||
from app.database import Base, get_session
|
||||
from app.community_importer import stage_observations
|
||||
from app.main import app
|
||||
from app.models import Bait, BaitKind, CatchReport, Fish, ImportStatus, ModerationEvent, ModerationStatus, OfficialRecordImport, SourceType, Spot, Waterbody
|
||||
from app.models import Bait, BaitKind, CatchReport, ExternalEntityAlias, ExternalObservation, Fish, ImportStatus, ModerationEvent, ModerationStatus, OfficialRecordImport, SourceType, Spot, Waterbody
|
||||
|
||||
|
||||
engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool)
|
||||
@@ -89,6 +90,66 @@ def test_admin_requires_token() -> None:
|
||||
assert client.get("/api/v1/admin/catch-reports").status_code == 401
|
||||
assert client.get("/api/v1/admin/imports").status_code == 401
|
||||
assert client.post("/api/v1/admin/imports/official-records").status_code == 401
|
||||
assert client.get("/api/v1/admin/external-observations").status_code == 401
|
||||
|
||||
|
||||
def test_external_observation_requires_mapping_and_complete_data_before_publication() -> None:
|
||||
with Session(engine) as db:
|
||||
stage_observations(db, [{
|
||||
"source_system": "rf4db", "source_external_id": "review-complete",
|
||||
"source_url": "https://rf4db.com/catches/review-complete", "fish": "Pike external",
|
||||
"fish_external_id": "fish-1", "waterbody": "Lake external",
|
||||
"waterbody_external_id": "lake-1", "x": 31, "y": 41, "weight_g": 6200,
|
||||
"bait": "Тестовая приманка", "player_name": "External Player",
|
||||
}])
|
||||
observation_id = db.scalar(select(ExternalObservation.id).where(
|
||||
ExternalObservation.source_external_id == "review-complete"
|
||||
))
|
||||
headers = {"Authorization": "Bearer change-me-in-production"}
|
||||
premature = client.post(f"/api/v1/admin/external-observations/{observation_id}/publish", headers=headers)
|
||||
assert premature.status_code == 409
|
||||
mapped = client.patch(
|
||||
f"/api/v1/admin/external-observations/{observation_id}/mapping", headers=headers,
|
||||
json={"fish_slug": "pike", "waterbody_slug": "test-lake", "note": "verified fixture"},
|
||||
)
|
||||
assert mapped.status_code == 200
|
||||
assert mapped.json()["status"] == "ready"
|
||||
published = client.post(f"/api/v1/admin/external-observations/{observation_id}/publish", headers=headers)
|
||||
assert published.status_code == 200
|
||||
assert published.json()["status"] == "published"
|
||||
repeated = client.post(f"/api/v1/admin/external-observations/{observation_id}/publish", headers=headers)
|
||||
assert repeated.json()["catch_report_id"] == published.json()["catch_report_id"]
|
||||
with Session(engine) as db:
|
||||
observation = db.get(ExternalObservation, observation_id)
|
||||
report = db.get(CatchReport, observation.catch_report_id)
|
||||
aliases = list(db.scalars(select(ExternalEntityAlias).where(ExternalEntityAlias.source_system == "rf4db")))
|
||||
assert report.moderation_status == ModerationStatus.approved
|
||||
assert report.raw_payload["provenance"]["source_external_id"] == "review-complete"
|
||||
assert {alias.entity_type for alias in aliases} == {"fish", "waterbody"}
|
||||
|
||||
|
||||
def test_incomplete_external_observation_stays_out_of_public_data() -> None:
|
||||
with Session(engine) as db:
|
||||
stage_observations(db, [{
|
||||
"source_system": "rf4db", "source_external_id": "review-incomplete",
|
||||
"source_url": "https://rf4db.com/catches/review-incomplete", "fish": "Pike external",
|
||||
"waterbody": "Lake external", "x": 32, "y": 42,
|
||||
}])
|
||||
observation_id = db.scalar(select(ExternalObservation.id).where(
|
||||
ExternalObservation.source_external_id == "review-incomplete"
|
||||
))
|
||||
headers = {"Authorization": "Bearer change-me-in-production"}
|
||||
mapped = client.patch(
|
||||
f"/api/v1/admin/external-observations/{observation_id}/mapping", headers=headers,
|
||||
json={"fish_slug": "pike", "waterbody_slug": "test-lake"},
|
||||
)
|
||||
assert mapped.json()["status"] == "mapped"
|
||||
assert client.post(f"/api/v1/admin/external-observations/{observation_id}/publish", headers=headers).status_code == 409
|
||||
rejected = client.patch(
|
||||
f"/api/v1/admin/external-observations/{observation_id}/reject", headers=headers,
|
||||
json={"reason": "weight is absent"},
|
||||
)
|
||||
assert rejected.json()["status"] == "rejected"
|
||||
|
||||
|
||||
def test_admin_can_start_and_list_official_import(monkeypatch) -> None:
|
||||
|
||||
Reference in New Issue
Block a user