diff --git a/src/lib/server/collection-ai-findings.test.ts b/src/lib/server/collection-ai-findings.test.ts index 243e60b..ea326e1 100644 --- a/src/lib/server/collection-ai-findings.test.ts +++ b/src/lib/server/collection-ai-findings.test.ts @@ -218,6 +218,23 @@ describe("buildDocFindings", () => { ]); }); + it("never says '0 are still outstanding' for float noise", () => { + expect(toFollow({ order_qty: 0.1 + 0.2, quantity: 0.3, qty_collected: 0.3 })).not.toContainEqual( + expect.stringContaining("still outstanding"), + ); + }); + + it("does not flag an order-line mismatch that is only float noise", () => { + expect( + buildDocFindings({ + ...base, + read: read([dl({ line_no: 1, quantity: 0.3 })]), + poLines: [pl({ order_qty: 0.1 + 0.2, quantity: 0.3, qty_collected: 0.3 })], + pairs: [{ doc_line_no: 1, po_line_id: "p1" }], + }), + ).toEqual([]); + }); + it("prints a single-spaced placeholder for a null document quantity", () => { expect( buildDocFindings({ diff --git a/src/lib/server/collection-ai-findings.ts b/src/lib/server/collection-ai-findings.ts index 4898353..2863f9d 100644 --- a/src/lib/server/collection-ai-findings.ts +++ b/src/lib/server/collection-ai-findings.ts @@ -13,9 +13,14 @@ export type PoLineLite = { export type LinePair = { doc_line_no: number; po_line_id: string | null }; +/** Rounded to 3 decimals, so float noise never prints or compares. */ +function round3(n: number): number { + return Math.round(n * 1000) / 1000; +} + /** 40 not 40.0; at most 3 decimals so float noise never prints. */ function fmt(n: number): string { - return String(Math.round(n * 1000) / 1000); + return String(round3(n)); } /** Ordered = order_qty, falling back to quantity when order_qty is 0. */ @@ -90,7 +95,7 @@ export function buildDocFindings(input: { for (const { doc, po } of resolved) { if (po && doc.to_follow === 0) { - const outstanding = ordered(po) - po.qty_collected; + const outstanding = round3(ordered(po) - po.qty_collected); if (outstanding > 0) { out.push( `${po.description}: supplier shows nothing to follow, but ${fmt(outstanding)} are still outstanding.`, @@ -100,7 +105,7 @@ export function buildDocFindings(input: { } for (const { po } of resolved) { - if (po && po.order_qty > 0 && po.quantity > 0 && po.order_qty !== po.quantity) { + if (po && po.order_qty > 0 && po.quantity > 0 && round3(po.order_qty) !== round3(po.quantity)) { out.push( `${po.description}: order line says ${fmt(po.quantity)} but the PO quantity is ${fmt(po.order_qty)}.`, );