use axum::Json; use axum::Router; use axum::extract::State; use axum::routing::post; use holzleitner_application::dto::{ApplyScansRequest, ApplyScansResponse}; use crate::error::ApiError; use crate::extractors::AuthenticatedUser; use crate::state::AppState; pub fn router() -> Router { Router::new().route("/scans", post(apply_scans)) } /// Wendet eine Liste von Scan-Events idempotent an. /// /// Pro Event ein eigenes Resultat. Status `applied` schreibt einen /// frischen Audit-Eintrag, `duplicate` liefert den aktuellen Stand am /// Server, `rejected` enthält die Begründung. Reihenfolge der `results` /// entspricht der Reihenfolge der `scans` im Request. #[utoipa::path( post, path = "/scans", tag = "scans", request_body = ApplyScansRequest, responses( (status = 200, description = "Bulk-Ergebnis pro Event", body = ApplyScansResponse), (status = 401, description = "Authentifizierung fehlgeschlagen") ), security( ("bearer_auth" = []) ) )] pub async fn apply_scans( State(state): State, AuthenticatedUser(claims): AuthenticatedUser, Json(request): Json, ) -> Result, ApiError> { tracing::info!( actor = claims.personalnummer, count = request.scans.len(), "apply_scans", ); let response = state .apply_scans .execute(request, claims.personalnummer) .await?; Ok(Json(response)) }