feat(health+core+ai): 业务流程全面修复 Phase 4-6 + 集成测试修复
Phase 4 — Dead-letter 重试 + 内容推送 + 安全加固: - erp-core: retry_dead_letters() 定时重试 + PII payload 脱敏 - erp-core: audit_service 哈希链定时验证 + 写入失败告警 - erp-health: article.published 消费者匹配 patient_tag 推送消息 - erp-health: care_plan 事件消费者 (激活通知 + 完成积分) Phase 5 — 患者批量操作 + 咨询增强 + 护理事件: - patient: batch_import_patients + bind_by_phone + refer_patient - consultation: rate_session 满意度评价 (rating + feedback) - consent: patient_sign_consent 患者端签署 - validation: source 枚举 (7值) + relationship 枚举 (7值) + 12 单元测试 Phase 6 — 咨询文件上传 + AI 引用标注: - consultation_message: media_id 附件上传端点 - ai_suggestion: references JSONB + [ref:id] 格式引用标注 - AI system prompt 增加引用指令 + output_parser 提取逻辑 迁移: 000161 (media_id + references) + 000162 (rating + feedback) 集成测试: consultation/follow_up/pii_encryption 新字段同步修复 讨论文档: 2026-05-20-business-process-brainstorm.md (10域审核报告)
This commit is contained in:
@@ -11,8 +11,9 @@ use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::patient_dto::{
|
||||
CreatePatientReq, FamilyMemberReq, FamilyMemberResp, ManageTagsReq, PatientResp,
|
||||
UpdatePatientReq,
|
||||
BatchImportPatientReq, BatchResultResp, BindByPhoneReq, BindResultResp, CreatePatientReq,
|
||||
FamilyMemberReq, FamilyMemberResp, ManageTagsReq, PatientResp, ReferPatientReq,
|
||||
ReferResultResp, UpdatePatientReq,
|
||||
};
|
||||
use crate::service::patient_service;
|
||||
use crate::state::HealthState;
|
||||
@@ -448,3 +449,90 @@ where
|
||||
patient_service::delete_tag(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
/// 批量导入患者
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/health/patients/import",
|
||||
request_body = BatchImportPatientReq,
|
||||
responses(
|
||||
(status = 200, description = "批量导入结果"),
|
||||
),
|
||||
tag = "患者管理",
|
||||
security(("bearer_auth" = [])),
|
||||
)]
|
||||
pub async fn batch_import_patients<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<BatchImportPatientReq>,
|
||||
) -> Result<Json<ApiResponse<BatchResultResp>>, AppError>
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
req.validate()
|
||||
.map_err(|e| AppError::Validation(e.to_string()))?;
|
||||
let result =
|
||||
patient_service::batch_import_patients(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
/// 患者通过手机号自助绑定
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/health/patients/bind-by-phone",
|
||||
request_body = BindByPhoneReq,
|
||||
responses(
|
||||
(status = 200, description = "绑定成功"),
|
||||
(status = 404, description = "未找到匹配患者"),
|
||||
),
|
||||
tag = "患者管理",
|
||||
security(("bearer_auth" = [])),
|
||||
)]
|
||||
pub async fn bind_by_phone<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<BindByPhoneReq>,
|
||||
) -> Result<Json<ApiResponse<BindResultResp>>, AppError>
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
// 患者自己绑定,只需认证,不需要特殊权限
|
||||
req.validate()
|
||||
.map_err(|e| AppError::Validation(e.to_string()))?;
|
||||
let result = patient_service::bind_by_phone(&state, ctx.tenant_id, ctx.user_id, req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
/// 患者转诊
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/health/patients/{id}/refer",
|
||||
request_body = ReferPatientReq,
|
||||
responses(
|
||||
(status = 200, description = "转诊成功"),
|
||||
(status = 404, description = "患者或医生不存在"),
|
||||
),
|
||||
tag = "患者管理",
|
||||
security(("bearer_auth" = [])),
|
||||
)]
|
||||
pub async fn refer_patient<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(id): Path<Uuid>,
|
||||
Json(req): Json<ReferPatientReq>,
|
||||
) -> Result<Json<ApiResponse<ReferResultResp>>, AppError>
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
req.validate()
|
||||
.map_err(|e| AppError::Validation(e.to_string()))?;
|
||||
let result =
|
||||
patient_service::refer_patient(&state, ctx.tenant_id, id, req, Some(ctx.user_id)).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user