Skip to learning content
← All use cases
RAG free

Resolving invoice exceptions across PDFs and ERP

Follow a EUR 400 invoice difference from the supplier PDF to a clear review report. Build the record checks, add policy search where it helps, and test the workflow before connecting real ERP actions.

The question: Why does this invoice disagree with the order and delivery records, and who should resolve it?

You’ll learn: Build a checked invoice record and an evidence-linked review report; choose the document reader, exact checks and optional policy search.

For: Finance teams, product owners and engineers. No AI background needed.

Executed teaching prototype · AI-assisted source check . This is not a human expert endorsement.

1. Follow one invoice#

An invoice arrives for EUR 2,400. The order and delivery record support EUR 2,000. Finance needs to know what explains the extra EUR 400, who should check it, and which records to open.

We will build a review queue that answers those questions. It reads the invoice PDF, checks the purchasing records, and prepares a short report. A person handles the exception through the company’s normal process.

RecordWhat it saysWhere to check
Invoice INV1042120 units × EUR 20 = EUR 2,400Invoice PDF, page 1, line 1
Order PO778100 units approved at EUR 20Purchasing system, order line 1
Receipt GR552100 units receivedPurchasing system, receipt line 1
Earlier bills against this line0 unitsPosted invoice history

All amounts in this example exclude tax, discounts and freight. The unit is each, and the currency is EUR. There is one invoice line and one order line. We will keep those limits visible rather than pretend this first version covers every invoice.

An ERP is the business system that stores orders, receipts and invoices. Comparing those three records is often called three-way matching. First check whether your ERP already does this well. If it does, use its result and improve document capture and the review screen around it.

Source: How Dynamics 365 compares invoice prices and received quantities ↗

The evidence behind the EUR 400 question

Open each step to see its role. The comparison uses the actual numbers; a text-search result cannot change them.

Select a box to inspect its role. On a small screen, scroll the diagram sideways.
billedorderreceivedreview
Invoice: 120 units

The PDF is the supplier’s claim. Preserve the original file and the page that shows the line.

Read the complete diagram as text
  • Invoice: 120 units: The PDF is the supplier’s claim. Preserve the original file and the page that shows the line.
  • Order: 100 units: The approved order supplies the supplier ID, item, unit, quantity and EUR 20 price.
  • Receipt: 100 units: The posted receipt records delivery. Missing evidence must stay missing, not become zero.
  • Compare the records: Match exact IDs, confirm currency and units, subtract earlier billed quantities, then calculate with decimal arithmetic.
  • Finance reviews EUR 400: Show all three sources and the reason for the hold. Do not change the invoice or approve payment.
  • Invoice: 120 units → billed → Compare the records
  • Order: 100 units → order → Compare the records
  • Receipt: 100 units → received → Compare the records
  • Compare the records → review → Finance reviews EUR 400

Step 1. Agree the first version with finance#

Start with one legal entity, one ERP, purchase-order invoices, and one invoice currency. Choose a small set of suppliers. Ask finance to label sample invoices as matched, missing receipt, wrong price, duplicate, or unclear. Keep some suppliers for the final test so the reader must handle layouts it has not seen before.

CollectWhy we need itStop when
PDF and file versionShow exactly what the supplier sentThe file is unreadable or unsafe to process
Supplier ID, invoice number and dateFind the right account and check duplicatesTwo suppliers could be the match
Order ID and line IDRead the approved quantity and priceThe order is missing, closed or unapproved
Posted receipts, returns and earlier billsWork out the quantity still available to billThe snapshot is incomplete or out of date
Written tolerances and policy datesKnow which differences need reviewTwo rules conflict or no applicable rule exists
Reviewer and permitted company scopeSend the exception to a person allowed to see itThe caller lacks access

Our teaching rule uses zero tolerance and no returns. Your production adapter must read net accepted receipts, returns, earlier invoices and credit notes using the ERP’s rules. A service invoice may need proof of completed work instead of a goods receipt. Give those cases their own rule.

