test(health): 扩展预约集成测试 +3 — 状态流转/取消/乐观锁冲突
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

This commit is contained in:
iven
2026-04-27 22:01:38 +08:00
parent fdbbc47a60
commit e1d9f97d79

View File

@@ -5,7 +5,7 @@
//! 预约创建依赖患者 + 医护档案 + 排班三条前置数据。
use erp_core::events::EventBus;
use erp_health::dto::appointment_dto::CreateAppointmentReq;
use erp_health::dto::appointment_dto::{CreateAppointmentReq, UpdateAppointmentStatusReq};
use erp_health::dto::doctor_dto::CreateDoctorReq;
use erp_health::dto::patient_dto::CreatePatientReq;
use erp_health::service::{
@@ -246,3 +246,149 @@ async fn test_appointment_tenant_isolation() {
"跨租户查询预约应返回错误"
);
}
// ---------------------------------------------------------------------------
// 测试 4: 预约状态流转 — pending → confirmed → completed
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_appointment_status_flow() {
let test_db = TestDb::new().await;
let state = make_state(test_db.db());
let tenant_id = uuid::Uuid::new_v4();
let operator_id = uuid::Uuid::new_v4();
let patient_id = seed_patient(&state, tenant_id, "状态患者").await;
let doctor_id = seed_doctor(&state, tenant_id, "状态医生").await;
let date = chrono::NaiveDate::from_ymd_opt(2026, 5, 15).unwrap();
seed_schedule(&state, tenant_id, doctor_id, date).await;
let appt = appointment_service::create_appointment(
&state, tenant_id, Some(operator_id),
CreateAppointmentReq {
patient_id,
doctor_id: Some(doctor_id),
appointment_type: None,
appointment_date: date,
start_time: chrono::NaiveTime::from_hms_opt(9, 0, 0).unwrap(),
end_time: chrono::NaiveTime::from_hms_opt(9, 30, 0).unwrap(),
notes: None,
},
)
.await
.expect("创建预约应成功");
assert_eq!(appt.status, "pending");
// pending → confirmed
let confirmed = appointment_service::update_appointment_status(
&state, tenant_id, appt.id, Some(operator_id),
UpdateAppointmentStatusReq { status: "confirmed".to_string(), cancel_reason: None },
appt.version,
)
.await
.expect("确认应成功");
assert_eq!(confirmed.status, "confirmed");
// confirmed → completed
let completed = appointment_service::update_appointment_status(
&state, tenant_id, appt.id, Some(operator_id),
UpdateAppointmentStatusReq { status: "completed".to_string(), cancel_reason: None },
confirmed.version,
)
.await
.expect("完成应成功");
assert_eq!(completed.status, "completed");
}
// ---------------------------------------------------------------------------
// 测试 5: 预约取消 — pending → cancelled
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_appointment_cancel() {
let test_db = TestDb::new().await;
let state = make_state(test_db.db());
let tenant_id = uuid::Uuid::new_v4();
let patient_id = seed_patient(&state, tenant_id, "取消患者").await;
let doctor_id = seed_doctor(&state, tenant_id, "取消医生").await;
let date = chrono::NaiveDate::from_ymd_opt(2026, 5, 16).unwrap();
seed_schedule(&state, tenant_id, doctor_id, date).await;
let appt = appointment_service::create_appointment(
&state, tenant_id, None,
CreateAppointmentReq {
patient_id,
doctor_id: Some(doctor_id),
appointment_type: None,
appointment_date: date,
start_time: chrono::NaiveTime::from_hms_opt(9, 0, 0).unwrap(),
end_time: chrono::NaiveTime::from_hms_opt(9, 30, 0).unwrap(),
notes: None,
},
)
.await
.expect("创建应成功");
let cancelled = appointment_service::update_appointment_status(
&state, tenant_id, appt.id, None,
UpdateAppointmentStatusReq {
status: "cancelled".to_string(),
cancel_reason: Some("患者临时有事".to_string()),
},
appt.version,
)
.await
.expect("取消应成功");
assert_eq!(cancelled.status, "cancelled");
}
// ---------------------------------------------------------------------------
// 测试 6: 预约乐观锁 — 旧版本更新拒绝
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_appointment_version_conflict() {
let test_db = TestDb::new().await;
let state = make_state(test_db.db());
let tenant_id = uuid::Uuid::new_v4();
let operator_id = uuid::Uuid::new_v4();
let patient_id = seed_patient(&state, tenant_id, "乐观锁患者").await;
let doctor_id = seed_doctor(&state, tenant_id, "乐观锁医生").await;
let date = chrono::NaiveDate::from_ymd_opt(2026, 5, 17).unwrap();
seed_schedule(&state, tenant_id, doctor_id, date).await;
let appt = appointment_service::create_appointment(
&state, tenant_id, Some(operator_id),
CreateAppointmentReq {
patient_id,
doctor_id: Some(doctor_id),
appointment_type: None,
appointment_date: date,
start_time: chrono::NaiveTime::from_hms_opt(9, 0, 0).unwrap(),
end_time: chrono::NaiveTime::from_hms_opt(9, 30, 0).unwrap(),
notes: None,
},
)
.await
.expect("创建应成功");
// 正确版本确认
let _confirmed = appointment_service::update_appointment_status(
&state, tenant_id, appt.id, Some(operator_id),
UpdateAppointmentStatusReq { status: "confirmed".to_string(), cancel_reason: None },
appt.version,
)
.await
.expect("确认应成功");
// 用旧版本再更新应失败
let result = appointment_service::update_appointment_status(
&state, tenant_id, appt.id, Some(operator_id),
UpdateAppointmentStatusReq { status: "cancelled".to_string(), cancel_reason: None },
appt.version, // 旧版本
)
.await;
assert!(result.is_err(), "旧版本更新应失败");
}