功能修复: 1. 患者创建空名称验证:后端添加 name.trim().is_empty() 检查 2. 仪表盘统计容错:单个查询失败返回零值而非 500 3. FHIR 路由修复:从 /fhir 移到 /api/v1/fhir 保持一致 4. 冻结模块后端中间件:新增 frozen_module_middleware 拦截冻结路径 5. 积分端点权限码:health.health-data.list → health.points.list 6. 角色权限迁移:护士补充 devices.list,运营补充 points.list/manage 7. 测试结果文档:R01-R05 角色测试 + T00/T10 结果归档 Clippy 全 workspace 清零(14→0 errors): - erp-core: 修复 empty doc line、collapsible if、redundant closure 等 9 处 - erp-health: 修复 too_many_arguments、unused var、unnecessary parens 等 58 处 - erp-ai: 修复 dead_code、unused import 等 11 处 - erp-plugin: 修复 too_many_arguments、wildcard pattern 等 11 处 - erp-server-migration: 修复 enum_variant_names 5 处 - erp-auth/config/workflow/message: 各 1-3 处 工程改进: - lint-staged 配置迁移到 .lintstagedrc.js(函数式避免文件列表传给 clippy) - cargo fmt 统一格式化
205 lines
6.5 KiB
Rust
205 lines
6.5 KiB
Rust
//! erp-health 日常监测集成测试
|
||
//!
|
||
//! 验证日常监测 CRUD(委托 vital_signs)、列表按患者过滤、租户隔离。
|
||
|
||
use erp_health::dto::daily_monitoring_dto::*;
|
||
use erp_health::service::daily_monitoring_service;
|
||
|
||
use super::test_fixture::TestApp;
|
||
|
||
fn default_create_req(patient_id: uuid::Uuid) -> CreateDailyMonitoringReq {
|
||
CreateDailyMonitoringReq {
|
||
patient_id,
|
||
record_date: chrono::NaiveDate::from_ymd_opt(2026, 5, 1).unwrap(),
|
||
morning_bp_systolic: Some(125),
|
||
morning_bp_diastolic: Some(82),
|
||
evening_bp_systolic: None,
|
||
evening_bp_diastolic: None,
|
||
weight: Some(68.5),
|
||
blood_sugar: Some(5.2),
|
||
fluid_intake: Some(2000),
|
||
urine_output: Some(1500),
|
||
notes: Some("状态良好".to_string()),
|
||
}
|
||
}
|
||
|
||
async fn seed_monitoring(app: &TestApp, patient_id: uuid::Uuid) -> DailyMonitoringResp {
|
||
daily_monitoring_service::create_daily_monitoring(
|
||
app.health_state(),
|
||
app.tenant_id(),
|
||
Some(app.operator_id()),
|
||
default_create_req(patient_id),
|
||
)
|
||
.await
|
||
.expect("创建日常监测应成功")
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 1: 创建日常监测
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_create() {
|
||
let app = TestApp::new().await;
|
||
let patient_id = app.create_patient("监测患者").await;
|
||
|
||
let dm = seed_monitoring(&app, patient_id).await;
|
||
|
||
assert_eq!(dm.patient_id, patient_id);
|
||
assert_eq!(dm.morning_bp_systolic, Some(125));
|
||
assert_eq!(dm.weight, Some(68.5));
|
||
assert_eq!(dm.version, 1);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 2: 查询日常监测
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_get() {
|
||
let app = TestApp::new().await;
|
||
let patient_id = app.create_patient("监测查询患者").await;
|
||
let dm = seed_monitoring(&app, patient_id).await;
|
||
|
||
let fetched =
|
||
daily_monitoring_service::get_daily_monitoring(app.health_state(), app.tenant_id(), dm.id)
|
||
.await
|
||
.expect("查询应成功");
|
||
assert_eq!(fetched.id, dm.id);
|
||
assert_eq!(fetched.blood_sugar, Some(5.2));
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 3: 更新日常监测
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_update() {
|
||
let app = TestApp::new().await;
|
||
let patient_id = app.create_patient("监测更新患者").await;
|
||
let dm = seed_monitoring(&app, patient_id).await;
|
||
|
||
let updated = daily_monitoring_service::update_daily_monitoring(
|
||
app.health_state(),
|
||
app.tenant_id(),
|
||
dm.id,
|
||
Some(app.operator_id()),
|
||
UpdateDailyMonitoringReq {
|
||
weight: Some(67.0),
|
||
blood_sugar: None,
|
||
morning_bp_systolic: None,
|
||
morning_bp_diastolic: None,
|
||
evening_bp_systolic: Some(118),
|
||
evening_bp_diastolic: Some(76),
|
||
fluid_intake: None,
|
||
urine_output: None,
|
||
notes: None,
|
||
record_date: None,
|
||
},
|
||
dm.version,
|
||
)
|
||
.await
|
||
.expect("更新应成功");
|
||
|
||
assert_eq!(updated.weight, Some(67.0));
|
||
assert_eq!(updated.evening_bp_systolic, Some(118));
|
||
assert_eq!(updated.version, 2);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 4: 列表按患者过滤
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_list_by_patient() {
|
||
let app = TestApp::new().await;
|
||
let patient_a = app.create_patient("监测列表A").await;
|
||
let patient_b = app.create_patient("监测列表B").await;
|
||
|
||
seed_monitoring(&app, patient_a).await;
|
||
seed_monitoring(&app, patient_b).await;
|
||
|
||
let list_a = daily_monitoring_service::list_daily_monitoring(
|
||
app.health_state(),
|
||
app.tenant_id(),
|
||
patient_a,
|
||
1,
|
||
20,
|
||
)
|
||
.await
|
||
.unwrap();
|
||
assert_eq!(list_a.total, 1);
|
||
|
||
let list_b = daily_monitoring_service::list_daily_monitoring(
|
||
app.health_state(),
|
||
app.tenant_id(),
|
||
patient_b,
|
||
1,
|
||
20,
|
||
)
|
||
.await
|
||
.unwrap();
|
||
assert_eq!(list_b.total, 1);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 5: 软删除
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_soft_delete() {
|
||
let app = TestApp::new().await;
|
||
let patient_id = app.create_patient("监测删除患者").await;
|
||
let dm = seed_monitoring(&app, patient_id).await;
|
||
|
||
daily_monitoring_service::delete_daily_monitoring(
|
||
app.health_state(),
|
||
app.tenant_id(),
|
||
dm.id,
|
||
Some(app.operator_id()),
|
||
dm.version,
|
||
)
|
||
.await
|
||
.expect("删除应成功");
|
||
|
||
let result =
|
||
daily_monitoring_service::get_daily_monitoring(app.health_state(), app.tenant_id(), dm.id)
|
||
.await;
|
||
assert!(result.is_err(), "软删除后查询应失败");
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 6: 租户隔离
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_tenant_isolation() {
|
||
let app = TestApp::new().await;
|
||
let patient_id = app.create_patient("监测隔离患者").await;
|
||
seed_monitoring(&app, patient_id).await;
|
||
|
||
let other_tenant = uuid::Uuid::new_v4();
|
||
let list = daily_monitoring_service::list_daily_monitoring(
|
||
app.health_state(),
|
||
other_tenant,
|
||
patient_id,
|
||
1,
|
||
20,
|
||
)
|
||
.await
|
||
.unwrap();
|
||
assert_eq!(list.total, 0, "不同租户不应看到日常监测");
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 测试 7: 无效患者创建返回错误
|
||
// ---------------------------------------------------------------------------
|
||
#[tokio::test]
|
||
async fn test_daily_monitoring_invalid_patient() {
|
||
let app = TestApp::new().await;
|
||
let fake_patient = uuid::Uuid::new_v4();
|
||
|
||
let result = daily_monitoring_service::create_daily_monitoring(
|
||
app.health_state(),
|
||
app.tenant_id(),
|
||
None,
|
||
default_create_req(fake_patient),
|
||
)
|
||
.await;
|
||
assert!(result.is_err(), "无效患者应返回错误");
|
||
}
|