2. Build the workflow#

Step 2. Give each component one job#

Choice for this exampleWhy it fits hereWhen to change it
Document Intelligence prebuilt-invoice as a starting readerWe need standard invoice fields and line itemsTest a Content Understanding analyzer if varied layouts or custom fields cause too much correction
ERP read API and decimal calculationsOrder IDs, quantities and prices need exact checksReuse the ERP’s matching result where available
PostgreSQL for cases, versions and review stateKeep the report and its evidence references togetherFollow the company’s existing approved data platform
Keyword search, then optional pgvectorA policy may use different wording from the reviewer’s questionKeep keyword search alone if it finds the right clauses reliably
A saved workflow with a retry queueThe steps are known and a reviewer may return tomorrowAdd an agent only for a tested investigation that needs flexible follow-up
A short report templateThe main result is already known from codeAdd a language model only if it makes explanations more useful in testing

These are starting choices, not benchmark winners. Microsoft’s current guide distinguishes standard invoice fields from highly varied documents. Test both reading routes on your suppliers. Measure the time spent correcting them, not just how tidy the JSON looks.

Source: Choose a document reader for the layouts you receive ↗

Step 3. Read the PDF and keep the evidence#

Save the original PDF under a generated file ID. Ask the reader for supplier name, invoice number, order reference, currency, quantity, unit price and line amount. Document Intelligence’s prebuilt-invoice model returns structured fields and line items. Its documented v4.0 API version is 2024-11-30.

Source: Invoice model and supported extraction fields ↗

Store three things together: the original text, the checked value, and its page or source region. For example, keep 20,00 beside the decimal value 20.00. If the quantity is unclear, send that field for review before doing the match. A high model confidence score does not prove the supplier billed correctly.

Go deeper · optional · freeHow to turn PDF fields into values you can check ↗From business PDFs to validated data

Step 4. Read the exact order and receipt#

Resolve the supplier against the approved supplier list. Then use the order ID and line ID to fetch the order, posted receipts and earlier bills. The server must obtain the allowed company from the signed-in session. It must not accept a company ID chosen by the PDF or the model.

Keep the source system, record ID, version and read time. Match the supplier, item, unit and currency before comparing amounts. If any of those checks fail, hold the case. Similar-looking supplier names or nearby invoice numbers are suggestions for a reviewer, never an automatic match.

Go deeper · optional · freeHow to give an assistant a narrow, read-only ERP tool ↗MCP and enterprise tool integration

Step 5. Calculate the difference#

The invoice’s own maths is correct: 120 × 20 = 2,400. The problem is that the available order and receipt support only 100 units. No units have been billed before. The extra 20 units are worth EUR 400 at the approved price.

CheckResult in this example
Quantity available to billmin(100 ordered, 100 received) − 0 already billed = 100
Extra billed quantitymax(120 invoiced − 100 available, 0) = 20 units
Quantity difference20 × EUR 20 approved price = EUR 400
Price difference120 × (EUR 20 invoice price − EUR 20 approved price) = EUR 0
OutcomeHold for review: EUR 400 quantity difference

Check quantity and price separately. A lower price must not hide an unsupported quantity. Do not decide from a net total alone. Missing or stale receipts mean “cannot check delivery yet”; they do not justify treating the receipt as zero.

Use decimal arithmetic for money. Keep both the invoice values and the difference. Never silently replace 120 with 100 to make the invoice pass.

Now finance asks: “What do we do if some goods have not arrived?” The approved policy may call this “partial delivery” or “quantity variance.” This is where searching by meaning can help.

Keep two paths. Exact ERP records decide the numbers. Search finds the policy text that helps a reviewer act on the result. If the case already has a trusted rule ID, fetch that rule directly. Use search when the question or policy is not yet identified.

Two paths, one review report

Search provides relevant text. It does not supply a replacement order, receipt or payment decision.

Select a box to inspect its role. On a small screen, scroll the diagram sideways.
exact IDswords or meaningchecked numberscited guidance
Checked invoice fields

