fix: 财务本人报销由总经理独立审批(09-04-reimbursement-state-gap-finance-view)
这个提交包含在:
+37
-1
@@ -1,4 +1,7 @@
|
||||
const { AppError } = require("./AppError");
|
||||
const { buildBusinessValidationError } = require("./businessValidationError");
|
||||
|
||||
const FINANCE_OWNER_APPROVAL_STEP_ID = "approval_1_ceo_finance_owner";
|
||||
|
||||
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
const MAX_MANAGER_DEPTH = 10;
|
||||
@@ -199,8 +202,39 @@ function assertOwnerSelfFallbackRole(roleCode, ownerRoleCodes) {
|
||||
return roleCode;
|
||||
}
|
||||
|
||||
async function buildApprovalWorkflowSnapshot({ tx, approvalRule, ownerId, logger }) {
|
||||
async function buildFinanceOwnerApprovalSnapshot({ tx, ownerId, submitterId }) {
|
||||
const ownerRoleCodes = await loadOwnerRoleCodes(tx, ownerId);
|
||||
if (ownerRoleCodes?.has("finance")) {
|
||||
const applicantIds = [...new Set([ownerId, submitterId].filter(Boolean))];
|
||||
const ceo = await tx.employeeRole.findFirst({
|
||||
where: {
|
||||
role_code: "ceo",
|
||||
employee_id: { notIn: applicantIds },
|
||||
employee: { status: "active", archived_at: null },
|
||||
},
|
||||
select: { employee_id: true },
|
||||
});
|
||||
if (!ceo) {
|
||||
throw buildBusinessValidationError("reimbursement.finance_owner_ceo_unavailable", {
|
||||
workflow: "no_actionable_approver", reason: "finance_owner_ceo_unavailable",
|
||||
}, 409);
|
||||
}
|
||||
return [{
|
||||
id: FINANCE_OWNER_APPROVAL_STEP_ID,
|
||||
name: "总经理审批",
|
||||
type: "approval",
|
||||
assignee_rule: { type: "role", value: "ceo" },
|
||||
}];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function buildApprovalWorkflowSnapshot({ tx, approvalRule, ownerId, submitterId, entityType, logger }) {
|
||||
const rawSteps = buildWorkflowStepsFromApprovalRule(approvalRule);
|
||||
if (entityType === "reimbursement") {
|
||||
const financeOwnerSteps = await buildFinanceOwnerApprovalSnapshot({ tx, ownerId, submitterId });
|
||||
if (financeOwnerSteps) return financeOwnerSteps;
|
||||
}
|
||||
const hasManagerStep = rawSteps.some((step) => isDepartmentManagerRule(step.assignee_rule));
|
||||
|
||||
if (!hasManagerStep || !approvalRule.owner_self_fallback_role) {
|
||||
@@ -567,9 +601,11 @@ function toMoneyString(value) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
FINANCE_OWNER_APPROVAL_STEP_ID,
|
||||
BUSINESS_APPROVAL_ROLE_CODES,
|
||||
OWNER_SELF_FALLBACK_ROLE_CODES,
|
||||
buildApprovalWorkflowSnapshot,
|
||||
buildFinanceOwnerApprovalSnapshot,
|
||||
buildWorkflowStepsFromApprovalRule,
|
||||
getWorkflowStepsSnapshot,
|
||||
isBusinessApprovalRoleCode,
|
||||
|
||||
在新工单中引用
屏蔽一个用户