fix: 财务本人报销由总经理独立审批(09-04-reimbursement-state-gap-finance-view)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-09-12 20:03:29 +08:00
父节点 31ab9fbb2b
当前提交 229867f5fd
共修改 18 个文件,包含 629 行新增和 20 行删除
+24
查看文件
@@ -4,6 +4,7 @@ const { FEATURE_FLAG_KEYS, evaluateFeatureFlag } = require("./featureFlags");
const { currentDateString, parseDateOnlyString } = require("../utils/date");
const {
buildApprovalWorkflowSnapshot,
buildFinanceOwnerApprovalSnapshot,
parseWorkflowSteps,
resolveActionableStep,
} = require("../utils/workflow");
@@ -92,6 +93,8 @@ async function buildReimbursementOperationalChecks(tx, { reimbursementId, config
where: { id: reimbursementId },
select: {
id: true,
owner_id: true,
submitter_id: true,
items: {
orderBy: [{ created_at: "asc" }, { id: "asc" }],
select: {
@@ -106,6 +109,22 @@ async function buildReimbursementOperationalChecks(tx, { reimbursementId, config
throw buildNotFoundError();
}
const blockingReasons = [];
try {
await buildFinanceOwnerApprovalSnapshot({
tx, ownerId: reimbursement.owner_id, submitterId: reimbursement.submitter_id,
});
} catch (error) {
if (!(error instanceof AppError) || error.details?.reason !== "finance_owner_ceo_unavailable") {
throw error;
}
blockingReasons.push(buildIssue(
"finance_owner_ceo_unavailable",
"缺少非申请人的总经理审批人",
"财务本人报销需由非归属人且非提交人的在职总经理审批,请联系管理员核实审批配置。",
));
}
const [invoices, attachmentCount] = await Promise.all([
tx.invoicePool.findMany({
where: { linked_reimbursement_id: reimbursementId, status: "bound" },
@@ -191,6 +210,7 @@ async function buildReimbursementOperationalChecks(tx, { reimbursementId, config
timelinessChecks,
assetHint: { required: assetItemCount > 0, itemCount: assetItemCount },
warnings,
blockingReasons,
};
}
@@ -200,6 +220,7 @@ function mergeReimbursementOperationalChecks(precheck, operationalChecks) {
evidenceSummary: operationalChecks.evidenceSummary,
timelinessChecks: operationalChecks.timelinessChecks,
assetHint: operationalChecks.assetHint,
blockingReasons: [...precheck.blockingReasons, ...operationalChecks.blockingReasons],
warnings: [...precheck.warnings, ...operationalChecks.warnings],
};
}
@@ -659,6 +680,7 @@ async function buildReimbursementPrecheck(tx, { reimbursementId, config, logger
total_amount: true,
status: true,
owner_id: true,
submitter_id: true,
items: {
select: {
id: true,
@@ -729,6 +751,8 @@ async function buildReimbursementPrecheck(tx, { reimbursementId, config, logger
tx,
approvalRule,
ownerId: reimbursement.owner_id,
submitterId: reimbursement.submitter_id,
entityType: "reimbursement",
logger,
});
const resolved = await resolveActionableStep({