feat(health): vital_signs_daily 日聚合表 + Entity + service
- 新增 vital_signs_daily 表迁移(带唯一索引 tenant+patient+device_type+date) - 新增 SeaORM Entity(含 percentile_95 统计字段) - 实现日聚合 service:从 hourly 聚合到 daily(支持 upsert) - 实现 aggregate_daily_for_all_tenants 多租户遍历聚合 - 实现 query_daily 范围查询 - 单元测试:percentile 计算验证
This commit is contained in:
@@ -103,6 +103,7 @@ mod m20260501_000100_seed_action_inbox_menu;
|
||||
mod m20260502_000101_seed_health_dictionaries;
|
||||
mod m20260502_000102_seed_warning_thresholds;
|
||||
mod m20260502_000103_seed_follow_up_template_menu;
|
||||
mod m20260504_000104_create_vital_signs_daily;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
@@ -213,6 +214,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260502_000101_seed_health_dictionaries::Migration),
|
||||
Box::new(m20260502_000102_seed_warning_thresholds::Migration),
|
||||
Box::new(m20260502_000103_seed_follow_up_template_menu::Migration),
|
||||
Box::new(m20260504_000104_create_vital_signs_daily::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(Alias::new("vital_signs_daily"))
|
||||
.col(
|
||||
ColumnDef::new(Alias::new("id"))
|
||||
.uuid()
|
||||
.not_null()
|
||||
.default(Expr::val("gen_random_uuid()")),
|
||||
)
|
||||
.col(ColumnDef::new(Alias::new("tenant_id")).uuid().not_null())
|
||||
.col(ColumnDef::new(Alias::new("patient_id")).uuid().not_null())
|
||||
.col(ColumnDef::new(Alias::new("device_type")).string().not_null())
|
||||
.col(ColumnDef::new(Alias::new("date_bucket")).date().not_null())
|
||||
.col(ColumnDef::new(Alias::new("min_val")).double())
|
||||
.col(ColumnDef::new(Alias::new("max_val")).double())
|
||||
.col(ColumnDef::new(Alias::new("avg_val")).double().not_null())
|
||||
.col(ColumnDef::new(Alias::new("sample_count")).integer().not_null())
|
||||
.col(ColumnDef::new(Alias::new("percentile_95")).double())
|
||||
.col(
|
||||
ColumnDef::new(Alias::new("created_at"))
|
||||
.timestamp_with_time_zone()
|
||||
.not_null()
|
||||
.default(Expr::val("NOW()")),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Alias::new("updated_at"))
|
||||
.timestamp_with_time_zone()
|
||||
.not_null()
|
||||
.default(Expr::val("NOW()")),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Alias::new("version"))
|
||||
.integer()
|
||||
.not_null()
|
||||
.default(1),
|
||||
)
|
||||
.primary_key(Index::create().col(Alias::new("id")))
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("idx_vital_signs_daily_unique")
|
||||
.table(Alias::new("vital_signs_daily"))
|
||||
.col(Alias::new("tenant_id"))
|
||||
.col(Alias::new("patient_id"))
|
||||
.col(Alias::new("device_type"))
|
||||
.col(Alias::new("date_bucket"))
|
||||
.unique()
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Alias::new("vital_signs_daily")).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user