feat: 选票自动生成报销明细并支持集中分类(08-29-reimbursement-expense-policy-invoice-guard)
这个提交包含在:
@@ -0,0 +1,54 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
在新工单中引用
屏蔽一个用户