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

这个提交包含在:
2026-09-16 12:56:27 +08:00
父节点 b7d2285d8d
当前提交 3516d7ec04
共修改 28 个文件,包含 791 行新增和 616 行删除
@@ -106,6 +106,23 @@ function buildApp({
}
describe("GET /api/invoice-pool/bindable", () => {
it.each([
["GET", "/invoice-pool?page=0", "list_query_invalid"],
["GET", "/invoice-pool/bindable?reimbursementId=invalid", "selection_query_invalid"],
["GET", "/invoice-pool/status", "status_query_invalid"],
["GET", "/invoice-pool/status?ids=invalid", "status_query_invalid"],
["GET", "/invoice-pool/invalid", "id_invalid"],
["POST", "/invoice-pool/invalid/signed-url", "id_invalid"],
])("explains invalid invoice request %s %s before data access", async (method, url, reason) => {
const { app, prisma } = await buildApp();
try {
const response = await app.inject({ method, url: `/api${url}`, headers: { authorization: "Bearer test" } });
expect(response.statusCode).toBe(400);
expect(response.json().error.details.reasonCode).toBe(`invoice_pool.${reason}`);
expect(prisma.invoicePool.findMany).not.toHaveBeenCalled();
expect(prisma.reimbursementForm.findUnique).not.toHaveBeenCalled();
} finally { await app.close(); }
});
it("returns bindable invoices for reimbursement submitter and uses reimbursement owner for filtering", async () => {
const bindableItems = [
{
@@ -199,7 +216,7 @@ describe("GET /api/invoice-pool/bindable", () => {
});
it("rejects reimbursements not in draft or rejected status", async () => {
const { app } = await buildApp({
const { app, prisma } = await buildApp({
reimbursement: {
id: REIMBURSEMENT_ID,
owner_id: OWNER_ID,
@@ -215,7 +232,8 @@ describe("GET /api/invoice-pool/bindable", () => {
});
expect(response.statusCode).toBe(409);
expect(response.json().error.details).toEqual({ reimbursement: "invalid_status_for_bind" });
expect(response.json().error.details).toEqual({ reimbursement: "invalid_status_for_bind", reasonCode: "invoice_pool.reimbursement_not_editable" });
expect(prisma.invoicePool.findMany).not.toHaveBeenCalled();
await app.close();
});