use axum::Extension; use axum::extract::{FromRef, Json, Path, Query, State}; 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::patient_dto::{ CreatePatientReq, FamilyMemberReq, FamilyMemberResp, ManageTagsReq, PatientResp, UpdatePatientReq, }; use crate::service::patient_service; use crate::state::HealthState; #[derive(Debug, Deserialize, IntoParams)] pub struct PatientListParams { pub page: Option, pub page_size: Option, pub search: Option, pub tag_id: Option, } /// 分配医生请求 #[derive(Debug, serde::Deserialize, utoipa::ToSchema)] pub struct AssignDoctorReq { pub doctor_id: Uuid, pub relationship_type: Option, } #[derive(Debug, serde::Deserialize, utoipa::ToSchema)] pub struct DeleteWithVersion { pub version: i32, } pub async fn list_patients( State(state): State, Extension(ctx): Extension, Query(params): Query, ) -> Result>>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.list")?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(20); let result = patient_service::list_patients( &state, ctx.tenant_id, page, page_size, params.search, params.tag_id, ) .await?; Ok(Json(ApiResponse::ok(result))) } pub async fn create_patient( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; let result = patient_service::create_patient( &state, ctx.tenant_id, Some(ctx.user_id), req, ) .await?; Ok(Json(ApiResponse::ok(result))) } pub async fn get_patient( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.list")?; let result = patient_service::get_patient(&state, ctx.tenant_id, id).await?; Ok(Json(ApiResponse::ok(result))) } pub async fn update_patient( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; let version = req.version; let update = UpdatePatientReq { name: req.name, gender: req.gender, birth_date: req.birth_date, blood_type: req.blood_type, id_number: req.id_number, allergy_history: req.allergy_history, medical_history_summary: req.medical_history_summary, emergency_contact_name: req.emergency_contact_name, emergency_contact_phone: req.emergency_contact_phone, source: req.source, notes: req.notes, status: req.status, verification_status: req.verification_status, }; let result = patient_service::update_patient( &state, ctx.tenant_id, id, Some(ctx.user_id), update, version, ) .await?; Ok(Json(ApiResponse::ok(result))) } pub async fn delete_patient( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; patient_service::delete_patient(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?; Ok(Json(ApiResponse::ok(()))) } pub async fn manage_patient_tags( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; patient_service::manage_patient_tags(&state, ctx.tenant_id, id, req, Some(ctx.user_id)).await?; Ok(Json(ApiResponse::ok(()))) } pub async fn get_health_summary( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.list")?; let result = patient_service::get_health_summary(&state, ctx.tenant_id, id).await?; Ok(Json(ApiResponse::ok(result))) } pub async fn list_family_members( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.list")?; let result = patient_service::list_family_members(&state, ctx.tenant_id, id).await?; Ok(Json(ApiResponse::ok(result))) } pub async fn create_family_member( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; let result = patient_service::create_family_member( &state, ctx.tenant_id, id, Some(ctx.user_id), req, ) .await?; Ok(Json(ApiResponse::ok(result))) } pub async fn update_family_member( State(state): State, Extension(ctx): Extension, Path((_patient_id, member_id)): Path<(Uuid, Uuid)>, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; let version = req.version; let update = FamilyMemberReq { name: req.name, relationship: req.relationship, phone: req.phone, birth_date: req.birth_date, notes: req.notes, }; let result = patient_service::update_family_member( &state, ctx.tenant_id, _patient_id, member_id, Some(ctx.user_id), update, version, ) .await?; Ok(Json(ApiResponse::ok(result))) } pub async fn delete_family_member( State(state): State, Extension(ctx): Extension, Path((patient_id, member_id)): Path<(Uuid, Uuid)>, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; patient_service::delete_family_member( &state, ctx.tenant_id, patient_id, member_id, Some(ctx.user_id), req.version, ) .await?; Ok(Json(ApiResponse::ok(()))) } pub async fn assign_doctor( State(state): State, Extension(ctx): Extension, Path(id): Path, Json(req): Json, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; patient_service::assign_doctor( &state, ctx.tenant_id, id, req.doctor_id, req.relationship_type.unwrap_or_else(|| "primary".to_string()), Some(ctx.user_id), ) .await?; Ok(Json(ApiResponse::ok(()))) } pub async fn remove_doctor( State(state): State, Extension(ctx): Extension, Path((patient_id, doctor_id)): Path<(Uuid, Uuid)>, ) -> Result>, AppError> where HealthState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; patient_service::remove_doctor(&state, ctx.tenant_id, patient_id, doctor_id).await?; Ok(Json(ApiResponse::ok(()))) } // 带版本号的更新请求包装 #[derive(Debug, serde::Deserialize, utoipa::ToSchema)] pub struct UpdatePatientWithVersion { pub name: Option, pub gender: Option, pub birth_date: Option, pub blood_type: Option, pub id_number: Option, pub allergy_history: Option, pub medical_history_summary: Option, pub emergency_contact_name: Option, pub emergency_contact_phone: Option, pub source: Option, pub notes: Option, pub status: Option, pub verification_status: Option, pub version: i32, } #[derive(Debug, serde::Deserialize, utoipa::ToSchema)] pub struct FamilyMemberUpdateWithVersion { pub name: String, pub relationship: String, pub phone: Option, pub birth_date: Option, pub notes: Option, pub version: i32, }