feat: 新增归档中心页面并完善知识库与报销查询能力

新增前端归档中心视图及相关工具函数,扩充知识库文档分类和
提取器支持多种格式,增强编排器报销查询的多维度检索,优
化本体规则和用户代理审核消息,前端完善报销创建和审批详
情交互细节,补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-22 16:00:19 +08:00
parent 1f15699013
commit 88ff04bef8
120 changed files with 6236 additions and 643 deletions

View File

@@ -13,8 +13,10 @@ from app.models.organization import OrganizationUnit
PRIVILEGED_CLAIM_ROLE_CODES = {"finance", "executive"}
ARCHIVE_CENTER_ROLE_CODES = {"finance", "executive", "auditor"}
APPROVAL_VISIBLE_CLAIM_ROLE_CODES = {"manager", "approver"}
CLAIM_DELETE_ROLE_CODES = {"executive"}
ARCHIVED_CLAIM_STATUSES = ("approved", "completed", "paid")
class ExpenseClaimAccessPolicy:
@@ -27,6 +29,30 @@ class ExpenseClaimAccessPolicy:
return True
return bool(ExpenseClaimAccessPolicy.normalize_role_codes(current_user) & PRIVILEGED_CLAIM_ROLE_CODES)
@staticmethod
def has_archive_center_access(current_user: CurrentUserContext) -> bool:
if current_user.is_admin:
return True
return bool(ExpenseClaimAccessPolicy.normalize_role_codes(current_user) & ARCHIVE_CENTER_ROLE_CODES)
@staticmethod
def build_archived_claim_condition() -> Any:
normalized_status = func.lower(func.coalesce(ExpenseClaim.status, ""))
stage = func.coalesce(ExpenseClaim.approval_stage, "")
return or_(
stage == "归档入账",
stage == "completed",
and_(
normalized_status.in_(ARCHIVED_CLAIM_STATUSES),
or_(
stage == "",
stage.is_(None),
stage == "归档入账",
stage == "completed",
),
),
)
@staticmethod
def has_claim_delete_access(current_user: CurrentUserContext) -> bool:
if current_user.is_admin:
@@ -374,7 +400,16 @@ class ExpenseClaimAccessPolicy:
include_approval_scope: bool = False,
) -> Any:
if self.has_privileged_claim_access(current_user):
return stmt
owned_conditions = self.build_personal_claim_conditions(current_user)
archived_condition = self.build_archived_claim_condition()
if owned_conditions:
return stmt.where(
or_(
~archived_condition,
and_(archived_condition, or_(*owned_conditions)),
)
)
return stmt.where(~archived_condition)
conditions = self.build_personal_claim_conditions(current_user)
@@ -386,6 +421,12 @@ class ExpenseClaimAccessPolicy:
return stmt.where(or_(*conditions))
def apply_archived_claim_scope(self, stmt: Any, current_user: CurrentUserContext) -> Any:
if not self.has_archive_center_access(current_user):
return stmt.where(ExpenseClaim.id == "__no_visible_claim__")
return stmt.where(self.build_archived_claim_condition())
@staticmethod
def resolve_claim_manager_name(claim: ExpenseClaim) -> str:
if claim.employee is not None: