fix: 完善动态错误指引与发票日期校验(09-05-error-explainability-payment-readiness)

这个提交包含在:
2026-09-16 12:56:27 +08:00
父节点 b7d2285d8d
当前提交 3516d7ec04
共修改 28 个文件,包含 791 行新增和 616 行删除
@@ -196,6 +196,32 @@ async function buildApp(options = {}) {
}
describe("workflow batch routes", () => {
it.each([
["POST", "/workflow/tasks/invalid/approve", {}, "workflow.task_id_invalid"],
["POST", "/workflow/tasks/11111111-1111-4111-8111-111111111111/reject", { comment: " " }, "workflow.comment_invalid"],
["POST", "/workflow/tasks/11111111-1111-4111-8111-111111111111/transfer", {}, "workflow.transfer_input_invalid"],
["POST", "/workflow/batch-approve", { taskIds: [] }, "workflow.batch_approve_input_invalid"],
["POST", "/workflow/batch-reject", { taskIds: [] }, "workflow.batch_reject_input_invalid"],
["POST", "/workflow/tasks/11111111-1111-4111-8111-111111111111/remind", { comment: "长".repeat(201) }, "workflow.remind_input_invalid"],
["GET", "/workflow/tasks/summary?scope=invalid", undefined, "workflow.summary_query_invalid"],
["GET", "/workflow/tasks?page=0", undefined, "workflow.task_list_query_invalid"],
["GET", "/workflow/approvers?page=0", undefined, "workflow.approver_query_invalid"],
])("rejects malformed %s %s before starting a business transaction", async (method, path, payload, reasonCode) => {
const { app, prisma, state } = await buildApp({
actor: { id: ACTOR_ID, roleCodes: ["manager"], permissionCodes: ["expense.approve", "expense.transfer"] },
});
const before = JSON.stringify([...state.tasks]);
try {
const response = await app.inject({ method, url: `/api${path}`, ...(payload === undefined ? {} : { payload }) });
expect(response.statusCode).toBe(400);
expect(response.json().error.details.reasonCode).toBe(reasonCode);
expect(prisma.$transaction).not.toHaveBeenCalled();
expect(JSON.stringify([...state.tasks])).toBe(before);
} finally {
await app.close();
}
});
it("rejects self approval on a single task action", async () => {
const { app, state } = await buildApp({
reimbursementOwnerId: ACTOR_ID,
@@ -212,6 +238,7 @@ describe("workflow batch routes", () => {
code: "VALID_001",
details: expect.objectContaining({
workflow: "self_approval_not_allowed",
reasonCode: "workflow.self_approval_forbidden",
}),
}),
);