H1-H10 优化OCR实时体验闭环

这个提交包含在:
2026-05-09 11:48:57 +08:00
父节点 549bd81e30
当前提交 c26cf9b954
共修改 34 个文件,包含 1217 行新增和 184 行删除
@@ -38,6 +38,8 @@ function buildMultipartRequest({ filename, contentType, content, fields = [] })
async function buildApp({
ocrProvider = "off",
jobDriver = "cron",
bossSend = null,
invoiceConflicts = [],
statusRows = [],
permissionCodes = ["invoice.upload"],
@@ -75,7 +77,11 @@ async function buildApp({
maxUploadSizeBytes: 5 * 1024 * 1024,
invoiceArchiveUnusedDays: 30,
ocrProvider,
jobDriver,
});
if (bossSend) {
app.decorate("boss", { send: bossSend });
}
app.decorate("authenticate", async (request) => {
if (!request.headers.authorization) {
throw new AppError({ code: "AUTH_001", message: "未登录", statusCode: 401 });
@@ -177,8 +183,13 @@ describe("invoicePool upload route", () => {
}
});
it("puts VAT uploads into pending_ocr when OCR provider is enabled", async () => {
const { app, prisma, tempDir } = await buildApp({ ocrProvider: "mock" });
it("puts VAT uploads into pending_ocr and enqueues a directed OCR job when OCR provider is enabled", async () => {
const bossSend = vi.fn(async () => ({ id: "ocr-job-1" }));
const { app, prisma, tempDir } = await buildApp({
ocrProvider: "mock",
jobDriver: "pgboss",
bossSend,
});
try {
const requestPayload = buildMultipartRequest({
@@ -214,6 +225,9 @@ describe("invoicePool upload route", () => {
}),
}),
);
expect(bossSend).toHaveBeenCalledWith("ocr.invoice", {
invoiceId: "11111111-1111-4111-8111-111111111111",
});
} finally {
await app.close();
await fs.rm(tempDir, { recursive: true, force: true });