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],
|
metrics: &[String],
|
||||||
range: &TimeRange,
|
range: &TimeRange,
|
||||||
) -> AppResult<TrendAnalysisDto>;
|
) -> 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 定义 ===
|
// === DTO 定义 ===
|
||||||
@@ -152,3 +166,21 @@ pub struct AnomalyInfo {
|
|||||||
pub std_dev: f64,
|
pub std_dev: f64,
|
||||||
pub deviation: 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::crypto::{self as pii, PiiCrypto};
|
||||||
use erp_core::error::{AppError, AppResult};
|
use erp_core::error::{AppError, AppResult};
|
||||||
use erp_core::health_provider::{
|
use erp_core::health_provider::{
|
||||||
AnomalyInfo, HealthDataProvider, HealthReportDto, LabItemDto, LabReportDto,
|
AnomalyInfo, AppointmentSummaryDto, HealthDataProvider, HealthReportDto, LabItemDto,
|
||||||
MetricTrendAnalysis, PatientSummaryDto, RegressionStats, ReportSectionDto, TimeRange,
|
LabReportDto, MedicationSummaryDto, MetricTrendAnalysis, PatientSummaryDto, RegressionStats,
|
||||||
TrendAnalysisDto, TrendDirection, VitalSignDto,
|
ReportSectionDto, TimeRange, TrendAnalysisDto, TrendDirection, VitalSignDto,
|
||||||
};
|
};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder};
|
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::entity::{
|
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 {
|
pub struct HealthDataProviderImpl {
|
||||||
@@ -557,4 +557,70 @@ impl HealthDataProvider for HealthDataProviderImpl {
|
|||||||
metrics: metric_results,
|
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