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 example | Why it fits here | When to change it |
|---|---|---|
| Document Intelligence prebuilt-invoice as a starting reader | We need standard invoice fields and line items | Test a Content Understanding analyzer if varied layouts or custom fields cause too much correction |
| ERP read API and decimal calculations | Order IDs, quantities and prices need exact checks | Reuse the ERP’s matching result where available |
| PostgreSQL for cases, versions and review state | Keep the report and its evidence references together | Follow the company’s existing approved data platform |
| Keyword search, then optional pgvector | A policy may use different wording from the reviewer’s question | Keep keyword search alone if it finds the right clauses reliably |
| A saved workflow with a retry queue | The steps are known and a reviewer may return tomorrow | Add an agent only for a tested investigation that needs flexible follow-up |
| A short report template | The main result is already known from code | Add 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.
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.
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.
| Check | Result in this example |
|---|---|
| Quantity available to bill | min(100 ordered, 100 received) − 0 already billed = 100 |
| Extra billed quantity | max(120 invoiced − 100 available, 0) = 20 units |
| Quantity difference | 20 × EUR 20 approved price = EUR 400 |
| Price difference | 120 × (EUR 20 invoice price − EUR 20 approved price) = EUR 0 |
| Outcome | Hold 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.
Step 6. Find the policy that explains the next action#
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.
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.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 here | Reason | Where to learn the details |
|---|---|---|
| Chunk policy by heading and clause | A 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 fields | Splitting 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 search | It 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 needed | This design already stores cases and policy metadata in PostgreSQL. One database is simpler to operate at this starting scale. | The pgvector lesson below |
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.
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.
| Saved step | What happens next | On failure |
|---|---|---|
| Received | Scan the file and save its identity | Reject or quarantine the file |
| Fields ready | Check required fields and evidence | Ask for a correction |
| Records matched | Compare approved, received and billed amounts | Hold if an ID, unit, currency or source is unclear |
| Difference found | Fetch the applicable rule or search the policy | Keep the numbers; mark missing guidance |
| Ready for review | Show the report and assign the next owner | Keep 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.