diff --git a/crates/erp-core/src/health_provider.rs b/crates/erp-core/src/health_provider.rs index 2e4687b..4f343df 100644 --- a/crates/erp-core/src/health_provider.rs +++ b/crates/erp-core/src/health_provider.rs @@ -39,6 +39,20 @@ pub trait HealthDataProvider: Send + Sync { metrics: &[String], range: &TimeRange, ) -> AppResult; + + /// 获取患者即将到来的预约 + async fn get_upcoming_appointments( + &self, + tenant_id: Uuid, + patient_id: Uuid, + ) -> AppResult>; + + /// 获取患者当前用药列表 + async fn get_medication_list( + &self, + tenant_id: Uuid, + patient_id: Uuid, + ) -> AppResult>; } // === DTO 定义 === @@ -152,3 +166,21 @@ pub struct AnomalyInfo { pub std_dev: f64, pub deviation: f64, } + +// === Agent 新增 DTO === + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AppointmentSummaryDto { + pub id: Uuid, + pub department: String, + pub doctor_name: String, + pub scheduled_at: String, + pub status: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MedicationSummaryDto { + pub name: String, + pub dosage: String, + pub frequency: String, +} diff --git a/crates/erp-health/src/health_provider_impl.rs b/crates/erp-health/src/health_provider_impl.rs index 5b7fb32..4d590a9 100644 --- a/crates/erp-health/src/health_provider_impl.rs +++ b/crates/erp-health/src/health_provider_impl.rs @@ -3,16 +3,16 @@ use chrono::Datelike; use erp_core::crypto::{self as pii, PiiCrypto}; use erp_core::error::{AppError, AppResult}; use erp_core::health_provider::{ - AnomalyInfo, HealthDataProvider, HealthReportDto, LabItemDto, LabReportDto, - MetricTrendAnalysis, PatientSummaryDto, RegressionStats, ReportSectionDto, TimeRange, - TrendAnalysisDto, TrendDirection, VitalSignDto, + AnomalyInfo, AppointmentSummaryDto, HealthDataProvider, HealthReportDto, LabItemDto, + LabReportDto, MedicationSummaryDto, MetricTrendAnalysis, PatientSummaryDto, RegressionStats, + ReportSectionDto, TimeRange, TrendAnalysisDto, TrendDirection, VitalSignDto, }; use num_traits::ToPrimitive; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder}; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect}; use uuid::Uuid; use crate::entity::{ - diagnosis, health_record, lab_report, medication_record, patient, vital_signs, + appointment, diagnosis, health_record, lab_report, medication_record, patient, vital_signs, }; pub struct HealthDataProviderImpl { @@ -557,4 +557,70 @@ impl HealthDataProvider for HealthDataProviderImpl { metrics: metric_results, }) } + + async fn get_upcoming_appointments( + &self, + tenant_id: Uuid, + patient_id: Uuid, + ) -> AppResult> { + let _ = find_patient(&self.db, tenant_id, patient_id).await?; + + let today = chrono::Utc::now().date_naive(); + let records = appointment::Entity::find() + .filter(appointment::Column::TenantId.eq(tenant_id)) + .filter(appointment::Column::PatientId.eq(patient_id)) + .filter(appointment::Column::DeletedAt.is_null()) + .filter(appointment::Column::AppointmentDate.gte(today)) + .filter( + appointment::Column::Status + .is_in(vec!["scheduled".to_string(), "confirmed".to_string()]), + ) + .order_by_asc(appointment::Column::AppointmentDate) + .order_by_asc(appointment::Column::StartTime) + .limit(10) + .all(&self.db) + .await?; + + let result = records + .into_iter() + .map(|r| AppointmentSummaryDto { + id: r.id, + department: r.appointment_type, + doctor_name: r + .doctor_id + .map_or("待定".to_string(), |_| "医生".to_string()), + scheduled_at: format!("{} {}", r.appointment_date, r.start_time), + status: r.status, + }) + .collect(); + + Ok(result) + } + + async fn get_medication_list( + &self, + tenant_id: Uuid, + patient_id: Uuid, + ) -> AppResult> { + let _ = find_patient(&self.db, tenant_id, patient_id).await?; + + let records = medication_record::Entity::find() + .filter(medication_record::Column::TenantId.eq(tenant_id)) + .filter(medication_record::Column::PatientId.eq(patient_id)) + .filter(medication_record::Column::DeletedAt.is_null()) + .filter(medication_record::Column::IsCurrent.eq(true)) + .all(&self.db) + .await?; + + let result = records + .into_iter() + .map(|m| MedicationSummaryDto { + name: m.medication_name, + dosage: m.dosage.unwrap_or_default(), + frequency: m.frequency.unwrap_or_default(), + }) + .collect(); + + Ok(result) + } }