feat: 增强风险规则生成引擎与预算中心页面

后端拆分风险规则生成为解释器、语义分析、本体对齐等子模块,
优化模板执行和流程图生成,完善员工种子数据和导入逻辑,增强
报销单权限策略和草稿持久化,前端新增预算中心视图和趋势图
组件,重构审计页面和风险规则测试对话框交互,完善文档中心
和报销创建页面细节,补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-26 09:15:14 +08:00
parent d0e946cf47
commit 0e861d8fa6
150 changed files with 14953 additions and 4099 deletions

View File

@@ -0,0 +1,53 @@
from __future__ import annotations
from datetime import UTC, date, datetime
from zoneinfo import ZoneInfo
from app.services.employee_serialization import format_history_datetime as serialize_history_datetime
DISPLAY_TIMEZONE = ZoneInfo("Asia/Shanghai")
def normalize_optional_text(value: str | None) -> str | None:
if value is None:
return None
text_value = value.strip()
return text_value or None
def parse_date(value: str | None) -> date | None:
if not value:
return None
return datetime.strptime(value, "%Y-%m-%d").date()
def parse_datetime(value: str | datetime | None) -> datetime | None:
if value is None:
return None
if isinstance(value, datetime):
return value
return datetime.strptime(value, "%Y-%m-%d %H:%M")
def format_date(value: date | None) -> str | None:
if value is None:
return None
return value.strftime("%Y-%m-%d")
def to_display_datetime(value: datetime) -> datetime:
if value.tzinfo is None:
normalized = value.replace(tzinfo=UTC)
else:
normalized = value.astimezone(UTC)
return normalized.astimezone(DISPLAY_TIMEZONE)
def format_datetime(value: datetime | None) -> str | None:
if value is None:
return None
return to_display_datetime(value).strftime("%Y-%m-%d %H:%M")
def format_history_datetime(value: datetime | None) -> str:
return serialize_history_datetime(value, to_display_datetime=to_display_datetime)