fix: 财务本人报销由总经理独立审批(09-04-reimbursement-state-gap-finance-view)
这个提交包含在:
@@ -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({
|
||||
|
||||
在新工单中引用
屏蔽一个用户