diff --git a/docs/collection-ai-checks.md b/docs/collection-ai-checks.md
index 6feeca8..c5ce304 100644
--- a/docs/collection-ai-checks.md
+++ b/docs/collection-ai-checks.md
@@ -102,11 +102,13 @@ Collection checks, and stored in
| Green | The document agrees with our line: our SKU equals the document code after normalising (uppercase, letters and digits only; this is also how a SKU the AI filled goes green), quantity equals what was collected and what was ordered, the AI is sure it is the same item, unit price after any discount within 1 cent |
| Amber | Close but worth a look: our SKU differs from the document code; collected quantity matches the document but the ordered quantity differs; the AI thinks it is the same item but is only "likely" sure |
| Red | Mismatch or missing: no SKU on our line, quantity differs from the document, price differs or we have no cost, or the line is not on the document or the AI says it is a different product (all four red) |
-| Grey | Can't check, per tick: **SKU** when the document line shows no code; **Qty** when it shows no quantity; **Price** on a delivery note or when the document line shows no price; **all four** when the AI couldn't pair the document (see the AI findings box for the reason; **Check with AI** retries) |
+| Grey | Can't check, per tick: **SKU** when the document line shows no code; **Qty** when it shows no quantity; **Price** when the document line shows no price (a delivery note that prints prices, like Plumblink's, is compared like an invoice — but the AI only ever corrects a cost from a tax invoice); **all four** when the AI couldn't pair the document (see the AI findings box for the reason; **Check with AI** retries) |
For stock purchase lines the SKU tick and robot use the line's own SKU
(the one a rep or the AI set on the purchase line), not the catalogue SKU.
+The AI findings box also lists the AI's **reading notes** — what it noticed on the photo (a delivery note rather than an invoice, the year missing from the date, a rotated or partly covered page).
+
Hover a tick for the values compared (ours vs the document). A robot icon
marks a SKU the AI filled. Click the document chip on a card to see the
extracted lines next to the photo.
diff --git a/src/components/collection-confirm/ai-findings.tsx b/src/components/collection-confirm/ai-findings.tsx
index f5211b6..a548445 100644
--- a/src/components/collection-confirm/ai-findings.tsx
+++ b/src/components/collection-confirm/ai-findings.tsx
@@ -7,9 +7,12 @@ import { docPriceLabel, docUnitCost, roundCents } from "@/lib/collection-ai-tick
const zar = new Intl.NumberFormat("en-ZA", { style: "currency", currency: "ZAR" });
-/** Box of document-level observations from the AI. Renders nothing when empty. */
-export function AiFindings({ findings }: { findings: string[] }) {
- if (findings.length === 0) return null;
+/**
+ * Box of document-level observations from the AI, plus its reading notes
+ * (what it noticed on the photo). Renders nothing when both are empty.
+ */
+export function AiFindings({ findings, notes = [] }: { findings: string[]; notes?: string[] }) {
+ if (findings.length === 0 && notes.length === 0) return null;
return (
AI findings
-
- {findings.map((finding, i) => (
-
{finding}
- ))}
-
+ {findings.length > 0 ? (
+
+ {findings.map((finding, i) => (
+
{finding}
+ ))}
+
+ ) : null}
+ {notes.length > 0 ? (
+
+
Reading notes
+
+ {notes.map((note, i) => (
+
{note}
+ ))}
+
+
+ ) : null}
);
}
diff --git a/src/components/collection-confirm/po-card-ai.test.tsx b/src/components/collection-confirm/po-card-ai.test.tsx
index d802e97..fbf6375 100644
--- a/src/components/collection-confirm/po-card-ai.test.tsx
+++ b/src/components/collection-confirm/po-card-ai.test.tsx
@@ -100,6 +100,25 @@ describe("PoCard AI layer", () => {
expect(screen.getByTestId("ai-findings")).toHaveTextContent("Freight not on PO");
});
+ it("shows the AI's reading notes in the findings box even when there are no findings", () => {
+ const row = makeAiRow({
+ ai_doc: {
+ read_id: "r",
+ doc_type: "delivery_note",
+ document_no: "2010/02893666",
+ doc_date: "2026-10-09",
+ supplier_name: "Plumblink",
+ findings: [],
+ notes: ["Year not printed on the document date"],
+ lines: [],
+ },
+ });
+ render();
+ const box = screen.getByTestId("ai-findings");
+ expect(box).toHaveTextContent("Reading notes");
+ expect(box).toHaveTextContent("Year not printed on the document date");
+ });
+
it("shows a line's own findings (e.g. a pairing failure) in the findings box", () => {
const row = makeAiRow({
ai_check: makeCheck({
diff --git a/src/components/collection-confirm/po-card.tsx b/src/components/collection-confirm/po-card.tsx
index 6ad0f3e..fe143cd 100644
--- a/src/components/collection-confirm/po-card.tsx
+++ b/src/components/collection-confirm/po-card.tsx
@@ -16,6 +16,7 @@ import {
import {
cardDocument,
cardFindings,
+ cardNotes,
documentChipLabel,
} from "@/lib/collection-ai-card";
import type { CollectionDocLine } from "@/lib/types";
@@ -204,6 +205,7 @@ export function PoCard({
const [docPanelOpen, setDocPanelOpen] = useState(false);
const aiDoc = useMemo(() => cardDocument(rows), [rows]);
const aiFindings = useMemo(() => cardFindings(rows), [rows]);
+ const aiNotes = useMemo(() => cardNotes(rows), [rows]);
// Every line the AI read from the chip's document; lines paired with a row
// on this card are marked "matched". Falls back to the paired lines alone
// when the document's full line list is unavailable.
@@ -890,7 +892,7 @@ export function PoCard({
)}
-
+