const { suggestInvoiceExpenseType } = require("../../../src/services/invoiceExpenseClassification"); const enabledTypes = [ { id: "train-type", code: "travel_train", enabled: true }, { id: "hotel-type", code: "travel_hotel", enabled: true }, { id: "meal-type", code: "business_client_meal", enabled: true }, ]; function invoiceWithCategory(documentCategory, extra = {}) { return { ocr_result: { result_json: { documentCategory } }, ...extra }; } describe("invoice expense classification", () => { it("suggests the enabled train type from a recognized electronic train ticket", () => { expect(suggestInvoiceExpenseType(invoiceWithCategory("electronic_train_ticket"), enabledTypes)) .toEqual({ expenseTypeId: "train-type", source: "document_category" }); }); it.each(["vat_invoice", "full_vat_invoice", "unknown", null])( "does not guess an expense type from category %s, seller, filename or amount", (category) => { expect(suggestInvoiceExpenseType(invoiceWithCategory(category, { seller_name: "合成酒店餐饮公司", original_name: "办公用品.pdf", total_amount: "100.00", }), enabledTypes)).toBeNull(); }, ); it("does not substitute another enabled type when the matching type is disabled", () => { const expenseTypes = enabledTypes.map((type) => ({ ...type, enabled: type.code !== "travel_train" })); expect(suggestInvoiceExpenseType(invoiceWithCategory("electronic_train_ticket"), expenseTypes)).toBeNull(); }); it("does not substitute the first enabled type when the matching type is absent", () => { expect(suggestInvoiceExpenseType(invoiceWithCategory("electronic_train_ticket"), enabledTypes.slice(1))) .toBeNull(); }); it("does not infer from the historical provider or generic upload type", () => { expect(suggestInvoiceExpenseType({ ocr_provider: "tencent", ocr_type: "vat" }, enabledTypes)).toBeNull(); }); it("does not infer from client-facing category fields instead of persisted OCR metadata", () => { expect(suggestInvoiceExpenseType({ documentCategory: "electronic_train_ticket" }, enabledTypes)).toBeNull(); }); it("does not mutate invoice data or expense types", () => { const invoice = invoiceWithCategory("electronic_train_ticket"); const before = JSON.stringify({ invoice, enabledTypes }); suggestInvoiceExpenseType(invoice, enabledTypes); expect(JSON.stringify({ invoice, enabledTypes })).toBe(before); }); });