fix: 加固日历日期与动态错误合同(09-05-error-explainability-payment-readiness,09-08-reimbursement-payment-closeout)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-09-16 20:20:11 +08:00
父节点 842c61e696
当前提交 b1d25d3c99
共修改 20 个文件,包含 253 行新增和 21 行删除
@@ -196,6 +196,37 @@ async function buildApp(options = {}) {
}
describe("workflow batch routes", () => {
it("returns the precise reminder cooldown time without creating another reminder", async () => {
const taskId = "11111111-1111-4111-8111-111111111111";
const { app, tx, state } = await buildApp({
actor: { id: OWNER_ID, roleCodes: ["employee"], permissionCodes: [] },
});
tx.workflowHistory.findFirst = vi.fn().mockResolvedValue({
id: "synthetic-reminder", created_at: new Date("2026-09-16T08:30:00.000Z"),
});
vi.useFakeTimers({ toFake: ["Date"] });
vi.setSystemTime(new Date("2026-09-16T09:30:00.000Z"));
try {
const response = await app.inject({ method: "POST", url: `/api/workflow/tasks/${taskId}/remind`, payload: {} });
expect(response.statusCode).toBe(409);
expect(response.json().error).toMatchObject({ code: "VALID_001", details: {
reasonCode: "workflow.remind_cooldown", workflow: "remind_too_frequent",
nextAllowedAt: "2026-09-17T08:30:00.000Z",
} });
expect(tx.workflowHistory.findFirst).toHaveBeenCalledWith(expect.objectContaining({ where: {
task_id: taskId, actor_id: OWNER_ID, action: "remind",
created_at: { gte: new Date("2026-09-15T09:30:00.000Z") },
} }));
expect(tx.workflowHistory.create).not.toHaveBeenCalled();
expect(tx.notification.create).not.toHaveBeenCalled();
expect(tx.workflowTask.update).not.toHaveBeenCalled();
expect(state.history).toEqual([]);
} finally {
vi.useRealTimers();
await app.close();
}
});
it.each([
["POST", "/workflow/tasks/invalid/approve", {}, "workflow.task_id_invalid"],
["POST", "/workflow/tasks/11111111-1111-4111-8111-111111111111/reject", { comment: " " }, "workflow.comment_invalid"],