feat: 同步报销流程与工作台改动
This commit is contained in:
@@ -250,6 +250,45 @@ class ExpenseClaimAccessPolicy:
|
||||
return role_code
|
||||
return BUDGET_MONITOR_ROLE_CODE
|
||||
|
||||
@staticmethod
|
||||
def resolve_claim_finance_owner_name(claim: ExpenseClaim) -> str:
|
||||
employee = claim.employee
|
||||
if employee is not None and employee.finance_owner_name:
|
||||
return str(employee.finance_owner_name).strip()
|
||||
return ""
|
||||
|
||||
def resolve_finance_approver(self, claim: ExpenseClaim) -> Employee | None:
|
||||
claim_employee_id = str(claim.employee_id or "").strip()
|
||||
base_stmt = (
|
||||
select(Employee)
|
||||
.options(selectinload(Employee.roles))
|
||||
.where(Employee.roles.any(Role.role_code == "finance"))
|
||||
)
|
||||
if claim_employee_id:
|
||||
base_stmt = base_stmt.where(Employee.id != claim_employee_id)
|
||||
|
||||
finance_owner_name = self.resolve_claim_finance_owner_name(claim)
|
||||
if finance_owner_name:
|
||||
named_finance = self.db.scalar(
|
||||
base_stmt
|
||||
.where(Employee.name == finance_owner_name)
|
||||
.order_by(Employee.name.asc(), Employee.employee_no.asc())
|
||||
.limit(1)
|
||||
)
|
||||
if named_finance is not None:
|
||||
return named_finance
|
||||
|
||||
owner_matched_finance = self.db.scalar(
|
||||
base_stmt
|
||||
.where(func.lower(func.coalesce(Employee.finance_owner_name, "")) == finance_owner_name.lower())
|
||||
.order_by(Employee.name.asc(), Employee.employee_no.asc())
|
||||
.limit(1)
|
||||
)
|
||||
if owner_matched_finance is not None:
|
||||
return owner_matched_finance
|
||||
|
||||
return self.db.scalar(base_stmt.order_by(Employee.name.asc(), Employee.employee_no.asc()).limit(1))
|
||||
|
||||
def attach_budget_approval_snapshot(self, claim: ExpenseClaim | None) -> ExpenseClaim | None:
|
||||
if claim is None:
|
||||
return None
|
||||
@@ -269,9 +308,25 @@ class ExpenseClaimAccessPolicy:
|
||||
)
|
||||
return claim
|
||||
|
||||
def attach_finance_approval_snapshot(self, claim: ExpenseClaim | None) -> ExpenseClaim | None:
|
||||
if claim is None:
|
||||
return None
|
||||
if str(claim.approval_stage or "").strip() != FINANCE_APPROVAL_STAGE:
|
||||
return claim
|
||||
|
||||
finance_approver = self.resolve_finance_approver(claim)
|
||||
if finance_approver is not None and finance_approver.name:
|
||||
setattr(claim, "finance_approver_name", str(finance_approver.name).strip())
|
||||
return claim
|
||||
|
||||
def attach_approval_snapshot(self, claim: ExpenseClaim | None) -> ExpenseClaim | None:
|
||||
self.attach_budget_approval_snapshot(claim)
|
||||
self.attach_finance_approval_snapshot(claim)
|
||||
return claim
|
||||
|
||||
def attach_budget_approval_snapshots(self, claims: list[ExpenseClaim]) -> list[ExpenseClaim]:
|
||||
for claim in claims:
|
||||
self.attach_budget_approval_snapshot(claim)
|
||||
self.attach_approval_snapshot(claim)
|
||||
return claims
|
||||
|
||||
@staticmethod
|
||||
@@ -647,6 +702,11 @@ class ExpenseClaimAccessPolicy:
|
||||
*,
|
||||
include_approval_scope: bool = False,
|
||||
) -> Any:
|
||||
if current_user.is_admin:
|
||||
if include_approval_scope:
|
||||
return stmt
|
||||
return stmt.where(~self.build_archived_claim_condition())
|
||||
|
||||
conditions = self.build_personal_claim_conditions(current_user)
|
||||
role_codes = self.normalize_role_codes(current_user)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user