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::{CreateAlertRuleRequest, UpdateAlertRuleRequest}; use crate::service::alert_rule_service; use crate::state::HealthState; #[derive(Debug, Deserialize, IntoParams)] pub struct RuleListQuery { pub device_type: Option, pub page: Option, pub page_size: Option, } #[derive(Debug, Deserialize)] pub struct DeactivateRequest { pub version: i32, } pub async fn list_rules( State(state): State, Extension(ctx): Extension, Query(query): Query, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alert-rules.list")?; let page = query.page.unwrap_or(1); let page_size = query.page_size.unwrap_or(20); let (items, total) = alert_rule_service::list_rules( &state, ctx.tenant_id, query.device_type.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 create( State(state): State, Extension(ctx): Extension, axum::Json(mut body): axum::Json, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alert-rules.manage")?; body.sanitize(); let rule = alert_rule_service::create_rule( &state, ctx.tenant_id, ctx.user_id, body, ).await?; Ok(axum::Json(ApiResponse::ok(rule))) } pub async fn update( State(state): State, Extension(ctx): Extension, Path(id): Path, axum::Json(mut body): axum::Json, ) -> Result where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.alert-rules.manage")?; body.sanitize(); let rule = alert_rule_service::update_rule( &state, ctx.tenant_id, id, ctx.user_id, body, ).await?; Ok(axum::Json(ApiResponse::ok(rule))) } pub async fn deactivate( 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.alert-rules.manage")?; let rule = alert_rule_service::deactivate_rule( &state, ctx.tenant_id, id, body.version, ).await?; Ok(axum::Json(ApiResponse::ok(rule))) }