补齐报销待组批财务入口 [09-04-reimbursement-state-gap-finance-view][R1]
这个提交包含在:
@@ -444,7 +444,8 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
expect.objectContaining({ key: "submitted", state: "completed", actorName: "李四", result: "已提交" }),
|
||||
expect.objectContaining({ key: "approval_manager-task", label: "主管审批", state: "completed", actorName: "王经理", result: "通过" }),
|
||||
expect.objectContaining({ key: "approval_finance-task", label: "财务审批", state: "current", actorName: "财务专员", result: "处理中" }),
|
||||
expect.objectContaining({ key: "payment_batch_review", state: "pending", actorName: null, detail: "待财务安排付款" }),
|
||||
expect.objectContaining({ key: "payment_batch_created", label: "组建付款批次", state: "pending", actorName: null }),
|
||||
expect.objectContaining({ key: "payment_batch_review", state: "pending", actorName: null, detail: "待付款批次创建并提交复核" }),
|
||||
expect.objectContaining({ key: "payment_and_receipt", state: "pending", actorName: null }),
|
||||
]);
|
||||
|
||||
@@ -516,6 +517,7 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
expect.objectContaining({ key: "submitted", state: "current", actorName: "张三", detail: "待申请人提交" }),
|
||||
expect.objectContaining({ key: "manager_approval", state: "pending", actorName: null }),
|
||||
expect.objectContaining({ key: "finance_review", state: "pending", actorName: null }),
|
||||
expect.objectContaining({ key: "payment_batch_created", state: "pending", actorName: null }),
|
||||
expect.objectContaining({ key: "payment_batch_review", state: "pending", actorName: null }),
|
||||
expect.objectContaining({ key: "payment_and_receipt", state: "pending", actorName: null }),
|
||||
]);
|
||||
@@ -856,9 +858,10 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
const stages = response.json().data.processingProgress.stages;
|
||||
expect(stages[3]).toMatchObject({ state: reviewState, targetHref: null });
|
||||
expect(stages[4]).toMatchObject({ state: paymentState, detail, targetHref: null });
|
||||
if (status === "draft") expect(stages[3].actorName).toBe(null);
|
||||
expect(stages[3]).toMatchObject({ key: "payment_batch_created", state: "completed", targetHref: null });
|
||||
expect(stages[4]).toMatchObject({ state: reviewState, targetHref: null });
|
||||
expect(stages[5]).toMatchObject({ state: paymentState, detail, targetHref: null });
|
||||
if (status === "draft") expect(stages[4].actorName).toBe(null);
|
||||
|
||||
await app.close();
|
||||
});
|
||||
@@ -895,7 +898,7 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
headers: { authorization: "Bearer test" },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.processingProgress.stages[3]).toMatchObject({
|
||||
expect(response.json().data.processingProgress.stages[4]).toMatchObject({
|
||||
detail: "待非制单人复核付款",
|
||||
actorName: null,
|
||||
targetHref: "/payment-batches?id=batch-1",
|
||||
@@ -906,12 +909,12 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
|
||||
it("attaches the payment-batch link to exactly one status-owning stage", async () => {
|
||||
const cases = [
|
||||
{ status: "draft", reviewedAt: null, targetIndex: 3 },
|
||||
{ status: "reviewed", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 4 },
|
||||
{ status: "executed", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 4 },
|
||||
{ status: "failed", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 4 },
|
||||
{ status: "cancelled", reviewedAt: null, targetIndex: 3 },
|
||||
{ status: "cancelled", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 4 },
|
||||
{ status: "draft", reviewedAt: null, targetIndex: 4 },
|
||||
{ status: "reviewed", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 5 },
|
||||
{ status: "executed", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 5 },
|
||||
{ status: "failed", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 5 },
|
||||
{ status: "cancelled", reviewedAt: null, targetIndex: 4 },
|
||||
{ status: "cancelled", reviewedAt: new Date("2026-04-11T08:00:00.000Z"), targetIndex: 5 },
|
||||
];
|
||||
|
||||
for (const item of cases) {
|
||||
@@ -967,10 +970,11 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.processingProgress.stages[3]).toMatchObject({
|
||||
key: "payment_batch_created",
|
||||
state: "current",
|
||||
actorName: null,
|
||||
result: "待安排",
|
||||
detail: "待财务安排付款",
|
||||
result: "待组批",
|
||||
detail: "待财务组建付款批次",
|
||||
});
|
||||
|
||||
await app.close();
|
||||
@@ -991,7 +995,7 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
headers: { authorization: "Bearer test" },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.processingProgress.stages[4]).toMatchObject({
|
||||
expect(response.json().data.processingProgress.stages[5]).toMatchObject({
|
||||
state: "completed",
|
||||
actorName: "实际付款人",
|
||||
occurredAt: "2026-04-12T08:00:00.000Z",
|
||||
|
||||
在新工单中引用
屏蔽一个用户