Invoice ID, exact order reference, quantity, currency, unit and source page.

Read the complete diagram as text
  • Checked invoice fields: Invoice ID, exact order reference, quantity, currency, unit and source page.
  • ERP lookup and checks: Use exact authorized records and decimal calculations to identify the exception.
  • Policy question: Example: What should finance do when part of a delivery is missing?
  • Approved policy search: Search only allowed versions that apply on the chosen business date; retain the clause and page.
  • Short evidence report: Combine the calculated exception with a relevant policy passage and a named next owner.
  • Checked invoice fields → exact IDs → ERP lookup and checks
  • Policy question → words or meaning → Approved policy search
  • ERP lookup and checks → checked numbers → Short evidence report
  • Approved policy search → cited guidance → Short evidence report
Decision hereReasonWhere to learn the details
Chunk policy by heading and clauseA rule and its exceptions need to stay together. Start with a roughly 400-token cap; repeat up to 50 tokens only when a long clause must continue. Test these settings.The chunking lesson below
Keep invoice rows as fieldsSplitting every 500 tokens could separate a price from its quantity. The comparison does not need invoice embeddings.The PDF and chunking lessons
Try text-embedding-3-small for policy searchIt is already used in this stack. It is a baseline to test against other embedding models, not a claim that it is best.The embedding-model comparison below
Add pgvector to PostgreSQL if neededThis design already stores cases and policy metadata in PostgreSQL. One database is simpler to operate at this starting scale.The pgvector lesson below
Go deeper · optional · freeChunking: keep the rule, exception and table together ↗Chunking documents without losing meaningGo deeper · optional · freeEmbeddings: what they are, how models produce them, and how to choose ↗Embeddings explained: what they do and how to choose a modelGo deeper · optional · freeWhy pgvector fits here, and when you can skip it ↗Why pgvector, and when to use it

Filter by company, permissions, policy status and effective date before choosing the passages to show. Decide with finance which date governs the rule: invoice date, posting date or review date. Save that choice. The newest document is not automatically the applicable one.

Start with keyword search. Add semantic search when your test questions miss relevant clauses with different wording. Combine their ranked results, then inspect a small set of passages. No useful passage means “policy not found”; conflicting rules go to the policy owner. Neither situation changes the calculated invoice difference.

Go deeper · optional · freeHow to keep search tied to the right source version ↗Enterprise RAG: retrieval, relationships and trustworthy evidence

Step 7. Save progress so the job can resume#

Use a durable queue: a saved list of jobs that survives a restart. In this stack, a worker can use Bull and Redis, while PostgreSQL stores the case state and completed steps. A retry must check those records before repeating work.

A direct ERP API is enough for these fixed steps. Use MCP only if the company already exposes the same narrow tools through it. An agent may help investigate an unusual case later, but it still needs a runtime that limits tools, retries and spend.

Go deeper · optional · freeWhen a workflow is enough, and when an agent earns its place ↗Designing enterprise AI systems: models, workflows, agents and harnesses
Saved stepWhat happens nextOn failure
ReceivedScan the file and save its identityReject or quarantine the file
Fields readyCheck required fields and evidenceAsk for a correction
Records matchedCompare approved, received and billed amountsHold if an ID, unit, currency or source is unclear
Difference foundFetch the applicable rule or search the policyKeep the numbers; mark missing guidance
Ready for reviewShow the report and assign the next ownerKeep the case queued for a person

Use one intake key per company and file hash to stop repeat uploads creating repeat jobs. Check business duplicates separately using the supplier and invoice identity; two different PDFs can contain the same bill. Bound retries and service calls. Send exhausted jobs to a failed queue with a clear reason.

Go deeper · optional · freeRetries, duplicate actions and approvals that survive a restart ↗Durable AI workflows: state, approvals and recovery

3. Review, test and roll out#

Step 8. Show a report people can use#

