修复报销票据门禁提示与 OCR 降级(08-30-b2-submit-error-ocr-fallback)
这个提交包含在:
@@ -41,6 +41,7 @@ function buildReimbursementRecord(overrides = {}) {
|
||||
name: "打车费",
|
||||
category: "travel",
|
||||
enabled: true,
|
||||
requires_invoice: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -56,6 +57,10 @@ function buildReimbursementRecord(overrides = {}) {
|
||||
total_amount: "188.80",
|
||||
original_name: "receipt.pdf",
|
||||
linked_item_id: "item-1",
|
||||
ocr_attempts: 1,
|
||||
ocr_last_requested_at: new Date("2026-04-09T01:00:00.000Z"),
|
||||
ocr_last_error: null,
|
||||
ocr_completed_at: new Date("2026-04-09T01:00:01.000Z"),
|
||||
},
|
||||
],
|
||||
workflow_instances: [
|
||||
@@ -358,8 +363,10 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
totalAmount: "188.80",
|
||||
originalName: "receipt.pdf",
|
||||
linkedItemId: "item-1",
|
||||
amountEvidenceStatus: "verified",
|
||||
},
|
||||
],
|
||||
invoiceAmountManualReviewRequired: false,
|
||||
approvalHistory: [
|
||||
{
|
||||
id: "history-start",
|
||||
@@ -394,6 +401,47 @@ describe("GET /api/reimbursements/:id detail enhancements", () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("keeps the manual amount-review marker visible to a finance detail reader", async () => {
|
||||
const reimbursement = buildReimbursementRecord({
|
||||
invoice_pool_items: [{
|
||||
id: "invoice-off",
|
||||
status: "bound",
|
||||
invoice_code: null,
|
||||
invoice_number: null,
|
||||
invoice_date: null,
|
||||
seller_name: null,
|
||||
total_amount: null,
|
||||
original_name: "manual-review.pdf",
|
||||
linked_item_id: "item-1",
|
||||
ocr_attempts: 0,
|
||||
ocr_last_requested_at: null,
|
||||
ocr_last_error: null,
|
||||
ocr_completed_at: null,
|
||||
}],
|
||||
});
|
||||
const { app } = await buildApp({
|
||||
employeeId: "finance-reader",
|
||||
permissionCodes: ["expense.view_all"],
|
||||
reimbursement,
|
||||
});
|
||||
|
||||
const response = await app.inject({
|
||||
method: "GET",
|
||||
url: `/api/reimbursements/${REIMBURSEMENT_ID}`,
|
||||
headers: { authorization: "Bearer test" },
|
||||
});
|
||||
|
||||
expect(response.statusCode, response.body).toBe(200);
|
||||
expect(response.json().data).toEqual(expect.objectContaining({
|
||||
invoiceAmountManualReviewRequired: true,
|
||||
invoices: [expect.objectContaining({
|
||||
id: "invoice-off",
|
||||
amountEvidenceStatus: "manual_review",
|
||||
})],
|
||||
}));
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("returns null submittedAt and empty approvalHistory when reimbursement has never been submitted", async () => {
|
||||
const reimbursement = buildReimbursementRecord({
|
||||
status: "draft",
|
||||
|
||||
在新工单中引用
屏蔽一个用户