fix: 修复测试发现的 7 个问题 + 全 workspace clippy 清零
功能修复: 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 统一格式化
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
@@ -82,8 +82,7 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.action-inbox.team")?;
|
||||
let result =
|
||||
action_inbox_service::get_team_overview(&state.db, ctx.tenant_id).await?;
|
||||
let result = action_inbox_service::get_team_overview(&state.db, ctx.tenant_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Path, Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::Extension;
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
use uuid::Uuid;
|
||||
@@ -36,9 +36,15 @@ where
|
||||
let page_size = query.page_size.unwrap_or(20);
|
||||
|
||||
let (items, total) = alert_service::list_alerts(
|
||||
&state, ctx.tenant_id, query.patient_id, query.doctor_id, query.status.as_deref(),
|
||||
page, page_size,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
query.patient_id,
|
||||
query.doctor_id,
|
||||
query.status.as_deref(),
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(axum::Json(ApiResponse::ok(PaginatedResponse {
|
||||
data: items,
|
||||
@@ -74,9 +80,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.alerts.manage")?;
|
||||
let alert = alert_service::acknowledge_alert(
|
||||
&state, ctx.tenant_id, id, ctx.user_id, body.version,
|
||||
).await?;
|
||||
let alert =
|
||||
alert_service::acknowledge_alert(&state, ctx.tenant_id, id, ctx.user_id, body.version)
|
||||
.await?;
|
||||
Ok(axum::Json(ApiResponse::ok(alert)))
|
||||
}
|
||||
|
||||
@@ -91,9 +97,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.alerts.manage")?;
|
||||
let alert = alert_service::dismiss_alert(
|
||||
&state, ctx.tenant_id, id, ctx.user_id, body.version,
|
||||
).await?;
|
||||
let alert =
|
||||
alert_service::dismiss_alert(&state, ctx.tenant_id, id, ctx.user_id, body.version).await?;
|
||||
Ok(axum::Json(ApiResponse::ok(alert)))
|
||||
}
|
||||
|
||||
@@ -108,8 +113,6 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.alerts.manage")?;
|
||||
let alert = alert_service::resolve_alert(
|
||||
&state, ctx.tenant_id, id, body.version,
|
||||
).await?;
|
||||
let alert = alert_service::resolve_alert(&state, ctx.tenant_id, id, body.version).await?;
|
||||
Ok(axum::Json(ApiResponse::ok(alert)))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Path, Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::Extension;
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
use uuid::Uuid;
|
||||
@@ -39,8 +39,13 @@ where
|
||||
let page_size = query.page_size.unwrap_or(20);
|
||||
|
||||
let (items, total) = alert_rule_service::list_rules(
|
||||
&state, ctx.tenant_id, query.device_type.as_deref(), page, page_size,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
query.device_type.as_deref(),
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(axum::Json(ApiResponse::ok(PaginatedResponse {
|
||||
data: items,
|
||||
@@ -62,9 +67,7 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.alert-rules.manage")?;
|
||||
body.sanitize();
|
||||
let rule = alert_rule_service::create_rule(
|
||||
&state, ctx.tenant_id, ctx.user_id, body,
|
||||
).await?;
|
||||
let rule = alert_rule_service::create_rule(&state, ctx.tenant_id, ctx.user_id, body).await?;
|
||||
Ok(axum::Json(ApiResponse::ok(rule)))
|
||||
}
|
||||
|
||||
@@ -80,9 +83,8 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.alert-rules.manage")?;
|
||||
body.sanitize();
|
||||
let rule = alert_rule_service::update_rule(
|
||||
&state, ctx.tenant_id, id, ctx.user_id, body,
|
||||
).await?;
|
||||
let rule =
|
||||
alert_rule_service::update_rule(&state, ctx.tenant_id, id, ctx.user_id, body).await?;
|
||||
Ok(axum::Json(ApiResponse::ok(rule)))
|
||||
}
|
||||
|
||||
@@ -97,8 +99,6 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.alert-rules.manage")?;
|
||||
let rule = alert_rule_service::deactivate_rule(
|
||||
&state, ctx.tenant_id, id, body.version,
|
||||
).await?;
|
||||
let rule = alert_rule_service::deactivate_rule(&state, ctx.tenant_id, id, body.version).await?;
|
||||
Ok(axum::Json(ApiResponse::ok(rule)))
|
||||
}
|
||||
|
||||
@@ -64,8 +64,14 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = appointment_service::list_appointments(
|
||||
&state, ctx.tenant_id, page, page_size, params.status, params.patient_id,
|
||||
params.doctor_id, params.date,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.status,
|
||||
params.patient_id,
|
||||
params.doctor_id,
|
||||
params.date,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -83,10 +89,9 @@ where
|
||||
require_permission(&ctx, "health.appointment.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = appointment_service::create_appointment(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
appointment_service::create_appointment(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -121,7 +126,12 @@ where
|
||||
};
|
||||
update_req.sanitize();
|
||||
let result = appointment_service::update_appointment_status(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), update_req, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
update_req,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -140,7 +150,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = appointment_service::list_schedules(
|
||||
&state, ctx.tenant_id, page, page_size, params.doctor_id, params.date,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.doctor_id,
|
||||
params.date,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -156,10 +171,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.appointment.manage")?;
|
||||
let result = appointment_service::create_schedule(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
appointment_service::create_schedule(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -175,7 +188,12 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.appointment.manage")?;
|
||||
let result = appointment_service::update_schedule(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -192,7 +210,11 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.appointment.list")?;
|
||||
let result = appointment_service::calendar_view(
|
||||
&state, ctx.tenant_id, params.start_date, params.end_date, params.doctor_id,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
params.start_date,
|
||||
params.end_date,
|
||||
params.doctor_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
|
||||
@@ -34,9 +34,9 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
req.sanitize();
|
||||
let result = article_category_service::create_category(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
let result =
|
||||
article_category_service::create_category(&state, ctx.tenant_id, Some(ctx.user_id), req.0)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -53,8 +53,13 @@ where
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
req.sanitize();
|
||||
let result = article_category_service::update_category(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.0,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -75,7 +80,12 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
article_category_service::delete_category(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::{require_any_permission, require_permission};
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::article_dto::{ArticleListItem, ArticleListParams, ArticleResp, CreateArticleReq, ReviewArticleReq, UpdateArticleReq};
|
||||
use crate::dto::article_dto::{
|
||||
ArticleListItem, ArticleListParams, ArticleResp, CreateArticleReq, ReviewArticleReq,
|
||||
UpdateArticleReq,
|
||||
};
|
||||
use crate::service::article_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -22,14 +25,24 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
// 非管理权限用户只能查看已发布文章,防止草稿泄露
|
||||
let status = if require_any_permission(&ctx, &["health.articles.manage", "health.articles.review"]).is_ok() {
|
||||
params.status
|
||||
} else {
|
||||
Some("published".to_string())
|
||||
};
|
||||
let status =
|
||||
if require_any_permission(&ctx, &["health.articles.manage", "health.articles.review"])
|
||||
.is_ok()
|
||||
{
|
||||
params.status
|
||||
} else {
|
||||
Some("published".to_string())
|
||||
};
|
||||
let result = article_service::list_articles(
|
||||
&state, ctx.tenant_id, page, page_size,
|
||||
params.category, status, params.category_id, params.tag_id, params.keyword,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.category,
|
||||
status,
|
||||
params.category_id,
|
||||
params.tag_id,
|
||||
params.keyword,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -45,7 +58,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.articles.list")?;
|
||||
let is_admin = require_any_permission(&ctx, &["health.articles.manage", "health.articles.review"]).is_ok();
|
||||
let is_admin =
|
||||
require_any_permission(&ctx, &["health.articles.manage", "health.articles.review"]).is_ok();
|
||||
let result = article_service::get_article(&state, ctx.tenant_id, id, is_admin).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
@@ -61,9 +75,8 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
req.sanitize();
|
||||
let result = article_service::create_article(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
let result =
|
||||
article_service::create_article(&state, ctx.tenant_id, Some(ctx.user_id), req.0).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -79,9 +92,9 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
req.sanitize();
|
||||
let result = article_service::update_article(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
let result =
|
||||
article_service::update_article(&state, ctx.tenant_id, id, Some(ctx.user_id), req.0)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -101,7 +114,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
article_service::delete_article(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?;
|
||||
article_service::delete_article(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -126,9 +140,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
let result = article_service::submit_article(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
).await?;
|
||||
let result =
|
||||
article_service::submit_article(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -147,8 +161,14 @@ where
|
||||
req.sanitize();
|
||||
let version = req.version.unwrap_or(0);
|
||||
let result = article_service::approve_article(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.0, version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.0,
|
||||
version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -167,8 +187,14 @@ where
|
||||
req.sanitize();
|
||||
let version = req.version.unwrap_or(0);
|
||||
let result = article_service::reject_article(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.0, version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.0,
|
||||
version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -185,8 +211,13 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
let result = article_service::unpublish_article(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -216,7 +247,10 @@ pub async fn list_revisions<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(id): Path<uuid::Uuid>,
|
||||
Query(params): Query<ListRevisionsQuery>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<crate::dto::article_dto::ArticleRevisionResp>>>, AppError>
|
||||
) -> Result<
|
||||
Json<ApiResponse<PaginatedResponse<crate::dto::article_dto::ArticleRevisionResp>>>,
|
||||
AppError,
|
||||
>
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
@@ -224,8 +258,7 @@ where
|
||||
require_permission(&ctx, "health.articles.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = article_service::list_revisions(
|
||||
&state, ctx.tenant_id, id, page, page_size,
|
||||
).await?;
|
||||
let result =
|
||||
article_service::list_revisions(&state, ctx.tenant_id, id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -34,9 +34,8 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
req.sanitize();
|
||||
let result = article_tag_service::create_tag(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
let result =
|
||||
article_tag_service::create_tag(&state, ctx.tenant_id, Some(ctx.user_id), req.0).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -52,9 +51,9 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
req.sanitize();
|
||||
let result = article_tag_service::update_tag(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
let result =
|
||||
article_tag_service::update_tag(&state, ctx.tenant_id, id, Some(ctx.user_id), req.0)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -74,8 +73,7 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.articles.manage")?;
|
||||
article_tag_service::delete_tag(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
).await?;
|
||||
article_tag_service::delete_tag(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, TenantContext};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::dto::ble_gateway_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::ble_gateway_dto::*;
|
||||
use crate::gateway_auth::GatewayAuthContext;
|
||||
use crate::service::ble_gateway_service;
|
||||
use crate::state::HealthState;
|
||||
@@ -54,8 +54,7 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.ble-gateways.manage")?;
|
||||
let result =
|
||||
ble_gateway_service::create_gateway(&state, ctx.tenant_id, Some(ctx.user_id), body)
|
||||
.await?;
|
||||
ble_gateway_service::create_gateway(&state, ctx.tenant_id, Some(ctx.user_id), body).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -179,14 +178,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.ble-gateways.manage")?;
|
||||
let result = ble_gateway_service::batch_bind(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
gateway_id,
|
||||
Some(ctx.user_id),
|
||||
body,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
ble_gateway_service::batch_bind(&state, ctx.tenant_id, gateway_id, Some(ctx.user_id), body)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
@@ -74,14 +74,9 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.care-plan.manage")?;
|
||||
req.data.sanitize();
|
||||
let result = care_plan_service::update_care_plan(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
plan_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
care_plan_service::update_care_plan(&state, ctx.tenant_id, plan_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -124,14 +119,9 @@ where
|
||||
require_permission(&ctx, "health.care-plan.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = care_plan_service::list_care_plan_items(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
plan_id,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
care_plan_service::list_care_plan_items(&state, ctx.tenant_id, plan_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -222,14 +212,9 @@ where
|
||||
require_permission(&ctx, "health.care-plan.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = care_plan_service::list_care_plan_outcomes(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
plan_id,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
care_plan_service::list_care_plan_outcomes(&state, ctx.tenant_id, plan_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use serde::Deserialize;
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::dto::consent_dto::*;
|
||||
use crate::service::consent_service;
|
||||
@@ -28,10 +28,8 @@ where
|
||||
require_permission(&ctx, "health.consent.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = consent_service::list_consents(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
consent_service::list_consents(&state, ctx.tenant_id, patient_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -47,10 +45,8 @@ where
|
||||
require_permission(&ctx, "health.consent.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = consent_service::grant_consent(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
consent_service::grant_consent(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -67,9 +63,8 @@ where
|
||||
require_permission(&ctx, "health.consent.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = consent_service::revoke_consent(
|
||||
&state, ctx.tenant_id, consent_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
consent_service::revoke_consent(&state, ctx.tenant_id, consent_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -60,10 +60,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.consultation.manage")?;
|
||||
let result = consultation_service::create_session(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
consultation_service::create_session(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -80,7 +78,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = consultation_service::list_sessions(
|
||||
&state, ctx.tenant_id, page, page_size, params.status, params.patient_id,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.status,
|
||||
params.patient_id,
|
||||
params.doctor_id,
|
||||
)
|
||||
.await?;
|
||||
@@ -115,7 +118,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = consultation_service::list_messages(
|
||||
&state, ctx.tenant_id, session_id, page, page_size, params.after_id,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
session_id,
|
||||
page,
|
||||
page_size,
|
||||
params.after_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -133,7 +141,11 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.consultation.manage")?;
|
||||
let result = consultation_service::close_session(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -166,7 +178,12 @@ where
|
||||
};
|
||||
msg_req.sanitize();
|
||||
let result = consultation_service::create_message(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), ctx.user_id, sender_role, msg_req,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
Some(ctx.user_id),
|
||||
ctx.user_id,
|
||||
sender_role,
|
||||
msg_req,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -183,8 +200,13 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.consultation.list")?;
|
||||
let result = consultation_service::export_sessions(
|
||||
&state, ctx.tenant_id, params.status, params.patient_id, params.doctor_id,
|
||||
params.page, params.page_size,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
params.status,
|
||||
params.patient_id,
|
||||
params.doctor_id,
|
||||
params.page,
|
||||
params.page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -219,10 +241,7 @@ where
|
||||
.map_err(|e| AppError::Internal(e.to_string()))?
|
||||
.is_some();
|
||||
let role = if is_doctor { "doctor" } else { "patient" };
|
||||
consultation_service::mark_session_read(
|
||||
&state, ctx.tenant_id, id, ctx.user_id, role,
|
||||
)
|
||||
.await?;
|
||||
consultation_service::mark_session_read(&state, ctx.tenant_id, id, ctx.user_id, role).await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -244,12 +263,13 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.consultation.list")?;
|
||||
let mut result = consultation_service::get_doctor_dashboard(
|
||||
&state, ctx.tenant_id, ctx.user_id,
|
||||
)
|
||||
.await?;
|
||||
let mut result =
|
||||
consultation_service::get_doctor_dashboard(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
consultation_service::enrich_doctor_dashboard_health(
|
||||
&state, ctx.tenant_id, ctx.user_id, &mut result,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
ctx.user_id,
|
||||
&mut result,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Path, Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::Extension;
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
use uuid::Uuid;
|
||||
@@ -31,16 +31,19 @@ where
|
||||
let page = query.page.unwrap_or(1);
|
||||
let page_size = query.page_size.unwrap_or(20);
|
||||
|
||||
let (items, total) = critical_alert_service::list_pending_alerts(
|
||||
&state, ctx.tenant_id, page, page_size,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!(error = %e, tenant_id = %ctx.tenant_id, "查询危急值告警列表失败");
|
||||
e
|
||||
})?;
|
||||
let (items, total) =
|
||||
critical_alert_service::list_pending_alerts(&state, ctx.tenant_id, page, page_size)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!(error = %e, tenant_id = %ctx.tenant_id, "查询危急值告警列表失败");
|
||||
e
|
||||
})?;
|
||||
|
||||
let total_pages = if page_size > 0 { total.div_ceil(page_size) } else { 0 };
|
||||
let total_pages = if page_size > 0 {
|
||||
total.div_ceil(page_size)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
Ok(axum::Json(ApiResponse::ok(PaginatedResponse {
|
||||
data: items,
|
||||
@@ -81,13 +84,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.critical-alerts.manage")?;
|
||||
critical_alert_service::acknowledge_alert(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
ctx.user_id,
|
||||
body.notes,
|
||||
)
|
||||
.await?;
|
||||
Ok(axum::Json(ApiResponse::ok(serde_json::json!({"message": "告警已确认"}))))
|
||||
critical_alert_service::acknowledge_alert(&state, ctx.tenant_id, id, ctx.user_id, body.notes)
|
||||
.await?;
|
||||
Ok(axum::Json(ApiResponse::ok(
|
||||
serde_json::json!({"message": "告警已确认"}),
|
||||
)))
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, State};
|
||||
use serde::Deserialize;
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, TenantContext};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::service::critical_value_threshold_service;
|
||||
use crate::state::HealthState;
|
||||
@@ -105,8 +105,13 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.critical-value-thresholds.manage")?;
|
||||
critical_value_threshold_service::delete_threshold(&state.db, ctx.tenant_id, id, Some(ctx.user_id))
|
||||
.await?;
|
||||
critical_value_threshold_service::delete_threshold(
|
||||
&state.db,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::daily_monitoring_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::daily_monitoring_dto::*;
|
||||
use crate::service::daily_monitoring_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -40,7 +40,11 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = daily_monitoring_service::list_daily_monitoring(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -56,10 +60,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.daily-monitoring.list")?;
|
||||
let result = daily_monitoring_service::get_daily_monitoring(
|
||||
&state, ctx.tenant_id, record_id,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
daily_monitoring_service::get_daily_monitoring(&state, ctx.tenant_id, record_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -76,7 +78,10 @@ where
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = daily_monitoring_service::create_daily_monitoring(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -96,7 +101,12 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = daily_monitoring_service::update_daily_monitoring(
|
||||
&state, ctx.tenant_id, record_id, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
record_id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -114,7 +124,11 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.daily-monitoring.manage")?;
|
||||
daily_monitoring_service::delete_daily_monitoring(
|
||||
&state, ctx.tenant_id, record_id, Some(ctx.user_id), req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
record_id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! 设备管理 API — 设备列表查询与解绑
|
||||
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Path, Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::Extension;
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
use uuid::Uuid;
|
||||
@@ -72,14 +72,8 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.devices.manage")?;
|
||||
|
||||
let device = device_service::unbind_device(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
ctx.user_id,
|
||||
body.version,
|
||||
)
|
||||
.await?;
|
||||
let device =
|
||||
device_service::unbind_device(&state, ctx.tenant_id, id, ctx.user_id, body.version).await?;
|
||||
|
||||
Ok(axum::Json(ApiResponse::ok(device)))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Path, Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::Extension;
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
use uuid::Uuid;
|
||||
@@ -44,9 +44,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.device-readings.manage")?;
|
||||
let result = device_reading_service::batch_create_readings(
|
||||
&state, ctx.tenant_id, path.patient_id, body,
|
||||
).await?;
|
||||
let result =
|
||||
device_reading_service::batch_create_readings(&state, ctx.tenant_id, path.patient_id, body)
|
||||
.await?;
|
||||
Ok(axum::Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -64,9 +64,15 @@ where
|
||||
let page = query.page.unwrap_or(1);
|
||||
let page_size = query.page_size.unwrap_or(20);
|
||||
let result = device_reading_service::query_device_readings(
|
||||
&state, ctx.tenant_id, path.patient_id,
|
||||
query.device_type.as_deref(), query.hours, page, page_size,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
path.patient_id,
|
||||
query.device_type.as_deref(),
|
||||
query.hours,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(axum::Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -85,8 +91,14 @@ where
|
||||
let page_size = query.page_size.unwrap_or(20);
|
||||
let days = query.days.unwrap_or(7);
|
||||
let result = device_reading_service::query_hourly_readings(
|
||||
&state, ctx.tenant_id, path.patient_id,
|
||||
&query.device_type, days, page, page_size,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
path.patient_id,
|
||||
&query.device_type,
|
||||
days,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(axum::Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use serde::Deserialize;
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::dto::diagnosis_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::diagnosis_dto::*;
|
||||
use crate::service::diagnosis_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -29,10 +29,9 @@ where
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = diagnosis_service::list_diagnoses(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
diagnosis_service::list_diagnoses(&state, ctx.tenant_id, patient_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -50,7 +49,11 @@ where
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = diagnosis_service::create_diagnosis(
|
||||
&state, ctx.tenant_id, patient_id, Some(ctx.user_id), req,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -70,7 +73,12 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = diagnosis_service::update_diagnosis(
|
||||
&state, ctx.tenant_id, diagnosis_id, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
diagnosis_id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -88,7 +96,11 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
diagnosis_service::delete_diagnosis(
|
||||
&state, ctx.tenant_id, diagnosis_id, Some(ctx.user_id), req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
diagnosis_id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
|
||||
@@ -8,8 +8,8 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::doctor_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::doctor_dto::*;
|
||||
use crate::service::doctor_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -42,7 +42,13 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = doctor_service::list_doctors(
|
||||
&state, ctx.tenant_id, page, page_size, params.search, params.department, params.title,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.search,
|
||||
params.department,
|
||||
params.title,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -60,10 +66,8 @@ where
|
||||
require_permission(&ctx, "health.doctor.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = doctor_service::create_doctor(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
doctor_service::create_doctor(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -95,7 +99,12 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = doctor_service::update_doctor(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -112,6 +121,7 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.doctor.manage")?;
|
||||
doctor_service::delete_doctor(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?;
|
||||
doctor_service::delete_doctor(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! 家庭成员健康代理 Handler — 同意管理 + 健康摘要查看
|
||||
|
||||
use axum::extract::{Json, Path, Query, State};
|
||||
use axum::Extension;
|
||||
use axum::extract::{Json, Path, Query, State};
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, TenantContext};
|
||||
@@ -27,9 +27,15 @@ pub async fn grant_family_access(
|
||||
) -> Result<Json<ApiResponse<FamilyMemberResp>>, AppError> {
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
let result = family_proxy_service::grant_family_access(
|
||||
&state, ctx.tenant_id, patient_id, family_member_id,
|
||||
Some(ctx.user_id), req, params.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
family_member_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
params.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -42,9 +48,14 @@ pub async fn revoke_family_access(
|
||||
) -> Result<Json<ApiResponse<FamilyMemberResp>>, AppError> {
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
let result = family_proxy_service::revoke_family_access(
|
||||
&state, ctx.tenant_id, patient_id, family_member_id,
|
||||
Some(ctx.user_id), params.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
family_member_id,
|
||||
Some(ctx.user_id),
|
||||
params.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -53,9 +64,8 @@ pub async fn list_my_family_patients(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
) -> Result<Json<ApiResponse<Vec<FamilyPatientSummaryResp>>>, AppError> {
|
||||
let result = family_proxy_service::list_family_patients(
|
||||
&state, ctx.tenant_id, ctx.user_id,
|
||||
).await?;
|
||||
let result =
|
||||
family_proxy_service::list_family_patients(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -66,8 +76,12 @@ pub async fn get_family_health_summary(
|
||||
Path(patient_id): Path<Uuid>,
|
||||
) -> Result<Json<ApiResponse<FamilyHealthSummaryResp>>, AppError> {
|
||||
let result = family_proxy_service::get_family_health_summary(
|
||||
&state, ctx.tenant_id, ctx.user_id, patient_id,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
ctx.user_id,
|
||||
patient_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -78,7 +92,11 @@ pub async fn link_family_member_user(
|
||||
Path(family_member_id): Path<Uuid>,
|
||||
) -> Result<Json<ApiResponse<FamilyMemberResp>>, AppError> {
|
||||
let result = family_proxy_service::link_family_member_user(
|
||||
&state, ctx.tenant_id, family_member_id, ctx.user_id,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
family_member_id,
|
||||
ctx.user_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::follow_up_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::follow_up_dto::*;
|
||||
use crate::service::follow_up_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -33,10 +33,9 @@ where
|
||||
if req.patient_ids.len() > 100 {
|
||||
return Err(AppError::Validation("单次批量最多 100 条".to_string()));
|
||||
}
|
||||
let result = follow_up_service::batch_create_tasks(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
follow_up_service::batch_create_tasks(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -56,10 +55,9 @@ where
|
||||
if req.task_ids.len() > 100 {
|
||||
return Err(AppError::Validation("单次批量最多 100 条".to_string()));
|
||||
}
|
||||
let result = follow_up_service::batch_assign_tasks(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
follow_up_service::batch_assign_tasks(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -79,10 +77,9 @@ where
|
||||
if req.task_ids.len() > 100 {
|
||||
return Err(AppError::Validation("单次批量最多 100 条".to_string()));
|
||||
}
|
||||
let result = follow_up_service::batch_complete_tasks(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
follow_up_service::batch_complete_tasks(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -123,7 +120,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = follow_up_service::list_tasks(
|
||||
&state, ctx.tenant_id, page, page_size, params.patient_id, params.assigned_to,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.patient_id,
|
||||
params.assigned_to,
|
||||
params.status,
|
||||
)
|
||||
.await?;
|
||||
@@ -156,10 +158,8 @@ where
|
||||
require_permission(&ctx, "health.follow-up.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = follow_up_service::create_task(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
follow_up_service::create_task(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -177,7 +177,12 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = follow_up_service::update_task(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -194,7 +199,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.follow-up.manage")?;
|
||||
follow_up_service::delete_task(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?;
|
||||
follow_up_service::delete_task(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -210,14 +216,14 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.follow-up.manage")?;
|
||||
if req.task_id != task_id {
|
||||
return Err(AppError::Validation("路径中的 task_id 与请求体不一致".to_string()));
|
||||
return Err(AppError::Validation(
|
||||
"路径中的 task_id 与请求体不一致".to_string(),
|
||||
));
|
||||
}
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = follow_up_service::create_record(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
follow_up_service::create_record(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -234,7 +240,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = follow_up_service::list_records(
|
||||
&state, ctx.tenant_id, page, page_size, params.task_id, params.patient_id,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.task_id,
|
||||
params.patient_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
|
||||
@@ -8,8 +8,8 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::follow_up_template_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::follow_up_template_dto::*;
|
||||
use crate::service::follow_up_template_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -41,7 +41,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = follow_up_template_service::list_templates(
|
||||
&state, ctx.tenant_id, page, page_size, params.follow_up_type, params.status,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.follow_up_type,
|
||||
params.status,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -73,10 +78,9 @@ where
|
||||
require_permission(&ctx, "health.follow-up-templates.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = follow_up_template_service::create_template(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
follow_up_template_service::create_template(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -94,7 +98,12 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = follow_up_template_service::update_template(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -112,7 +121,11 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.follow-up-templates.manage")?;
|
||||
follow_up_template_service::delete_template(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
|
||||
@@ -8,8 +8,8 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::health_data_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::health_data_dto::*;
|
||||
use crate::service::health_data_service;
|
||||
use crate::service::trend_service;
|
||||
use crate::state::HealthState;
|
||||
@@ -59,10 +59,9 @@ where
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = health_data_service::list_vital_signs(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
health_data_service::list_vital_signs(&state, ctx.tenant_id, patient_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -80,7 +79,11 @@ where
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = health_data_service::create_vital_signs(
|
||||
&state, ctx.tenant_id, patient_id, Some(ctx.user_id), req,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -100,7 +103,13 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = health_data_service::update_vital_signs(
|
||||
&state, ctx.tenant_id, patient_id, vid, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
vid,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -117,7 +126,14 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
health_data_service::delete_vital_signs(&state, ctx.tenant_id, vid, Some(ctx.user_id), req.version).await?;
|
||||
health_data_service::delete_vital_signs(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
vid,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -138,10 +154,9 @@ where
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = health_data_service::list_lab_reports(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
health_data_service::list_lab_reports(&state, ctx.tenant_id, patient_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -159,7 +174,11 @@ where
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = health_data_service::create_lab_report(
|
||||
&state, ctx.tenant_id, patient_id, Some(ctx.user_id), req,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -179,7 +198,13 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = health_data_service::update_lab_report(
|
||||
&state, ctx.tenant_id, _patient_id, rid, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
_patient_id,
|
||||
rid,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -196,7 +221,14 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
health_data_service::delete_lab_report(&state, ctx.tenant_id, rid, Some(ctx.user_id), req.version).await?;
|
||||
health_data_service::delete_lab_report(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
rid,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -214,7 +246,13 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = health_data_service::review_lab_report(
|
||||
&state, ctx.tenant_id, _patient_id, rid, ctx.user_id, data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
_patient_id,
|
||||
rid,
|
||||
ctx.user_id,
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -238,7 +276,11 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = health_data_service::list_health_records(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -258,7 +300,11 @@ where
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = health_data_service::create_health_record(
|
||||
&state, ctx.tenant_id, patient_id, Some(ctx.user_id), req,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -278,7 +324,13 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = health_data_service::update_health_record(
|
||||
&state, ctx.tenant_id, patient_id, rid, Some(ctx.user_id), data, req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
rid,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -295,7 +347,14 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
health_data_service::delete_health_record(&state, ctx.tenant_id, rid, Some(ctx.user_id), req.version).await?;
|
||||
health_data_service::delete_health_record(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
rid,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -316,10 +375,8 @@ where
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = trend_service::list_trends(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
trend_service::list_trends(&state, ctx.tenant_id, patient_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -335,7 +392,12 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
let result = trend_service::generate_trend(
|
||||
&state, ctx.tenant_id, patient_id, Some(ctx.user_id), req.period_start, req.period_end,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
Some(ctx.user_id),
|
||||
req.period_start,
|
||||
req.period_end,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -353,7 +415,12 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let result = trend_service::get_indicator_timeseries(
|
||||
&state, ctx.tenant_id, patient_id, indicator, params.start_date, params.end_date,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
indicator,
|
||||
params.start_date,
|
||||
params.end_date,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -374,7 +441,11 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let result = trend_service::get_mini_trend(
|
||||
&state, ctx.tenant_id, ctx.user_id, params.indicator, params.range,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
ctx.user_id,
|
||||
params.indicator,
|
||||
params.range,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -394,10 +465,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
let result = trend_service::get_mini_today(
|
||||
&state, ctx.tenant_id, ctx.user_id, params.patient_id,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
trend_service::get_mini_today(&state, ctx.tenant_id, ctx.user_id, params.patient_id)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use serde::Deserialize;
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::dto::medication_record_dto::*;
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::medication_record_dto::*;
|
||||
use crate::service::medication_record_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -31,7 +31,11 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = medication_record_service::list_medications(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -66,13 +70,9 @@ where
|
||||
require_permission(&ctx, "health.medication-records.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = medication_record_service::create_medication(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
Some(ctx.user_id),
|
||||
req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
medication_record_service::create_medication(&state, ctx.tenant_id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::medication_reminder_dto::{CreateMedicationReminderReq, MedicationReminderResp, UpdateMedicationReminderReq};
|
||||
use crate::dto::medication_reminder_dto::{
|
||||
CreateMedicationReminderReq, MedicationReminderResp, UpdateMedicationReminderReq,
|
||||
};
|
||||
use crate::service::medication_reminder_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -28,8 +30,13 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = medication_reminder_service::list_reminders(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -45,8 +52,12 @@ where
|
||||
require_permission(&ctx, "health.medication-reminders.manage")?;
|
||||
req.sanitize();
|
||||
let result = medication_reminder_service::create_reminder(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req.0,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
Some(ctx.user_id),
|
||||
req.0,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -71,8 +82,14 @@ where
|
||||
let mut data = req.data;
|
||||
data.sanitize();
|
||||
let result = medication_reminder_service::update_reminder(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version, data,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
data,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -93,7 +110,12 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.medication-reminders.manage")?;
|
||||
medication_reminder_service::delete_reminder(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
pub mod action_inbox_handler;
|
||||
pub mod alert_handler;
|
||||
pub mod ble_gateway_handler;
|
||||
pub mod alert_rule_handler;
|
||||
pub mod appointment_handler;
|
||||
pub mod article_category_handler;
|
||||
pub mod article_handler;
|
||||
pub mod article_tag_handler;
|
||||
pub mod ble_gateway_handler;
|
||||
pub mod care_plan_handler;
|
||||
pub mod consultation_handler;
|
||||
pub mod consent_handler;
|
||||
pub mod consultation_handler;
|
||||
pub mod critical_alert_handler;
|
||||
pub mod critical_value_threshold_handler;
|
||||
pub mod daily_monitoring_handler;
|
||||
pub mod device_handler;
|
||||
pub mod device_reading_handler;
|
||||
pub mod diagnosis_handler;
|
||||
pub mod family_proxy_handler;
|
||||
pub mod medication_record_handler;
|
||||
pub mod medication_reminder_handler;
|
||||
pub mod doctor_handler;
|
||||
pub mod family_proxy_handler;
|
||||
pub mod follow_up_handler;
|
||||
pub mod follow_up_template_handler;
|
||||
pub mod health_data_handler;
|
||||
pub mod medication_record_handler;
|
||||
pub mod medication_reminder_handler;
|
||||
pub mod patient_handler;
|
||||
pub mod points_handler;
|
||||
pub mod stats_handler;
|
||||
pub mod shift_handler;
|
||||
pub mod stats_handler;
|
||||
pub mod vital_signs_daily_handler;
|
||||
|
||||
@@ -8,11 +8,11 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::dto::patient_dto::{
|
||||
CreatePatientReq, FamilyMemberReq, FamilyMemberResp, ManageTagsReq, PatientResp,
|
||||
UpdatePatientReq,
|
||||
};
|
||||
use crate::dto::DeleteWithVersion;
|
||||
use crate::service::patient_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
@@ -44,7 +44,12 @@ where
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = patient_service::list_patients(
|
||||
&state, ctx.tenant_id, page, page_size, params.search, params.tag_id,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
page,
|
||||
page_size,
|
||||
params.search,
|
||||
params.tag_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -62,10 +67,11 @@ where
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = patient_service::create_patient(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
if req.name.trim().is_empty() {
|
||||
return Err(AppError::Validation("患者姓名不能为空".into()));
|
||||
}
|
||||
let result =
|
||||
patient_service::create_patient(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -112,7 +118,12 @@ where
|
||||
};
|
||||
update.sanitize();
|
||||
let result = patient_service::update_patient(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), update, version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
update,
|
||||
version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -129,7 +140,8 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
patient_service::delete_patient(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?;
|
||||
patient_service::delete_patient(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -189,10 +201,9 @@ where
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = patient_service::create_family_member(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
patient_service::create_family_member(&state, ctx.tenant_id, id, Some(ctx.user_id), req)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -217,7 +228,13 @@ where
|
||||
};
|
||||
update.sanitize();
|
||||
let result = patient_service::update_family_member(
|
||||
&state, ctx.tenant_id, _patient_id, member_id, Some(ctx.user_id), update, version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
_patient_id,
|
||||
member_id,
|
||||
Some(ctx.user_id),
|
||||
update,
|
||||
version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -235,7 +252,12 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
patient_service::delete_family_member(
|
||||
&state, ctx.tenant_id, patient_id, member_id, Some(ctx.user_id), req.version,
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
member_id,
|
||||
Some(ctx.user_id),
|
||||
req.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
@@ -257,7 +279,8 @@ where
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
req.doctor_id,
|
||||
req.relationship_type.unwrap_or_else(|| "primary".to_string()),
|
||||
req.relationship_type
|
||||
.unwrap_or_else(|| "primary".to_string()),
|
||||
Some(ctx.user_id),
|
||||
)
|
||||
.await?;
|
||||
@@ -274,7 +297,14 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
patient_service::remove_doctor(&state, ctx.tenant_id, patient_id, doctor_id, Some(ctx.user_id)).await?;
|
||||
patient_service::remove_doctor(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
patient_id,
|
||||
doctor_id,
|
||||
Some(ctx.user_id),
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -338,11 +368,16 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
let result = patient_service::create_tag(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id),
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
Some(ctx.user_id),
|
||||
patient_service::CreateTagReq {
|
||||
name: req.name, color: req.color, description: req.description,
|
||||
name: req.name,
|
||||
color: req.color,
|
||||
description: req.description,
|
||||
},
|
||||
).await?;
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -366,11 +401,18 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
let result = patient_service::update_tag(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id),
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
id,
|
||||
Some(ctx.user_id),
|
||||
patient_service::UpdateTagReq {
|
||||
name: req.name, color: req.color, description: req.description, version: req.version,
|
||||
name: req.name,
|
||||
color: req.color,
|
||||
description: req.description,
|
||||
version: req.version,
|
||||
},
|
||||
).await?;
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -385,8 +427,6 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.manage")?;
|
||||
patient_service::delete_tag(
|
||||
&state, ctx.tenant_id, id, Some(ctx.user_id), req.version,
|
||||
).await?;
|
||||
patient_service::delete_tag(&state, ctx.tenant_id, id, Some(ctx.user_id), req.version).await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -36,9 +36,11 @@ pub async fn get_my_account<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
) -> Result<Json<ApiResponse<PointsAccountResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
let result = points_service::get_account(&state, ctx.tenant_id, patient_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -48,13 +50,14 @@ pub async fn daily_checkin<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
) -> Result<Json<ApiResponse<CheckinStatusResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
let result = points_service::daily_checkin(
|
||||
&state, ctx.tenant_id, patient_id, Some(ctx.user_id),
|
||||
).await?;
|
||||
let result =
|
||||
points_service::daily_checkin(&state, ctx.tenant_id, patient_id, Some(ctx.user_id)).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -62,9 +65,11 @@ pub async fn get_checkin_status<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
) -> Result<Json<ApiResponse<CheckinStatusResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
let result = points_service::get_checkin_status(&state, ctx.tenant_id, patient_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
@@ -79,15 +84,17 @@ pub async fn list_my_transactions<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<PaginationParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PointsTransactionResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = points_service::list_transactions(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::list_transactions(&state, ctx.tenant_id, patient_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -97,14 +104,15 @@ pub async fn list_products<S>(
|
||||
Query(params): Query<ProductTypeParam>,
|
||||
Query(page): Query<PaginationParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PointsProductResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let p = page.page.unwrap_or(1);
|
||||
let ps = page.page_size.unwrap_or(20);
|
||||
let result = points_service::list_products(
|
||||
&state, ctx.tenant_id, params.product_type, p, ps,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::list_products(&state, ctx.tenant_id, params.product_type, p, ps).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -113,9 +121,11 @@ pub async fn get_product<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(product_id): Path<Uuid>,
|
||||
) -> Result<Json<ApiResponse<PointsProductResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let result = points_service::get_product(&state, ctx.tenant_id, product_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
@@ -125,13 +135,15 @@ pub async fn exchange_product<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<ExchangeReq>,
|
||||
) -> Result<Json<ApiResponse<PointsOrderResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
let result = points_service::exchange_product(
|
||||
&state, ctx.tenant_id, patient_id, req, Some(ctx.user_id),
|
||||
).await?;
|
||||
let result =
|
||||
points_service::exchange_product(&state, ctx.tenant_id, patient_id, req, Some(ctx.user_id))
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -140,15 +152,16 @@ pub async fn list_my_orders<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<PaginationParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PointsOrderResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = points_service::list_orders(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::list_orders(&state, ctx.tenant_id, patient_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -161,14 +174,15 @@ pub async fn list_offline_events<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<PaginationParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<OfflineEventResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.list")?;
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = points_service::list_offline_events(
|
||||
&state, ctx.tenant_id, page, page_size,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::list_offline_events(&state, ctx.tenant_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -177,13 +191,20 @@ pub async fn register_event<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(event_id): Path<Uuid>,
|
||||
) -> Result<Json<ApiResponse<()>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.health-data.manage")?;
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let patient_id = resolve_patient_id(&state, ctx.tenant_id, ctx.user_id).await?;
|
||||
points_service::register_event(
|
||||
&state, ctx.tenant_id, event_id, patient_id, Some(ctx.user_id),
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
event_id,
|
||||
patient_id,
|
||||
Some(ctx.user_id),
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -196,12 +217,13 @@ pub async fn verify_order<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<VerifyOrderReq>,
|
||||
) -> Result<Json<ApiResponse<PointsOrderResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let result = points_service::verify_order(
|
||||
&state, ctx.tenant_id, req.qr_code, ctx.user_id,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::verify_order(&state, ctx.tenant_id, req.qr_code, ctx.user_id).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -209,7 +231,9 @@ pub async fn list_rules<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
) -> Result<Json<ApiResponse<Vec<PointsRuleResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let result = points_service::list_rules(&state, ctx.tenant_id).await?;
|
||||
@@ -221,14 +245,14 @@ pub async fn create_rule<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<CreatePointsRuleReq>,
|
||||
) -> Result<Json<ApiResponse<PointsRuleResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = points_service::create_rule(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
).await?;
|
||||
let result = points_service::create_rule(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -238,14 +262,22 @@ pub async fn update_rule<S>(
|
||||
Path(rule_id): Path<Uuid>,
|
||||
Json(wrapper): Json<crate::dto::points_dto::UpdateRuleWithVersion>,
|
||||
) -> Result<Json<ApiResponse<PointsRuleResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let mut data = wrapper.data;
|
||||
data.sanitize();
|
||||
let result = points_service::update_rule(
|
||||
&state, ctx.tenant_id, rule_id, Some(ctx.user_id), data, wrapper.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
rule_id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
wrapper.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -255,12 +287,19 @@ pub async fn delete_rule<S>(
|
||||
Path(rule_id): Path<Uuid>,
|
||||
Json(wrapper): Json<crate::dto::DeleteWithVersion>,
|
||||
) -> Result<Json<ApiResponse<()>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
points_service::delete_rule(
|
||||
&state, ctx.tenant_id, rule_id, Some(ctx.user_id), wrapper.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
rule_id,
|
||||
Some(ctx.user_id),
|
||||
wrapper.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -271,14 +310,22 @@ pub async fn admin_list_products<S>(
|
||||
Query(page): Query<PaginationParams>,
|
||||
Query(filter): Query<AdminProductFilter>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PointsProductResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let p = page.page.unwrap_or(1);
|
||||
let ps = page.page_size.unwrap_or(20);
|
||||
let result = points_service::admin_list_products(
|
||||
&state, ctx.tenant_id, params.product_type, filter.is_active, p, ps,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
params.product_type,
|
||||
filter.is_active,
|
||||
p,
|
||||
ps,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -287,14 +334,15 @@ pub async fn admin_create_product<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<CreatePointsProductReq>,
|
||||
) -> Result<Json<ApiResponse<PointsProductResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = points_service::create_product(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::create_product(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -304,14 +352,22 @@ pub async fn admin_update_product<S>(
|
||||
Path(product_id): Path<Uuid>,
|
||||
Json(wrapper): Json<crate::dto::points_dto::UpdateProductWithVersion>,
|
||||
) -> Result<Json<ApiResponse<PointsProductResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let mut data = wrapper.data;
|
||||
data.sanitize();
|
||||
let result = points_service::update_product(
|
||||
&state, ctx.tenant_id, product_id, Some(ctx.user_id), data, wrapper.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
product_id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
wrapper.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -321,12 +377,19 @@ pub async fn admin_delete_product<S>(
|
||||
Path(product_id): Path<Uuid>,
|
||||
Json(wrapper): Json<crate::dto::DeleteWithVersion>,
|
||||
) -> Result<Json<ApiResponse<()>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
points_service::delete_product(
|
||||
&state, ctx.tenant_id, product_id, Some(ctx.user_id), wrapper.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
product_id,
|
||||
Some(ctx.user_id),
|
||||
wrapper.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -335,15 +398,15 @@ pub async fn admin_list_orders<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<PaginationParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PointsOrderResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
// 管理端查看所有订单 — 不按 patient_id 过滤
|
||||
let result = points_service::admin_list_orders(
|
||||
&state, ctx.tenant_id, page, page_size,
|
||||
).await?;
|
||||
let result = points_service::admin_list_orders(&state, ctx.tenant_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -356,14 +419,15 @@ pub async fn admin_create_event<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Json(req): Json<CreateOfflineEventReq>,
|
||||
) -> Result<Json<ApiResponse<OfflineEventResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let mut req = req;
|
||||
req.sanitize();
|
||||
let result = points_service::create_offline_event(
|
||||
&state, ctx.tenant_id, Some(ctx.user_id), req,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::create_offline_event(&state, ctx.tenant_id, Some(ctx.user_id), req).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -373,14 +437,22 @@ pub async fn admin_update_event<S>(
|
||||
Path(event_id): Path<Uuid>,
|
||||
Json(wrapper): Json<UpdateOfflineEventWithVersion>,
|
||||
) -> Result<Json<ApiResponse<OfflineEventResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
let mut data = wrapper.data;
|
||||
data.sanitize();
|
||||
let result = points_service::update_offline_event(
|
||||
&state, ctx.tenant_id, event_id, Some(ctx.user_id), data, wrapper.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
event_id,
|
||||
Some(ctx.user_id),
|
||||
data,
|
||||
wrapper.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -390,12 +462,19 @@ pub async fn admin_delete_event<S>(
|
||||
Path(event_id): Path<Uuid>,
|
||||
Json(wrapper): Json<crate::dto::DeleteWithVersion>,
|
||||
) -> Result<Json<ApiResponse<()>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
points_service::delete_offline_event(
|
||||
&state, ctx.tenant_id, event_id, Some(ctx.user_id), wrapper.version,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
event_id,
|
||||
Some(ctx.user_id),
|
||||
wrapper.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -411,14 +490,21 @@ pub async fn admin_list_events<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<AdminListEventsParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<OfflineEventResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = points_service::admin_list_offline_events(
|
||||
&state, ctx.tenant_id, params.status, page, page_size,
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
params.status,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -428,12 +514,19 @@ pub async fn admin_checkin_event<S>(
|
||||
Path(event_id): Path<Uuid>,
|
||||
Json(req): Json<AdminCheckinReq>,
|
||||
) -> Result<Json<ApiResponse<()>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.manage")?;
|
||||
points_service::admin_checkin_event(
|
||||
&state, ctx.tenant_id, event_id, req.patient_id, Some(ctx.user_id),
|
||||
).await?;
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
event_id,
|
||||
req.patient_id,
|
||||
Some(ctx.user_id),
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -445,7 +538,9 @@ pub async fn get_points_statistics<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
) -> Result<Json<ApiResponse<PointsStatisticsResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let result = points_service::get_points_statistics(&state, ctx.tenant_id).await?;
|
||||
@@ -461,7 +556,9 @@ pub async fn admin_get_patient_account<S>(
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(patient_id): Path<Uuid>,
|
||||
) -> Result<Json<ApiResponse<PointsAccountResp>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let result = points_service::get_account(&state, ctx.tenant_id, patient_id).await?;
|
||||
@@ -474,14 +571,16 @@ pub async fn admin_list_patient_transactions<S>(
|
||||
Path(patient_id): Path<Uuid>,
|
||||
Query(params): Query<PaginationParams>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<PointsTransactionResp>>>, AppError>
|
||||
where HealthState: FromRef<S>, S: Clone + Send + Sync + 'static,
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.points.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = points_service::list_transactions(
|
||||
&state, ctx.tenant_id, patient_id, page, page_size,
|
||||
).await?;
|
||||
let result =
|
||||
points_service::list_transactions(&state, ctx.tenant_id, patient_id, page, page_size)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Json, Path, Query, State};
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, TenantContext};
|
||||
@@ -58,7 +58,8 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
body.sanitize();
|
||||
let result = shift_service::create_shift(&state, ctx.tenant_id, Some(ctx.user_id), body).await?;
|
||||
let result =
|
||||
shift_service::create_shift(&state, ctx.tenant_id, Some(ctx.user_id), body).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -73,7 +74,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
let result = shift_service::update_shift(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), body).await?;
|
||||
let result =
|
||||
shift_service::update_shift(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), body)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -88,7 +91,14 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
shift_service::delete_shift(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), params.version).await?;
|
||||
shift_service::delete_shift(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
shift_id,
|
||||
Some(ctx.user_id),
|
||||
params.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -109,7 +119,8 @@ where
|
||||
require_permission(&ctx, "health.shifts.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = shift_service::list_assignments(&state, ctx.tenant_id, shift_id, page, page_size).await?;
|
||||
let result =
|
||||
shift_service::list_assignments(&state, ctx.tenant_id, shift_id, page, page_size).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -125,7 +136,9 @@ where
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
body.sanitize();
|
||||
let result = shift_service::create_assignment(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), body).await?;
|
||||
let result =
|
||||
shift_service::create_assignment(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), body)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -140,7 +153,9 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
let result = shift_service::batch_assign(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), body).await?;
|
||||
let result =
|
||||
shift_service::batch_assign(&state, ctx.tenant_id, shift_id, Some(ctx.user_id), body)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -155,7 +170,15 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
let result = shift_service::update_assignment(&state, ctx.tenant_id, shift_id, assignment_id, Some(ctx.user_id), body).await?;
|
||||
let result = shift_service::update_assignment(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
shift_id,
|
||||
assignment_id,
|
||||
Some(ctx.user_id),
|
||||
body,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -170,7 +193,15 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
shift_service::delete_assignment(&state, ctx.tenant_id, shift_id, assignment_id, Some(ctx.user_id), params.version).await?;
|
||||
shift_service::delete_assignment(
|
||||
&state,
|
||||
ctx.tenant_id,
|
||||
shift_id,
|
||||
assignment_id,
|
||||
Some(ctx.user_id),
|
||||
params.version,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
@@ -202,6 +233,7 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.shifts.manage")?;
|
||||
let result = shift_service::create_handoff(&state, ctx.tenant_id, Some(ctx.user_id), body).await?;
|
||||
let result =
|
||||
shift_service::create_handoff(&state, ctx.tenant_id, Some(ctx.user_id), body).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ use erp_core::error::AppError;
|
||||
use erp_core::rbac::require_permission;
|
||||
use erp_core::types::{ApiResponse, TenantContext};
|
||||
|
||||
use crate::service::stats_service;
|
||||
use crate::dto::stats_dto::*;
|
||||
use crate::service::stats_service;
|
||||
use crate::state::HealthState;
|
||||
|
||||
pub async fn get_patient_stats<S>(
|
||||
@@ -56,9 +56,44 @@ where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.patient.list")?;
|
||||
let patients = stats_service::get_patient_statistics(&state, ctx.tenant_id).await?;
|
||||
let consultations = stats_service::get_consultation_statistics(&state, ctx.tenant_id).await?;
|
||||
let follow_ups = stats_service::get_follow_up_statistics(&state, ctx.tenant_id).await?;
|
||||
|
||||
let patients = stats_service::get_patient_statistics(&state, ctx.tenant_id)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
tracing::warn!("仪表盘患者统计查询失败: {e}");
|
||||
PatientStatisticsResp {
|
||||
total_patients: 0,
|
||||
new_this_month: 0,
|
||||
new_this_week: 0,
|
||||
active_this_month: 0,
|
||||
}
|
||||
});
|
||||
|
||||
let consultations = stats_service::get_consultation_statistics(&state, ctx.tenant_id)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
tracing::warn!("仪表盘咨询统计查询失败: {e}");
|
||||
ConsultationStatisticsResp {
|
||||
total_sessions: 0,
|
||||
pending_reply: 0,
|
||||
avg_response_time_minutes: None,
|
||||
this_month: 0,
|
||||
}
|
||||
});
|
||||
|
||||
let follow_ups = stats_service::get_follow_up_statistics(&state, ctx.tenant_id)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
tracing::warn!("仪表盘随访统计查询失败: {e}");
|
||||
FollowUpStatisticsResp {
|
||||
total_tasks: 0,
|
||||
completed: 0,
|
||||
pending: 0,
|
||||
overdue: 0,
|
||||
completion_rate: 0.0,
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Json(ApiResponse::ok(DashboardStatsResp {
|
||||
patients,
|
||||
consultations,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::Extension;
|
||||
use axum::extract::{FromRef, Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::Extension;
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
|
||||
@@ -33,9 +33,10 @@ where
|
||||
let start = query.start_date.parse::<chrono::NaiveDate>().map_err(|_| {
|
||||
AppError::Validation("Invalid start_date format, expected YYYY-MM-DD".into())
|
||||
})?;
|
||||
let end = query.end_date.parse::<chrono::NaiveDate>().map_err(|_| {
|
||||
AppError::Validation("Invalid end_date format, expected YYYY-MM-DD".into())
|
||||
})?;
|
||||
let end = query
|
||||
.end_date
|
||||
.parse::<chrono::NaiveDate>()
|
||||
.map_err(|_| AppError::Validation("Invalid end_date format, expected YYYY-MM-DD".into()))?;
|
||||
|
||||
let results = vital_signs_daily_service::query_daily(
|
||||
&state.db,
|
||||
|
||||
Reference in New Issue
Block a user