test(health): 扩展预约集成测试 +3 — 状态流转/取消/乐观锁冲突
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
//! 预约创建依赖患者 + 医护档案 + 排班三条前置数据。
|
//! 预约创建依赖患者 + 医护档案 + 排班三条前置数据。
|
||||||
|
|
||||||
use erp_core::events::EventBus;
|
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::doctor_dto::CreateDoctorReq;
|
||||||
use erp_health::dto::patient_dto::CreatePatientReq;
|
use erp_health::dto::patient_dto::CreatePatientReq;
|
||||||
use erp_health::service::{
|
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(), "旧版本更新应失败");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user