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.

Chapter 2: Build the workflow

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