fix(collection-ai): round quantities before comparing in the findings

F1: outstanding = round(ordered - collected, 3) > 0 and the order-line
mismatch compares round(order_qty, 3) with round(quantity, 3), so float
noise never produces "0 are still outstanding" or a false mismatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dave 2026-10-17 10:19:34 +02:00
parent 515c9d4cd2
commit f60b1d893c
2 changed files with 25 additions and 3 deletions

View file

@ -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({

View file

@ -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)}.`,
);