diff --git a/crates/erp-health/src/service/article_service.rs b/crates/erp-health/src/service/article_service.rs index 225453c..eabcbea 100644 --- a/crates/erp-health/src/service/article_service.rs +++ b/crates/erp-health/src/service/article_service.rs @@ -15,6 +15,7 @@ use crate::entity::article; use crate::entity::article_article_tag; use crate::entity::article_tag; use crate::error::{HealthError, HealthResult}; +use crate::service::validation; use crate::state::HealthState; /// 文章列表(管理端,支持状态/分类/标签/关键词筛选) @@ -130,9 +131,7 @@ pub async fn submit_article( let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; - if model.status != "draft" && model.status != "rejected" { - return Err(HealthError::InvalidStatusTransition(format!("无法从 {} 提交审核", model.status))); - } + validation::validate_article_status_transition(&model.status, "pending_review")?; let mut active: article::ActiveModel = model.into(); active.status = Set("pending_review".into()); @@ -164,9 +163,7 @@ pub async fn approve_article( let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; - if model.status != "pending_review" { - return Err(HealthError::InvalidStatusTransition(format!("无法从 {} 审核通过", model.status))); - } + validation::validate_article_status_transition(&model.status, "published")?; let now = Utc::now(); let mut active: article::ActiveModel = model.into(); @@ -203,9 +200,7 @@ pub async fn reject_article( let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; - if model.status != "pending_review" { - return Err(HealthError::InvalidStatusTransition(format!("无法从 {} 审核拒绝", model.status))); - } + validation::validate_article_status_transition(&model.status, "rejected")?; let now = Utc::now(); let mut active: article::ActiveModel = model.into(); @@ -240,9 +235,7 @@ pub async fn unpublish_article( let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; - if model.status != "published" { - return Err(HealthError::InvalidStatusTransition(format!("无法从 {} 撤回发布", model.status))); - } + validation::validate_article_status_transition(&model.status, "draft")?; let mut active: article::ActiveModel = model.into(); active.status = Set("draft".into()); diff --git a/crates/erp-health/src/service/dialysis_service.rs b/crates/erp-health/src/service/dialysis_service.rs index 6598510..4bda989 100644 --- a/crates/erp-health/src/service/dialysis_service.rs +++ b/crates/erp-health/src/service/dialysis_service.rs @@ -15,6 +15,7 @@ use erp_core::types::PaginatedResponse; use crate::dto::dialysis_dto::*; use crate::entity::{dialysis_record, patient}; use crate::error::{HealthError, HealthResult}; +use crate::service::validation; use crate::state::HealthState; pub async fn list_dialysis_records( @@ -221,6 +222,8 @@ pub async fn review_dialysis_record( let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; + validation::validate_dialysis_status_transition(&model.status, "reviewed")?; + let mut active: dialysis_record::ActiveModel = model.into(); active.status = Set("reviewed".to_string()); active.reviewed_by = Set(Some(reviewer_id)); diff --git a/crates/erp-health/src/service/health_data_service.rs b/crates/erp-health/src/service/health_data_service.rs index fafebc5..9bfa3e1 100644 --- a/crates/erp-health/src/service/health_data_service.rs +++ b/crates/erp-health/src/service/health_data_service.rs @@ -16,7 +16,7 @@ use erp_core::types::PaginatedResponse; use crate::dto::health_data_dto::*; use crate::entity::{doctor_profile, health_record, lab_report, patient, patient_doctor_relation, vital_signs}; use crate::error::{HealthError, HealthResult}; -use crate::service::validation::validate_record_type; +use crate::service::validation::{validate_record_type, validate_lab_report_status_transition}; use crate::state::HealthState; // --------------------------------------------------------------------------- @@ -512,6 +512,8 @@ pub async fn review_lab_report( let next_ver = check_version(expected_version, model.version) .map_err(|_| HealthError::VersionMismatch)?; + validate_lab_report_status_transition(&model.status, "reviewed")?; + let mut active: lab_report::ActiveModel = model.into(); active.status = Set("reviewed".to_string()); active.reviewed_by = Set(Some(reviewer_id)); diff --git a/crates/erp-health/src/service/validation.rs b/crates/erp-health/src/service/validation.rs index 4b5f993..4231461 100644 --- a/crates/erp-health/src/service/validation.rs +++ b/crates/erp-health/src/service/validation.rs @@ -141,8 +141,7 @@ pub fn validate_article_status(value: &str) -> HealthResult<()> { /// article.status 状态转换 /// draft → pending_review, rejected → pending_review -/// pending_review → approved / rejected -/// approved → published +/// pending_review → published / rejected(审核通过直接发布,或拒绝) /// published → draft (下架) pub fn validate_article_status_transition(current: &str, new: &str) -> HealthResult<()> { if current == new { @@ -150,8 +149,7 @@ pub fn validate_article_status_transition(current: &str, new: &str) -> HealthRes } let allowed = match current { "draft" => matches!(new, "pending_review"), - "pending_review" => matches!(new, "approved" | "rejected"), - "approved" => matches!(new, "published"), + "pending_review" => matches!(new, "published" | "rejected"), "rejected" => matches!(new, "pending_review"), "published" => matches!(new, "draft"), _ => false, @@ -369,19 +367,17 @@ mod tests { #[test] fn art_draft_to_published_fails() { assert!(validate_article_status_transition("draft", "published").is_err()); } #[test] - fn art_pending_review_to_approved() { assert!(validate_article_status_transition("pending_review", "approved").is_ok()); } + fn art_pending_review_to_published() { assert!(validate_article_status_transition("pending_review", "published").is_ok()); } #[test] fn art_pending_review_to_rejected() { assert!(validate_article_status_transition("pending_review", "rejected").is_ok()); } #[test] fn art_pending_review_to_draft_fails() { assert!(validate_article_status_transition("pending_review", "draft").is_err()); } #[test] - fn art_approved_to_published() { assert!(validate_article_status_transition("approved", "published").is_ok()); } - #[test] fn art_rejected_to_pending_review() { assert!(validate_article_status_transition("rejected", "pending_review").is_ok()); } #[test] fn art_published_to_draft() { assert!(validate_article_status_transition("published", "draft").is_ok()); } #[test] - fn art_published_to_approved_fails() { assert!(validate_article_status_transition("published", "approved").is_err()); } + fn art_published_to_pending_fails() { assert!(validate_article_status_transition("published", "pending_review").is_err()); } #[test] fn art_same_status_ok() { assert!(validate_article_status_transition("draft", "draft").is_ok()); }