```
feat: 添加数据库迁移脚本并更新Dockerfile配置 - 在Dockerfile中添加alembic配置文件和目录的复制指令 - 更新alembic/env.py注册新的模块模型:events、workflows、writebacks - 生成完整的初始数据库schema迁移脚本,包含以下表: - approval_requests, attendance_records, audit_logs, domain_events - expenses, feishu_event_receipts, fund_accounts, legacy_sync_runs - official_writeback_runs, performance_metrics, policies, procurements - projects, report_push_runs, risk_event_actions, risk_events - standards, suppliers, work_reports, work_tasks, workflow_actions - workflow_instances等21个数据表结构定义 - 在API路由器中添加新模块的路由:events、workflows、writebacks、observability ```
This commit is contained in:
@@ -17,9 +17,10 @@ from app.modules.audit.schemas import AuditLogCreate
|
||||
from app.modules.audit.service import AuditService
|
||||
from app.modules.approvals.constants import ApprovalActionValue, approval_action
|
||||
from app.modules.approvals.service import ApprovalService
|
||||
from app.modules.business.registry import get_domain_model, is_high_risk_domain
|
||||
from app.modules.business.registry import get_domain_model, get_writable_fields, is_high_risk_domain
|
||||
from app.modules.business.constants import (
|
||||
INVALID_FIELD_VALUE_TEMPLATE,
|
||||
READ_ONLY_FIELD_TEMPLATE,
|
||||
UNKNOWN_FIELD_TEMPLATE,
|
||||
BusinessErrorDetail,
|
||||
BusinessField,
|
||||
@@ -56,7 +57,7 @@ def _coerce_column_value(column: Column, value: Any) -> Any:
|
||||
return value
|
||||
|
||||
|
||||
def _model_payload(model: Any, data: dict[str, Any]) -> dict[str, Any]:
|
||||
def _model_payload(domain: str, model: Any, data: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Validate keys and coerce values according to model column types."""
|
||||
|
||||
columns = {
|
||||
@@ -64,6 +65,7 @@ def _model_payload(model: Any, data: dict[str, Any]) -> dict[str, Any]:
|
||||
for column in model.__table__.columns
|
||||
if column.name != BusinessField.ID
|
||||
}
|
||||
writable_fields = get_writable_fields(domain)
|
||||
payload: dict[str, Any] = {}
|
||||
for key, value in data.items():
|
||||
column = columns.get(key)
|
||||
@@ -72,6 +74,11 @@ def _model_payload(model: Any, data: dict[str, Any]) -> dict[str, Any]:
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=UNKNOWN_FIELD_TEMPLATE.format(field=key),
|
||||
)
|
||||
if key not in writable_fields:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=READ_ONLY_FIELD_TEMPLATE.format(field=key),
|
||||
)
|
||||
try:
|
||||
payload[key] = _coerce_column_value(column, value)
|
||||
except (ValueError, TypeError, InvalidOperation) as exc:
|
||||
@@ -127,7 +134,7 @@ class BusinessService:
|
||||
) -> dict[str, Any]:
|
||||
model = get_domain_model(domain)
|
||||
high_risk = is_high_risk_domain(domain)
|
||||
payload = _model_payload(model, data)
|
||||
payload = _model_payload(domain, model, data)
|
||||
record = model(**payload)
|
||||
self.db.add(record)
|
||||
if high_risk:
|
||||
@@ -176,7 +183,7 @@ class BusinessService:
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=BusinessErrorDetail.RECORD_NOT_FOUND,
|
||||
)
|
||||
payload = _model_payload(model, data)
|
||||
payload = _model_payload(domain, model, data)
|
||||
if high_risk:
|
||||
self._consume_approval(
|
||||
approval_ticket_id,
|
||||
|
||||
Reference in New Issue
Block a user