const fs = require("node:fs"); const path = require("node:path"); const ts = require("../../../../client/node_modules/typescript"); const { buildPaymentProcessingSemantics } = require("../../../src/services/paymentProcessingProgress"); const filename = path.resolve(__dirname, "../../../../client/src/lib/reimbursementPaymentHandoff.ts"); const compiled = ts.transpileModule(fs.readFileSync(filename, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 }, }).outputText; const clientModule = { exports: {} }; new Function("exports", compiled)(clientModule.exports); const { resolveReimbursementPaymentHandoff } = clientModule.exports; function project(status, options = {}) { const stages = Object.values(buildPaymentProcessingSemantics({ status, ...options })); return { stages: stages.map((stage) => ({ ...stage, actorName: null, targetHref: null })) }; } describe("报销付款下一步消费服务端阶段,不猜测批次存在性", () => { it.each([ ["draft", {}, "待非制单人复核付款"], ["reviewed", { requiresBankReceipt: true }, "等待财务线下付款并上传回单,非审批环节"], ["reviewed", { requiresBankReceipt: true, paymentOrderExportCount: 1 }, "已生成银行制单,等待付款完成并上传回单,非审批环节"], ["reviewed", { requiresBankReceipt: true, receiptCount: 1 }, "银行回单已上传,等待财务登记付款完成,非审批环节"], ["reviewed", {}, "付款复核已通过,等待财务登记付款完成,非审批环节"], ["failed", {}, "付款登记失败,待财务核对后重试,非审批环节"], ["cancelled", {}, "付款安排已取消,流程已终止"], ["cancelled", { reviewedAt: "2026-09-11T00:00:00Z" }, "付款安排已取消,流程已终止"], ])("%s 无读取链接也不允许重新组批 (%j)", (status, options, expected) => { const result = resolveReimbursementPaymentHandoff({ status: "approved", progress: project(status, options) }); expect(result).toEqual({ nextStep: expected, canCreateBatch: false, targetHref: null }); }); it("只有明确待组批投影才提供资格,入口权限仍由调用者检查", () => { const progress = project("unknown"); progress.stages[0] = { ...progress.stages[0], state: "current", detail: "待财务组建付款批次" }; expect(resolveReimbursementPaymentHandoff({ status: "approved", progress }).canCreateBatch).toBe(true); progress.stages[1].targetHref = "/payment-batches?id=synthetic"; expect(resolveReimbursementPaymentHandoff({ status: "approved", progress }).canCreateBatch).toBe(false); }); it("保留服务端有权的同一个批次入口", () => { const progress = project("reviewed"); progress.stages[2].targetHref = "/payment-batches?id=synthetic"; expect(resolveReimbursementPaymentHandoff({ status: "approved", progress }).targetHref).toBe(progress.stages[2].targetHref); }); it.each([undefined, { stages: [] }, { stages: project("reviewed").stages.slice(1) }, project("unknown")])("缺失或未知阶段拒绝猜测", (progress) => { expect(resolveReimbursementPaymentHandoff({ status: "approved", progress })).toEqual({ nextStep: "付款进度暂不可用,请刷新后重试", canCreateBatch: false, targetHref: null, }); }); it("已付款只展示完成事实,不把制单当付款", () => { expect(resolveReimbursementPaymentHandoff({ status: "paid", progress: project("executed") }).nextStep).toBe("付款已登记完成"); expect(resolveReimbursementPaymentHandoff({ status: "paid", progress: project("reviewed") }).targetHref).toBeNull(); }); it.each(["draft", "reviewing", "rejected", "cancelled"])("%s 不生成付款动作", (status) => { expect(resolveReimbursementPaymentHandoff({ status, progress: project("reviewed") })).toBeNull(); }); it("删除记录不生成付款动作", () => { expect(resolveReimbursementPaymentHandoff({ status: "approved", deletedAt: "2026-09-11T00:00:00Z", progress: project("reviewed") })).toBeNull(); }); });