//! erp-health 用药记录集成测试 //! //! 验证用药记录 CRUD、列表按患者过滤、租户隔离、乐观锁。 use erp_health::dto::medication_record_dto::*; use erp_health::service::medication_record_service; use super::test_fixture::TestApp; fn default_create_medication_req(patient_id: uuid::Uuid) -> CreateMedicationRecordReq { CreateMedicationRecordReq { patient_id, medication_name: "缬沙坦".to_string(), generic_name: Some("Valsartan".to_string()), dosage: Some("80mg".to_string()), unit: Some("mg".to_string()), frequency: Some("daily".to_string()), route: Some("oral".to_string()), start_date: chrono::NaiveDate::from_ymd_opt(2026, 1, 1), end_date: None, is_current: Some(true), prescribed_by: None, notes: None, } } async fn seed_medication(app: &TestApp, patient_id: uuid::Uuid) -> MedicationRecordResp { medication_record_service::create_medication( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_medication_req(patient_id), ) .await .expect("创建用药记录应成功") } // --------------------------------------------------------------------------- // 测试 1: 创建用药记录 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_create() { let app = TestApp::new().await; let patient_id = app.create_patient("用药患者").await; let med = seed_medication(&app, patient_id).await; assert_eq!(med.patient_id, patient_id); assert_eq!(med.medication_name, "缬沙坦"); assert_eq!(med.frequency, Some("daily".to_string())); assert!(med.is_current); assert_eq!(med.version, 1); } // --------------------------------------------------------------------------- // 测试 2: 查询用药记录 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_get() { let app = TestApp::new().await; let patient_id = app.create_patient("用药查询患者").await; let med = seed_medication(&app, patient_id).await; let fetched = medication_record_service::get_medication( app.health_state(), app.tenant_id(), med.id, ) .await .expect("查询应成功"); assert_eq!(fetched.id, med.id); assert_eq!(fetched.medication_name, "缬沙坦"); } // --------------------------------------------------------------------------- // 测试 3: 更新用药记录 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_update() { let app = TestApp::new().await; let patient_id = app.create_patient("用药更新患者").await; let med = seed_medication(&app, patient_id).await; let updated = medication_record_service::update_medication( app.health_state(), app.tenant_id(), med.id, Some(app.operator_id()), UpdateMedicationRecordReq { dosage: Some("160mg".to_string()), is_current: Some(false), medication_name: None, generic_name: None, unit: None, frequency: None, route: None, start_date: None, end_date: None, prescribed_by: None, notes: None, }, med.version, ) .await .expect("更新应成功"); assert_eq!(updated.dosage, Some("160mg".to_string())); assert!(!updated.is_current); assert_eq!(updated.version, 2); } // --------------------------------------------------------------------------- // 测试 4: 列表按患者过滤 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_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_medication(&app, patient_a).await; seed_medication(&app, patient_b).await; let list_a = medication_record_service::list_medications( app.health_state(), app.tenant_id(), patient_a, 1, 20, ) .await .unwrap(); assert_eq!(list_a.total, 1); let list_b = medication_record_service::list_medications( app.health_state(), app.tenant_id(), patient_b, 1, 20, ) .await .unwrap(); assert_eq!(list_b.total, 1); } // --------------------------------------------------------------------------- // 测试 5: 软删除 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_soft_delete() { let app = TestApp::new().await; let patient_id = app.create_patient("用药删除患者").await; let med = seed_medication(&app, patient_id).await; medication_record_service::delete_medication( app.health_state(), app.tenant_id(), med.id, Some(app.operator_id()), med.version, ) .await .expect("删除应成功"); let result = medication_record_service::get_medication( app.health_state(), app.tenant_id(), med.id, ) .await; assert!(result.is_err(), "软删除后查询应失败"); } // --------------------------------------------------------------------------- // 测试 6: 租户隔离 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_tenant_isolation() { let app = TestApp::new().await; let patient_id = app.create_patient("用药隔离患者").await; seed_medication(&app, patient_id).await; let other_tenant = uuid::Uuid::new_v4(); let list = medication_record_service::list_medications( app.health_state(), other_tenant, patient_id, 1, 20, ) .await .unwrap(); assert_eq!(list.total, 0, "不同租户不应看到用药记录"); } // --------------------------------------------------------------------------- // 测试 7: 乐观锁冲突 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_version_conflict() { let app = TestApp::new().await; let patient_id = app.create_patient("用药锁患者").await; let med = seed_medication(&app, patient_id).await; // 先更新一次 medication_record_service::update_medication( app.health_state(), app.tenant_id(), med.id, Some(app.operator_id()), UpdateMedicationRecordReq { dosage: Some("160mg".to_string()), medication_name: None, generic_name: None, unit: None, frequency: None, route: None, start_date: None, end_date: None, is_current: None, prescribed_by: None, notes: None, }, med.version, ) .await .unwrap(); // 用旧 version 再更新应失败 let result = medication_record_service::update_medication( app.health_state(), app.tenant_id(), med.id, Some(app.operator_id()), UpdateMedicationRecordReq { dosage: Some("320mg".to_string()), medication_name: None, generic_name: None, unit: None, frequency: None, route: None, start_date: None, end_date: None, is_current: None, prescribed_by: None, notes: None, }, med.version, ) .await; assert!(result.is_err(), "乐观锁冲突应返回错误"); } // --------------------------------------------------------------------------- // 测试 8: 无效患者创建用药记录返回错误 // --------------------------------------------------------------------------- #[tokio::test] async fn test_medication_invalid_patient() { let app = TestApp::new().await; let fake_patient = uuid::Uuid::new_v4(); let result = medication_record_service::create_medication( app.health_state(), app.tenant_id(), None, default_create_medication_req(fake_patient), ) .await; assert!(result.is_err(), "无效患者应返回错误"); }