use axum::extract::{FromRef, Path, Query, State}; use axum::response::IntoResponse; use axum::Extension; use serde::Deserialize; use utoipa::IntoParams; use uuid::Uuid; use erp_core::error::AppError; use erp_core::rbac::require_permission; use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext}; use crate::dto::alert_dto::AcknowledgeAlertRequest; use crate::service::alert_service; use crate::state::HealthState; #[derive(Debug, Deserialize, IntoParams)] pub struct AlertListQuery { pub patient_id: Option, pub doctor_id: Option, pub status: Option, pub page: Option, pub page_size: Option, } pub async fn list_alerts( State(state): State, Extension(ctx): Extension, Query(query): Query, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alerts.list")?; let page = query.page.unwrap_or(1); let page_size = query.page_size.unwrap_or(20); let (items, total) = alert_service::list_alerts( &state, ctx.tenant_id, query.patient_id, query.doctor_id, query.status.as_deref(), page, page_size, ).await?; Ok(axum::Json(ApiResponse::ok(PaginatedResponse { data: items, total, page, page_size, total_pages: total.div_ceil(page_size.max(1)), }))) } pub async fn acknowledge( State(state): State, Extension(ctx): Extension, Path(id): Path, axum::Json(body): axum::Json, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alerts.manage")?; let alert = alert_service::acknowledge_alert( &state, ctx.tenant_id, id, ctx.user_id, body.version, ).await?; Ok(axum::Json(ApiResponse::ok(alert))) } pub async fn dismiss( State(state): State, Extension(ctx): Extension, Path(id): Path, axum::Json(body): axum::Json, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alerts.manage")?; let alert = alert_service::dismiss_alert( &state, ctx.tenant_id, id, ctx.user_id, body.version, ).await?; Ok(axum::Json(ApiResponse::ok(alert))) } pub async fn resolve( State(state): State, Extension(ctx): Extension, Path(id): Path, axum::Json(body): axum::Json, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alerts.manage")?; let alert = alert_service::resolve_alert( &state, ctx.tenant_id, id, body.version, ).await?; Ok(axum::Json(ApiResponse::ok(alert))) }