A client sends invoices and GRNs (goods received notes / delivery slips) without purchase orders. The current matching system only connects GRNs to invoices indirectly through a shared PO cluster. Without POs, these documents remain unmatched.
Add #{"invoice" "goods-received-note"} as a directly matchable pair, with appropriate evidence signals, LLM prompts, and UI support.
One invoice typically references multiple GRNs (partial deliveries aggregated into a single invoice). One GRN typically maps to one invoice but many-to-many is possible.
candidates.clj: Add #{"invoice" "goods-received-note"} to matchable-pairs. Candidate retrieval and type filtering derive from this automatically.
view/shared.clj: Add :goods-received-note to invoice's counterpart-types list and :invoice to GRN's list.
evidence.clj)New signal: gr-reference-exact (+55)
Checks if invoice gr-references intersects with GRN delivery-note-numbers or grn-number. Weight 55 matches po-ref-exact — same class of cross-document reference match.
Requires a get-gr-references extractor (invoice yields gr-references, GRN yields grn-number + delivery-note-numbers) and a set intersection in collect-signals.
Extended signal: date-within-period (+20)
Add a case: when one document has a service-period (invoice) and the other has a receipt-date (GRN), check if the receipt date falls within the service period. Reuses the existing signal name.
Expected scoring for correct matches:
gr-reference-exact (55) + description-overlap (25) + date-within-period (20) = 1.0 deterministicllm_decision.clj)["invoice" "goods-received-note"]: One invoice can match multiple GRNs. Focus on GR references vs delivery note numbers, product descriptions, quantity aggregation (GRN quantities sum to invoice line items), delivery dates within service period. Many matches expected.
["goods-received-note" "invoice"]: Single GRN typically matches one invoice. Same signals from GRN perspective. Allow many matches.
No changes. The reconciliation system is generic — it loads all cluster documents and compares them via LLM. Invoice↔GRN clusters will automatically get quantity reconciliation (GRN quantity-received aggregated vs invoice line item quantities).
evidence.clj alpha: already has #{"invoice" "goods-received-note"} 0.3 (deterministic-heavy)normalize.clj: invoice extracts gr-references, GRN extracts grn-number + delivery-note-numberssearchable_text.clj: both types include relevant referencescandidates.clj filtering: derives from matchable-pairs automatically| Signal | Weight | Source |
|---|---|---|
gr-reference-exact |
+55 | Invoice gr-references ∩ GRN delivery-note-numbers/grn-number |
description-overlap |
+25 | Line item description token Jaccard > 15% |
quantity-exact |
+35 | Individual quantity matches (not aggregated) |
date-within-period |
+20 | GRN receipt-date within invoice service-period |
vat-id-match |
+30 | Rarely fires — GRN delivery slips often lack VAT ID |
currency-mismatch |
-30 | Safety check |
vat-id-mismatch |
-40 | Safety check |