fix(dn): a fragment of background paper no longer holds a page in grouping
Co-Authored-By: MiniMax Code <noreply@minimax.io>
This commit is contained in:
parent
fbc1f4f5c6
commit
eca2cb845c
2 changed files with 73 additions and 2 deletions
|
|
@ -51,6 +51,53 @@ describe("assemblePages", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("background fragments", () => {
|
||||
const fragment = (over: Partial<PageRead> = {}) => page(1, {
|
||||
multiple_documents: true,
|
||||
items: [{ description: "Bend 90", qty: 7, unit: "ea", unit_price: null, line_amount: null, product_code: null }],
|
||||
evidence: { multiple_documents: "A cropped corner of another paper is visible behind this invoice." },
|
||||
...over,
|
||||
});
|
||||
|
||||
it("groups a complete document that only has background paper behind it", () => {
|
||||
const result = assemblePages([fragment()]);
|
||||
expect(result.groups.map((group) => group.pages)).toEqual([[1]]);
|
||||
expect(result.openPages).toEqual([]);
|
||||
expect(result.requiresReview).toBe(false);
|
||||
});
|
||||
|
||||
it("still holds a page showing two complete documents side by side", () => {
|
||||
const result = assemblePages([fragment({
|
||||
evidence: { multiple_documents: "Two delivery notes side by side, each with its own header." },
|
||||
})]);
|
||||
expect(result.groups).toEqual([]);
|
||||
expect(result.openPages).toEqual([{ page: 1, reason: "multiple_documents" }]);
|
||||
expect(result.requiresReview).toBe(true);
|
||||
});
|
||||
|
||||
it("still holds a background fragment on a page with no line items", () => {
|
||||
const result = assemblePages([fragment({ items: [] })]);
|
||||
expect(result.openPages).toEqual([{ page: 1, reason: "multiple_documents" }]);
|
||||
});
|
||||
|
||||
it("still holds a background fragment on a page with no document number", () => {
|
||||
const result = assemblePages([fragment({ doc_number: "" })]);
|
||||
expect(result.openPages).toEqual([{ page: 1, reason: "multiple_documents" }]);
|
||||
});
|
||||
|
||||
it("still holds the page when the evidence names a second document number", () => {
|
||||
const result = assemblePages([fragment({
|
||||
evidence: { multiple_documents: "Corner of invoice 22433700 visible behind, a second document." },
|
||||
})]);
|
||||
expect(result.openPages).toEqual([{ page: 1, reason: "multiple_documents" }]);
|
||||
});
|
||||
|
||||
it("groups a fragment with no evidence text at all on a complete page", () => {
|
||||
const result = assemblePages([fragment({ evidence: {} })]);
|
||||
expect(result.openPages).toEqual([{ page: 1, reason: "multiple_documents" }]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("preserves manual split/merge decisions instead of rejoining by printed numbers",()=>{
|
||||
const reads=[page(1,{doc_number:"DN"}),page(2,{doc_number:"DN"}),page(3,{doc_number:"OTHER"})];
|
||||
|
|
|
|||
|
|
@ -43,8 +43,10 @@ export function assemblePages(
|
|||
const readsByPage = new Map(ordered.map((read) => [read.page, read]));
|
||||
for (const read of ordered) {
|
||||
if (read.multiple_documents) {
|
||||
openPages.push({ page: read.page, reason: "multiple_documents" });
|
||||
continue;
|
||||
if (!backgroundFragment(read)) {
|
||||
openPages.push({ page: read.page, reason: "multiple_documents" });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const previous = groups[groups.length - 1];
|
||||
|
|
@ -113,6 +115,28 @@ export function assemblePages(
|
|||
return { groups, openPages, requiresReview: openPages.length > 0 };
|
||||
}
|
||||
|
||||
const BACKGROUND = /background|behind|fragment|cropped|partial|edge|corner|stack/i;
|
||||
const DOCUMENT_NUMBER = /\d{4,}/g;
|
||||
/**
|
||||
* True when a page flagged `multiple_documents` is really one complete
|
||||
* document with a scrap of other paper behind it.
|
||||
*
|
||||
* The extraction prompt already tells the reader to ignore fragments, and it
|
||||
* still flags them often enough to hold whole invoices in "Check grouping"
|
||||
* for the want of a corner. Every condition has to hold: a number of its own
|
||||
* and at least one line, so there is a document to group, and evidence that
|
||||
* describes the other paper as background without naming a second reference —
|
||||
* a second reference means there is a second document to decide about.
|
||||
*/
|
||||
function backgroundFragment(read: PageRead): boolean {
|
||||
if (!read.doc_number.trim() || read.items.length === 0) return false;
|
||||
const evidence = read.evidence?.multiple_documents;
|
||||
if (!evidence || !BACKGROUND.test(evidence)) return false;
|
||||
const own = [read.doc_number, ...(read.doc_number_alts ?? [])].join("|");
|
||||
const elsewhere = evidence.replace(own, " ").match(DOCUMENT_NUMBER);
|
||||
return elsewhere === null;
|
||||
}
|
||||
|
||||
function sessionFor(page: number, hints: AssemblyHints): string | undefined {
|
||||
return hints.page_delivery_session_ids?.[page] ?? hints.delivery_session_ids?.[page] ??
|
||||
(hints.delivery_session_id ?? hints.deliverySessionId);
|
||||
|
|
|
|||
Loading…
Reference in a new issue