feat(core): HealthDataProvider 新增 get_upcoming_appointments + get_medication_list
This commit is contained in:
@@ -39,6 +39,20 @@ pub trait HealthDataProvider: Send + Sync {
|
||||
metrics: &[String],
|
||||
range: &TimeRange,
|
||||
) -> AppResult<TrendAnalysisDto>;
|
||||
|
||||
/// 获取患者即将到来的预约
|
||||
async fn get_upcoming_appointments(
|
||||
&self,
|
||||
tenant_id: Uuid,
|
||||
patient_id: Uuid,
|
||||
) -> AppResult<Vec<AppointmentSummaryDto>>;
|
||||
|
||||
/// 获取患者当前用药列表
|
||||
async fn get_medication_list(
|
||||
&self,
|
||||
tenant_id: Uuid,
|
||||
patient_id: Uuid,
|
||||
) -> AppResult<Vec<MedicationSummaryDto>>;
|
||||
}
|
||||
|
||||
// === 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,
|
||||
}
|
||||
|
||||
@@ -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<Vec<AppointmentSummaryDto>> {
|
||||
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<Vec<MedicationSummaryDto>> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user