feat: add bulk external observation rejection

This commit is contained in:
ik
2026-09-21 20:25:51 +07:00
parent e74929e7f7
commit 21c0ffbe75
2 changed files with 29 additions and 1 deletions
+15 -1
View File
@@ -20,7 +20,7 @@ from rf4_research.media_assets import publish_quality_upgrades, rollback_quality
from ..media_catalog import MEDIA_ROOT, review_assets, review_file
from ..models import CatchReport, CommunityImportRun, DataSource, ExternalObservation, Fish, ModerationEvent, ModerationStatus, OfficialRecordImport, SourceType, Waterbody
from ..public_cache import public_cache
from ..schemas import AdminCatchReportOut, AdminMediaDecision, AdminMediaReviewOut, AdminMediaRollback, AdminModerationHistoryOut, AdminSourceStatusOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationBulkResult, ModerationBulkUpdate, ModerationUpdate
from ..schemas import AdminCatchReportOut, AdminMediaDecision, AdminMediaReviewOut, AdminMediaRollback, AdminModerationHistoryOut, AdminSourceStatusOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationBulkDecision, ExternalObservationBulkResult, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationBulkResult, ModerationBulkUpdate, ModerationUpdate
from ..storage import delete_screenshot, signed_screenshot_url
from ..time_utils import aware
@@ -378,6 +378,20 @@ def admin_reject_external_observation(
raise HTTPException(status_code=409, detail=str(exc)) from exc
@router.patch("/api/v1/admin/external-observations/bulk-reject", response_model=ExternalObservationBulkResult)
def admin_reject_external_observations_bulk(payload: ExternalObservationBulkDecision, db: Db, _: Annotated[str, Depends(_admin)]) -> ExternalObservationBulkResult:
ids = [item.id for item in payload.items]
observations = list(db.scalars(select(ExternalObservation).where(ExternalObservation.id.in_(ids)).with_for_update()))
by_id = {item.id: item for item in observations}
expected = {item.id: item.expected_version for item in payload.items}
if len(by_id) != len(ids) or any(item.status in {"published", "rejected", "withdrawn"} or item.moderation_version != expected[item.id] for item in observations):
raise HTTPException(status_code=409, detail="one or more observations changed; reload the queue")
for item in observations:
item.moderation_version += 1
reject_observation(db, item, reason=payload.reason)
return ExternalObservationBulkResult(updated=len(observations))
@router.get("/api/v1/admin/catch-reports", response_model=list[AdminCatchReportOut])
def admin_reports(db: Db, _: Annotated[str, Depends(_admin)], status: ModerationStatus = ModerationStatus.pending, limit: int = Query(50, ge=1, le=100), offset: int = Query(0, ge=0)) -> list[AdminCatchReportOut]:
reports = list(db.scalars(select(CatchReport).options(joinedload(CatchReport.fish), joinedload(CatchReport.waterbody), joinedload(CatchReport.spot), joinedload(CatchReport.bait)).where(CatchReport.source_type == SourceType.user, CatchReport.moderation_status == status, CatchReport.deleted_at.is_(None)).order_by(CatchReport.reported_at, CatchReport.id).offset(offset).limit(limit)))