feat: 本体字段治理与风险规则模板执行器重构

- 新增本体字段注册表与字段治理审计脚本
- 重构风险规则模板执行器、DSL 验证与清单分类器
- 完善票据夹服务与差旅请求详情页交互
- 优化趋势图表与总览页数据展示
- 增强报销平台风险分级与模拟公司筛选
- 补充本体字段、风险规则生成与票据夹服务测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-03 15:46:56 +08:00
parent e12b140508
commit 34457f9c3e
81 changed files with 4858 additions and 1073 deletions

View File

@@ -36,6 +36,7 @@ from app.services.agent_foundation import AgentFoundationService
from app.services.audit import AuditLogService
from app.services.document_intelligence import build_document_insight
from app.services.document_numbering import is_application_claim_no
from app.services.budget_types import BudgetControlError
from app.services.expense_claim_access_policy import ExpenseClaimAccessPolicy
from app.services.expense_claim_approval_flow import ExpenseClaimApprovalFlowMixin
from app.services.expense_claim_approval_routing import ExpenseClaimApprovalRoutingMixin
@@ -57,6 +58,7 @@ from app.services.expense_claim_ontology_resolvers import ExpenseClaimOntologyRe
from app.services.expense_claim_read_model import ExpenseClaimReadModelMixin
from app.services.expense_claim_risk_stage import with_risk_business_stage
from app.services.expense_claim_review_preview import ExpenseClaimReviewPreviewMixin
from app.services.receipt_folder import ReceiptFolderService
from app.services.expense_claim_constants import (
EXPENSE_TYPE_LABELS,
MAX_DRAFT_CLAIMS_PER_USER,
@@ -320,6 +322,8 @@ class ExpenseClaimService(
item.item_location = (
self._normalize_optional_text(payload.item_location, allow_empty=True) or ""
)
if payload.item_note is not None:
item.item_note = self._normalize_optional_text(payload.item_note, allow_empty=True) or ""
if payload.item_amount is not None:
amount = payload.item_amount.quantize(Decimal("0.01"))
if amount < Decimal("0.00"):
@@ -376,6 +380,7 @@ class ExpenseClaimService(
or "other",
item_reason=self._normalize_optional_text(payload.item_reason, fallback="") or "",
item_location=self._normalize_optional_text(payload.item_location, fallback="") or "",
item_note=self._normalize_optional_text(payload.item_note, allow_empty=True) or "",
item_amount=item_amount,
invoice_id=self._normalize_optional_text(payload.invoice_id, allow_empty=True),
)
@@ -462,11 +467,16 @@ class ExpenseClaimService(
if missing_fields:
raise ExpenseClaimSubmissionBlockedError(missing_fields)
budget_flags = self._reserve_budget_for_submission(
claim,
current_user,
is_application_claim=is_application_claim,
)
try:
budget_flags = self._reserve_budget_for_submission(
claim,
current_user,
is_application_claim=is_application_claim,
)
except BudgetControlError as exc:
if is_application_claim:
raise
budget_flags = list(exc.flags or [])
before_json = self._serialize_claim(claim)
if is_application_claim:
submitted_at = datetime.now(UTC)
@@ -576,6 +586,7 @@ class ExpenseClaimService(
self._release_budget_for_delete(claim, current_user)
self._delete_claim_analysis_records(resource_id)
self._attachment_storage.delete_claim_files(claim)
ReceiptFolderService().delete_receipts_for_claim(resource_id)
self.db.delete(claim)
self.db.commit()
@@ -747,11 +758,6 @@ class ExpenseClaimService(