功能修复: 1. 患者创建空名称验证:后端添加 name.trim().is_empty() 检查 2. 仪表盘统计容错:单个查询失败返回零值而非 500 3. FHIR 路由修复:从 /fhir 移到 /api/v1/fhir 保持一致 4. 冻结模块后端中间件:新增 frozen_module_middleware 拦截冻结路径 5. 积分端点权限码:health.health-data.list → health.points.list 6. 角色权限迁移:护士补充 devices.list,运营补充 points.list/manage 7. 测试结果文档:R01-R05 角色测试 + T00/T10 结果归档 Clippy 全 workspace 清零(14→0 errors): - erp-core: 修复 empty doc line、collapsible if、redundant closure 等 9 处 - erp-health: 修复 too_many_arguments、unused var、unnecessary parens 等 58 处 - erp-ai: 修复 dead_code、unused import 等 11 处 - erp-plugin: 修复 too_many_arguments、wildcard pattern 等 11 处 - erp-server-migration: 修复 enum_variant_names 5 处 - erp-auth/config/workflow/message: 各 1-3 处 工程改进: - lint-staged 配置迁移到 .lintstagedrc.js(函数式避免文件列表传给 clippy) - cargo fmt 统一格式化
144 lines
4.6 KiB
Rust
144 lines
4.6 KiB
Rust
use erp_core::error::AppError;
|
||
|
||
/// Config module error types.
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum ConfigError {
|
||
#[error("验证失败: {0}")]
|
||
Validation(String),
|
||
|
||
#[error("资源未找到: {0}")]
|
||
NotFound(String),
|
||
|
||
#[error("键已存在: {0}")]
|
||
DuplicateKey(String),
|
||
|
||
#[error("编号序列耗尽: {0}")]
|
||
NumberingExhausted(String),
|
||
|
||
#[error("版本冲突: 数据已被其他操作修改,请刷新后重试")]
|
||
VersionMismatch,
|
||
}
|
||
|
||
impl From<sea_orm::TransactionError<ConfigError>> for ConfigError {
|
||
fn from(err: sea_orm::TransactionError<ConfigError>) -> Self {
|
||
match err {
|
||
sea_orm::TransactionError::Connection(err) => ConfigError::Validation(err.to_string()),
|
||
sea_orm::TransactionError::Transaction(inner) => inner,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl From<sea_orm::DbErr> for ConfigError {
|
||
fn from(err: sea_orm::DbErr) -> Self {
|
||
ConfigError::Validation(err.to_string())
|
||
}
|
||
}
|
||
|
||
impl From<ConfigError> for AppError {
|
||
fn from(err: ConfigError) -> Self {
|
||
match err {
|
||
ConfigError::Validation(s) => AppError::Validation(s),
|
||
ConfigError::NotFound(s) => AppError::NotFound(s),
|
||
ConfigError::DuplicateKey(s) => AppError::Conflict(s),
|
||
ConfigError::NumberingExhausted(s) => AppError::Internal(s),
|
||
ConfigError::VersionMismatch => AppError::VersionMismatch,
|
||
}
|
||
}
|
||
}
|
||
|
||
pub type ConfigResult<T> = Result<T, ConfigError>;
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use erp_core::error::AppError;
|
||
|
||
#[test]
|
||
fn config_error_validation_maps_to_app_validation() {
|
||
let app: AppError = ConfigError::Validation("字段不能为空".to_string()).into();
|
||
match app {
|
||
AppError::Validation(msg) => assert_eq!(msg, "字段不能为空"),
|
||
other => panic!("期望 Validation,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_not_found_maps_to_app_not_found() {
|
||
let app: AppError = ConfigError::NotFound("字典不存在".to_string()).into();
|
||
match app {
|
||
AppError::NotFound(msg) => assert_eq!(msg, "字典不存在"),
|
||
other => panic!("期望 NotFound,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_duplicate_key_maps_to_app_conflict() {
|
||
let app: AppError = ConfigError::DuplicateKey("编码已存在".to_string()).into();
|
||
match app {
|
||
AppError::Conflict(msg) => assert_eq!(msg, "编码已存在"),
|
||
other => panic!("期望 Conflict,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_numbering_exhausted_maps_to_app_internal() {
|
||
let app: AppError = ConfigError::NumberingExhausted("序列已耗尽".to_string()).into();
|
||
match app {
|
||
AppError::Internal(msg) => assert!(msg.contains("序列已耗尽")),
|
||
other => panic!("期望 Internal,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_version_mismatch_maps_to_app_version_mismatch() {
|
||
let app: AppError = ConfigError::VersionMismatch.into();
|
||
match app {
|
||
AppError::VersionMismatch => {}
|
||
other => panic!("期望 VersionMismatch,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_display_messages() {
|
||
// 验证各变体的 Display 输出包含中文描述
|
||
assert!(
|
||
ConfigError::Validation("test".into())
|
||
.to_string()
|
||
.contains("验证失败")
|
||
);
|
||
assert!(
|
||
ConfigError::NotFound("test".into())
|
||
.to_string()
|
||
.contains("资源未找到")
|
||
);
|
||
assert!(
|
||
ConfigError::DuplicateKey("test".into())
|
||
.to_string()
|
||
.contains("键已存在")
|
||
);
|
||
assert!(
|
||
ConfigError::NumberingExhausted("test".into())
|
||
.to_string()
|
||
.contains("编号序列耗尽")
|
||
);
|
||
assert!(
|
||
ConfigError::VersionMismatch
|
||
.to_string()
|
||
.contains("版本冲突")
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn transaction_error_connection_maps_to_validation() {
|
||
// TransactionError::Connection 应该转换为 ConfigError::Validation
|
||
let config_err: ConfigError = sea_orm::TransactionError::Connection(sea_orm::DbErr::Conn(
|
||
sea_orm::RuntimeErr::Internal("连接失败".to_string()),
|
||
))
|
||
.into();
|
||
match config_err {
|
||
ConfigError::Validation(msg) => assert!(msg.contains("连接失败")),
|
||
other => panic!("期望 Validation,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
}
|