On the review screenExample
What is wrong?The invoice bills 20 more units than the order and receipt support.
How much needs checking?EUR 400, excluding tax.
What can I open?Invoice page 1; order line 1; receipt line 1; the applicable policy clause.
Who acts next?Purchasing checks for an approved amendment; receiving checks for a missing receipt.
What happens after that?Finance checks the new evidence or requests a corrected invoice.
Has anything been paid?No. This report is a review record.

Put the invoice page beside the checked fields. Highlight the source region only when extraction actually supplied it. Let reviewers correct a field with a reason; keep the old value and file version in the history. Record who resolved the exception and what evidence changed.

If you later add an ERP write, show the exact proposed change first. Recheck permission and source versions when the reviewer approves. A changed order invalidates the old proposal. Use a separate write adapter and a unique action key so a retry cannot submit the same change twice.

Put controls at each hand-off#

PlaceControl to implement
UploadAllow expected file types; check content, size and page limits; scan files; parse in an isolated worker with no ERP credentials.
Files and recordsUse company-scoped storage and expiring source links. Recheck access when someone opens an attachment.
Models and searchTreat PDF and policy text as untrusted data. They cannot grant permissions, change tools or approve payments.
ERP adapterUse narrow read permissions. Keep credentials on the server and restrict which hosts it can call.
Logs and retentionLog IDs and failure codes by default. Set retention with finance; remove expired copies, search chunks and vectors together.
Provider callsConfirm the approved processing location, retention and data agreement before sending real invoices.

Source: File-upload controls ↗

Source: Why document text must not control tools or permissions ↗

Go deeper · optional · freeWhat happens when a PDF tells the AI to ignore the rules? ↗Prompt injection and trust boundaries

Step 9. Test the failures before expanding#

Test invoice or questionExpected behavior
120 billed; 100 ordered and receivedHold the EUR 400 quantity difference.
Missing or stale receiptHold; delivery support is unknown.
Some quantity already billedSubtract it before checking the current invoice.
Different supplier, currency or unitStop; do not compare incompatible records.
Duplicate invoiceFlag the duplicate; do not create another payment proposal.
Discounted price and excess quantityShow both checks; do not let one cancel the other.
Old or wrong-company policy ranks firstDo not show it; use an authorized applicable passage or abstain.
Instruction hidden in the PDFTreat it as document content; permissions remain unchanged.
Worker restarts or ERP times outResume or fail clearly without a repeated action.

Measure missed exceptions, false alarms, wrong field values, useful policy passages and reviewer correction time. Include provider calls, retries and human review in the cost. Compare with the current process on the same invoices. Set the acceptance limits with finance before reading the results.

Go deeper · optional · freeBuild a test set that catches real failures ↗Evaluating enterprise AI against business outcomes

Run the downloadable example#

Download the invoice exception lab. Unzip it, open a terminal in the extracted folder, and use Python 3.11 or later. The checker needs only Python’s standard library.

shell
python invoice_lab.py --input fixtures/base.json
python -m unittest discover -s tests -v

Open the synthetic PDF, compare it with fixtures/base.json, and run the command. Read the reason codes and source references in the output. Then try the supplied missing-receipt and partial-billing examples. The README names exactly which parts run locally and which connections you still need to build.

The lab treats one fixed order-line ID as the item match. The live ERP adapter must also verify the item itself. Its company selector and saved timestamps are teaching inputs, not a login system or a live connection. The example selects its rule using the stated review date.

Start with a small review queue#

First run beside the existing process. Let finance compare the reports without changing ERP records. Fix recurring field and matching errors. Add policy search only if it helps reviewers answer questions they could not resolve quickly. Expand suppliers and invoice types one group at a time.

The useful result is simple: a person can see what differs, which records prove it, and what to do next. The linked articles explain the technology when the reader wants that detail.

Sources & further reading

  1. Invoice matching rules ↗
  2. Document Intelligence invoice model ↗
  3. Choosing a document reader ↗
  4. OWASP file uploads ↗
  5. OWASP prompt injection ↗