fix(health+dialysis): S2 smoke test 修复 — Entity 表名 + 透析状态转换
- 修复 6 个 Entity table_name 与迁移不匹配: shift, handoff_log, patient_assignment, blind_index, critical_alert, critical_alert_response - 添加透析记录 draft→completed 状态转换 API (PUT /complete) - 修复 family_proxy_service 告警状态过滤 (active→pending/acknowledged) - dev.ps1 添加 RATE_LIMIT__FAIL_CLOSE=false 开发模式 - S2 透析日流程 smoke test 报告
This commit is contained in:
@@ -125,6 +125,24 @@ where
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
pub async fn complete_dialysis_record<S>(
|
||||
State(state): State<DialysisState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(record_id): Path<Uuid>,
|
||||
Json(req): Json<ReviewDialysisWithVersion>,
|
||||
) -> Result<Json<ApiResponse<DialysisRecordResp>>, AppError>
|
||||
where
|
||||
DialysisState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.dialysis.manage")?;
|
||||
let result = dialysis_service::complete_dialysis_record(
|
||||
&state, ctx.tenant_id, record_id, Some(ctx.user_id), req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
pub async fn delete_dialysis_record<S>(
|
||||
State(state): State<DialysisState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
|
||||
@@ -42,6 +42,10 @@ impl DialysisModule {
|
||||
"/health/dialysis-records/{id}/review",
|
||||
axum::routing::put(dialysis_handler::review_dialysis_record),
|
||||
)
|
||||
.route(
|
||||
"/health/dialysis-records/{id}/complete",
|
||||
axum::routing::put(dialysis_handler::complete_dialysis_record),
|
||||
)
|
||||
// 透析方案
|
||||
.route(
|
||||
"/health/dialysis-prescriptions",
|
||||
|
||||
@@ -211,6 +211,43 @@ pub async fn update_dialysis_record(
|
||||
Ok(to_resp(&state.crypto, m))
|
||||
}
|
||||
|
||||
pub async fn complete_dialysis_record(
|
||||
state: &DialysisState,
|
||||
tenant_id: Uuid,
|
||||
record_id: Uuid,
|
||||
operator_id: Option<Uuid>,
|
||||
expected_version: i32,
|
||||
) -> DialysisResult<DialysisRecordResp> {
|
||||
let model = dialysis_record::Entity::find()
|
||||
.filter(dialysis_record::Column::Id.eq(record_id))
|
||||
.filter(dialysis_record::Column::TenantId.eq(tenant_id))
|
||||
.filter(dialysis_record::Column::DeletedAt.is_null())
|
||||
.one(&state.db)
|
||||
.await?
|
||||
.ok_or(DialysisError::DialysisRecordNotFound)?;
|
||||
|
||||
let next_ver = check_version(expected_version, model.version)
|
||||
.map_err(|_| DialysisError::VersionMismatch)?;
|
||||
|
||||
validate_dialysis_status_transition(&model.status, "completed")?;
|
||||
|
||||
let now = Utc::now();
|
||||
let mut active: dialysis_record::ActiveModel = model.into();
|
||||
active.status = Set("completed".to_string());
|
||||
active.updated_at = Set(now);
|
||||
active.updated_by = Set(operator_id);
|
||||
active.version = Set(next_ver);
|
||||
let m = active.update(&state.db).await?;
|
||||
|
||||
audit_service::record(
|
||||
AuditLog::new(tenant_id, operator_id, "dialysis_record.completed", "dialysis_record")
|
||||
.with_resource_id(m.id),
|
||||
&state.db,
|
||||
).await;
|
||||
|
||||
Ok(to_resp(&state.crypto, m))
|
||||
}
|
||||
|
||||
pub async fn review_dialysis_record(
|
||||
state: &DialysisState,
|
||||
tenant_id: Uuid,
|
||||
|
||||
@@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[sea_orm(table_name = "blind_indexes")]
|
||||
#[sea_orm(table_name = "blind_index")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
|
||||
@@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[sea_orm(table_name = "critical_alerts")]
|
||||
#[sea_orm(table_name = "critical_alert")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
|
||||
@@ -2,7 +2,7 @@ use sea_orm::entity::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[sea_orm(table_name = "critical_alert_responses")]
|
||||
#[sea_orm(table_name = "critical_alert_response")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[sea_orm(table_name = "shift_handoff_log")]
|
||||
#[sea_orm(table_name = "handoff_log")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[sea_orm(table_name = "patient_assignments")]
|
||||
#[sea_orm(table_name = "patient_assignment")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[sea_orm(table_name = "shifts")]
|
||||
#[sea_orm(table_name = "shift")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
|
||||
@@ -327,7 +327,7 @@ async fn count_recent_alerts(
|
||||
let count = alerts::Entity::find()
|
||||
.filter(alerts::Column::TenantId.eq(tenant_id))
|
||||
.filter(alerts::Column::PatientId.eq(patient_id))
|
||||
.filter(alerts::Column::Status.eq("active"))
|
||||
.filter(alerts::Column::Status.is_in(["pending", "acknowledged"]))
|
||||
.count(db)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -588,7 +588,7 @@ async fn count_patients_by_care_level(
|
||||
let counts: Vec<CareLevelCount> = CareLevelCount::find_by_statement(
|
||||
sea_orm::Statement::from_sql_and_values(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
"SELECT care_level, CAST(COUNT(*) AS BIGINT) as count FROM patient_assignments \
|
||||
"SELECT care_level, CAST(COUNT(*) AS BIGINT) as count FROM patient_assignment \
|
||||
WHERE shift_id = $1 AND deleted_at IS NULL \
|
||||
GROUP BY care_level",
|
||||
[shift_id.into()],
|
||||
|
||||
Reference in New Issue
Block a user