feat: add bulk external observation publishing

This commit is contained in:
ik
2026-09-21 20:33:50 +07:00
parent 8e84f41924
commit bed156ae94
3 changed files with 34 additions and 3 deletions
+5 -2
View File
@@ -75,7 +75,9 @@ def reject_observation(
return observation
def publish_observation(session: Session, observation: ExternalObservation) -> CatchReport:
def publish_observation(
session: Session, observation: ExternalObservation, *, commit: bool = True,
) -> CatchReport:
if observation.catch_report is not None and observation.status == "published":
return observation.catch_report
if observation.status == "rejected":
@@ -138,7 +140,8 @@ def publish_observation(session: Session, observation: ExternalObservation) -> C
observation.catch_report = report
observation.status = "published"
observation.reviewed_at = now
session.commit()
if commit:
session.commit()
return report
+25 -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, ExternalObservationBulkDecision, ExternalObservationBulkMapping, ExternalObservationBulkResult, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationBulkResult, ModerationBulkUpdate, ModerationUpdate
from ..schemas import AdminCatchReportOut, AdminMediaDecision, AdminMediaReviewOut, AdminMediaRollback, AdminModerationHistoryOut, AdminSourceStatusOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationBulkAction, ExternalObservationBulkDecision, ExternalObservationBulkMapping, ExternalObservationBulkResult, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationBulkResult, ModerationBulkUpdate, ModerationUpdate
from ..storage import delete_screenshot, signed_screenshot_url
from ..time_utils import aware
@@ -389,6 +389,30 @@ def admin_publish_external_observation(
return ExternalObservationPublished(observation_id=observation.id, catch_report_id=report.id, status=observation.status)
@router.post("/api/v1/admin/external-observations/bulk-publish", response_model=ExternalObservationBulkResult)
def admin_publish_external_observations_bulk(
payload: ExternalObservationBulkAction, 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()))
expected = {item.id: item.expected_version for item in payload.items}
if len({item.id for item in observations}) != len(ids) or any(
item.status in {"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")
try:
for item in observations:
item.moderation_version += 1
publish_observation(db, item, commit=False)
db.commit()
except ExternalReviewError as exc:
db.rollback()
raise HTTPException(status_code=409, detail=str(exc)) from exc
public_cache.invalidate()
return ExternalObservationBulkResult(updated=len(observations))
@router.patch("/api/v1/admin/external-observations/{observation_id}/reject", response_model=ExternalObservationOut)
def admin_reject_external_observation(
observation_id: UUID, payload: ExternalObservationDecision, db: Db,
+4
View File
@@ -413,6 +413,10 @@ class ExternalObservationBulkDecision(BaseModel):
items: list[ExternalObservationBulkItem] = Field(min_length=1, max_length=50)
class ExternalObservationBulkAction(BaseModel):
items: list[ExternalObservationBulkItem] = Field(min_length=1, max_length=50)
class ExternalObservationBulkMapping(BaseModel):
fish_slug: str
waterbody_slug: str