//! erp-health 诊断记录集成测试 //! //! 验证诊断 CRUD、列表按患者过滤、租户隔离、乐观锁。 use erp_health::dto::diagnosis_dto::*; use erp_health::service::diagnosis_service; use super::test_fixture::TestApp; fn default_create_diagnosis_req() -> CreateDiagnosisReq { CreateDiagnosisReq { icd_code: "N18.9".to_string(), diagnosis_name: "慢性肾脏病".to_string(), diagnosis_type: "primary".to_string(), diagnosed_date: chrono::NaiveDate::from_ymd_opt(2026, 4, 15).unwrap(), status: "active".to_string(), health_record_id: None, diagnosed_by: None, notes: None, } } async fn seed_diagnosis( app: &TestApp, patient_id: uuid::Uuid, icd_code: &str, name: &str, ) -> DiagnosisResp { diagnosis_service::create_diagnosis( app.health_state(), app.tenant_id(), patient_id, Some(app.operator_id()), CreateDiagnosisReq { icd_code: icd_code.to_string(), diagnosis_name: name.to_string(), ..default_create_diagnosis_req() }, ) .await .expect("创建诊断应成功") } // --------------------------------------------------------------------------- // 测试 1: 创建诊断 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_create() { let app = TestApp::new().await; let patient_id = app.create_patient("诊断患者").await; let diag = seed_diagnosis(&app, patient_id, "N18.9", "慢性肾脏病").await; assert_eq!(diag.patient_id, patient_id); assert_eq!(diag.icd_code, "N18.9"); assert_eq!(diag.diagnosis_type, "primary"); assert_eq!(diag.status, "active"); assert_eq!(diag.version, 1); } // --------------------------------------------------------------------------- // 测试 2: 更新诊断 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_update() { let app = TestApp::new().await; let patient_id = app.create_patient("诊断更新患者").await; let diag = seed_diagnosis(&app, patient_id, "N18.8", "CKD更新").await; let updated = diagnosis_service::update_diagnosis( app.health_state(), app.tenant_id(), diag.id, Some(app.operator_id()), UpdateDiagnosisReq { status: Some("chronic".to_string()), notes: Some("长期随访".to_string()), icd_code: None, diagnosis_name: None, diagnosis_type: None, diagnosed_date: None, health_record_id: None, diagnosed_by: None, }, diag.version, ) .await .expect("更新应成功"); assert_eq!(updated.status, "chronic"); assert_eq!(updated.version, 2); } // --------------------------------------------------------------------------- // 测试 3: 列表按患者过滤 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_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_diagnosis(&app, patient_a, "N18.1", "CKD 1期").await; seed_diagnosis(&app, patient_a, "N18.2", "CKD 2期").await; seed_diagnosis(&app, patient_b, "E11.9", "2型糖尿病").await; let list_a = diagnosis_service::list_diagnoses(app.health_state(), app.tenant_id(), patient_a, 1, 20) .await .unwrap(); assert_eq!(list_a.total, 2); let list_b = diagnosis_service::list_diagnoses(app.health_state(), app.tenant_id(), patient_b, 1, 20) .await .unwrap(); assert_eq!(list_b.total, 1); } // --------------------------------------------------------------------------- // 测试 4: 软删除 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_soft_delete() { let app = TestApp::new().await; let patient_id = app.create_patient("诊断删除患者").await; let diag = seed_diagnosis(&app, patient_id, "N18.3", "CKD删除").await; diagnosis_service::delete_diagnosis( app.health_state(), app.tenant_id(), diag.id, Some(app.operator_id()), diag.version, ) .await .expect("删除应成功"); let list = diagnosis_service::list_diagnoses(app.health_state(), app.tenant_id(), patient_id, 1, 20) .await .unwrap(); assert_eq!(list.total, 0); } // --------------------------------------------------------------------------- // 测试 5: 租户隔离 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_tenant_isolation() { let app = TestApp::new().await; let patient_id = app.create_patient("诊断隔离患者").await; seed_diagnosis(&app, patient_id, "N18.4", "CKD隔离").await; let other_tenant = uuid::Uuid::new_v4(); let list = diagnosis_service::list_diagnoses(app.health_state(), other_tenant, patient_id, 1, 20) .await .unwrap(); assert_eq!(list.total, 0, "不同租户不应看到诊断记录"); } // --------------------------------------------------------------------------- // 测试 6: 无效患者创建诊断返回错误 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_invalid_patient() { let app = TestApp::new().await; let fake_patient = uuid::Uuid::new_v4(); let result = diagnosis_service::create_diagnosis( app.health_state(), app.tenant_id(), fake_patient, None, default_create_diagnosis_req(), ) .await; assert!(result.is_err(), "无效患者应返回错误"); } // --------------------------------------------------------------------------- // 测试 7: 乐观锁冲突 // --------------------------------------------------------------------------- #[tokio::test] async fn test_diagnosis_version_conflict() { let app = TestApp::new().await; let patient_id = app.create_patient("诊断锁患者").await; let diag = seed_diagnosis(&app, patient_id, "N18.5", "CKD锁").await; // 先更新一次 diagnosis_service::update_diagnosis( app.health_state(), app.tenant_id(), diag.id, Some(app.operator_id()), UpdateDiagnosisReq { status: Some("resolved".to_string()), icd_code: None, diagnosis_name: None, diagnosis_type: None, diagnosed_date: None, health_record_id: None, diagnosed_by: None, notes: None, }, diag.version, ) .await .unwrap(); // 用旧 version 再更新应失败 let result = diagnosis_service::update_diagnosis( app.health_state(), app.tenant_id(), diag.id, Some(app.operator_id()), UpdateDiagnosisReq { status: Some("chronic".to_string()), icd_code: None, diagnosis_name: None, diagnosis_type: None, diagnosed_date: None, health_record_id: None, diagnosed_by: None, notes: None, }, diag.version, ) .await; assert!(result.is_err(), "乐观锁冲突应返回错误"); }