FlowParse
Feature 9 August 2026 13 min read

Supplier invoice quantities

Every row of a supplier invoice comes out with its quantity, unit of measure, unit price and line total — from clean PDFs and from photographs of creased paper alike. Fields are recognised by what they mean rather than where they sit, so a new supplier needs no template, and the lines are checked against the invoice total before anything is exported.

FlowParse
flowparse.io

The quantity is the point

Most invoice extraction is built around the total, because the total is what gets paid. For anything involving stock that is the wrong field to care about. A total tells you what you owe; it tells you nothing about how many of what arrived at what price, which is the only thing stock is made of.

This page is about the row rather than the document: what comes out of each line, what is deliberately not guessed, and the one check that tells you whether a particular invoice was read correctly. If you want the reconciliation this feeds, that is on the stock purchase reconciliation page.

What comes out of each row

FieldExampleWhy it is separate
DescriptionWidget blue 500mlMatching to your catalogue
Product codeWB-500Far more reliable than description
Quantity24Meaningless without the next field
Unit of measurecaseThe most damaging assumption if guessed
Unit price18.40Where price changes become visible
Line discount5%Keeps list price and paid price apart
Line total419.52Feeds the sum check
Source file / pageinv-8841.pdf p2Traces a figure back to a document

Alongside the rows, the document-level fields come through as usual: supplier, invoice number and date, currency, net, tax and gross totals. Those belong to the invoice; the rows belong to the stock.

Read by meaning, not by position

The old way of reading invoices is a template per supplier: quantity lives at these coordinates, price at those. It works beautifully on the supplier it was built for and breaks the first time that supplier changes their invoicing software — silently, because the template still finds numbers, just the wrong ones.

Reading by meaning asks a different question of the page: which column contains counts, which contains money, which text is a description. That holds when the layout moves, when a new supplier appears, and when someone sends a document that has never existed before. For a business with forty suppliers rather than four, it is the difference between a system that works and a maintenance job.

It also removes the worst failure mode of templates, which is not breaking loudly but breaking quietly. A template that has slipped one column produces perfectly formed data that is entirely wrong, and nothing about the output announces it.

FlowParse
flowparse.io

The unit of measure deserves its own field

A quantity without a unit is not data, it is a number. Twelve can be twelve bottles, twelve cases of six, or twelve kilograms, and the same supplier will use more than one convention across their range — often on the same invoice.

So the stated unit is captured as its own field rather than being absorbed into the description or assumed away. That does not solve the problem by itself; it makes the problem visible, which is the most a document can honestly do. The supplier says cases. Whether a case is six or twelve is not on the invoice.

What follows is a decision recorded once per product: a conversion column of your own, applied deliberately. Ten minutes per supplier, and it removes an error class that otherwise appears only in a stock count, where it is indistinguishable from loss.

Packs, cases and multipliers inside descriptions

Many suppliers put the pack size in the product description rather than in a field: Widget 6x500ml. It is readable by a person and it is prose, not data, which means anything automatic reading it is interpreting rather than extracting.

The description comes through whole, so the information is not lost. What is deliberately avoided is parsing that text into a multiplier automatically, because the notations are not consistent — 6x500ml, 500ml x6, CS/6 and 6pk all appear, and so does 2x4 meaning something else entirely.

The practical approach is the same as for units: derive the multiplier once per product code, keep it in your own lookup, and apply it. Since descriptions repeat almost exactly across invoices from the same supplier, that work compounds rather than recurring.

Discounts, surcharges and delivery lines

A discount stated on a row is extracted as its own value rather than being netted into the unit price. It matters because the two questions behind those numbers are different: what does this supplier list at, and what do we actually pay. Netting them merges the answers and loses the negotiation history.

Delivery, handling and fuel surcharges come through as their own lines, in the position the invoice puts them. That is what allows a consistent treatment across suppliers who present carriage completely differently — one inside the unit price, one on a separate row, one on a separate document a week later.

The reason to keep these visible is not tidiness. Freight applied inconsistently makes product cost incomparable between suppliers, which undermines exactly the comparison a buyer most wants to make.

The line-sum check

One check is worth more than an accuracy percentage, because it applies to the document in front of you rather than to a population: the sum of the extracted lines, plus the stated charges and tax, should equal the invoice total.

When it agrees, the rows are almost certainly complete and correctly read — a misread line would have to be offset by another error of exactly the opposite size to survive. When it disagrees, one of two things is true: a line was read wrong, or the invoice contains something the lines do not explain, such as a settlement discount or a rounding adjustment. Both are worth seeing.

This is the same principle as the balance check on a bank statement, and it is the reason both are trustworthy: the document is asked to confirm itself, using arithmetic its own author put there.

FlowParse
flowparse.io

Awkward layouts that break naive extraction

Real supplier invoices are messier than the examples in software demos, and a few patterns account for most extraction failures elsewhere.

Tables spanning pages. A header repeated at the top of page two is read as data by anything that treats each page separately, adding a row that looks like a product called «Description».

Multi-line descriptions. A product name that wraps onto a second line splits the row, so a quantity ends up attached to half a description.

Sub-totals inside the table. A category sub-total sitting among the rows gets counted as a line, which is the fastest way to double an invoice.

Two columns of prices. List price and net price side by side, where reading the wrong one is undetectable without the sum check.

Layout problemWhat naive extraction doesSymptom in the data
Table spans two pagesReads the repeated header as dataA product called “Description”
Description wraps to a second lineSplits the rowQuantity attached to half a name
Sub-total inside the tableCounts it as a lineInvoice value roughly doubles
List and net price columnsPicks one at randomUndetectable without the sum check
Rotated or skewed scanMisaligns columnsPrices in the quantity column

Each of these is handled structurally rather than by pattern-matching a particular supplier, which is why the same handling survives a layout change. The line item extraction page goes further into the table logic.

Scans, photographs and paper that has been folded

A large share of supplier invoices in stock-heavy businesses never exist digitally. They arrive with the delivery, get signed, get folded into a pocket, and reach the office as a photograph. OCR handles the first step; the structuring and the checks are then identical to a digital PDF.

What changes is the confidence profile. On a clean PDF, everything reads with high certainty and review is a formality. On a creased photograph taken in a badly lit warehouse, a handful of fields will be uncertain — and those are flagged, so the review is a short list rather than a full re-read of two hundred rows.

Scan quality repays effort more than anything else here. A flat page at 300 DPI reads almost perfectly; a skewed photo does not. A minute spent rescanning is consistently cheaper than the corrections that follow a bad capture, though it never feels that way at the time.

FlowParse
flowparse.io

Product codes beat descriptions

Where an invoice carries a product code or SKU, it is extracted alongside the description — and it is the field to match on wherever it exists. Descriptions drift: the same physical item is «Widget blue 500ml» on one invoice and «WIDGET BLU 500» on the next, and matching on text produces two products where there is one.

Codes are stable within a supplier and meaningless across them, which is the shape of the mapping problem: one lookup per supplier, from their code to your SKU, built once and extended when new products appear. It is unglamorous and it is what makes year-on-year cost comparison possible at all.

Where no code exists, the description plus supplier is usually enough to group reliably, because the same supplier tends to describe the same item the same way. It is the cross-supplier case that needs your own mapping — and no extraction can supply it, because the connection exists only in your business.

Review before it becomes data

Extraction does not mean trusting blindly. Before export, the rows are shown in an editable preview with uncertain fields and any sum mismatch already highlighted. Correcting a smudged digit takes seconds while it is on screen and considerably longer once it has become a stock valuation.

The reason to keep a human step here is specific to stock. A wrong bank transaction is wrong once. A wrong unit price becomes the cost of every unit of that product until it is corrected, and it propagates into margin, into pricing decisions, and into the closing valuation.

Only what you confirm reaches the file. The editable preview page covers how the review works in practice.

FlowParse
flowparse.io

A month of invoices in one pass

One invoice at a time is useful for a spot check and useless as a process. Batch processing takes up to 100 files into a single export, with every row recording the document and page it came from — so a month of purchases from thirty suppliers becomes one table.

That is the shape the analysis needs. Filter by product to see every purchase of it across suppliers and dates. Filter by supplier to check what a price list actually cost you. Pivot by month to see when things moved. None of those questions can be answered one document at a time, which is why per-invoice review alone never produces the insight people expect from it.

It also makes the exceptions manageable: rather than reviewing thirty documents, you review the handful of rows that were flagged, wherever they happen to sit.

Export and mapping into your system

Excel and CSV, both carrying the same fields. Choose .xlsx when a person opens the file — the data types travel inside it, so a decimal comma cannot be reinterpreted by someone else's regional setting. Choose CSV when a system imports.

Most inventory and accounting systems accept a purchase import with a defined column set, and the export is arranged to map cleanly onto it. Where your system expects its own SKU rather than the supplier's code, the lookup sits between the two — built once, reused every month, and worth keeping in the same file so it does not get lost.

Keep the source-file column through the import if the system allows a reference field. It is the thing that lets someone six months from now walk a cost back to the document it came from, and it costs nothing to carry.

Through the API

For a business receiving invoices continuously, the useful version of this is not a person uploading files. The API returns the same line-level structure as JSON, so documents arriving by email or landing in a watched folder can be extracted and pushed onward automatically.

Automate the mechanical half first — extraction, the sum check, filing by supplier. Leave the judgement calls manual for longer than feels necessary: unit conversions, product mapping for new items, and anything where a wrong answer would be applied silently to every future purchase of that product.

One design note worth stating: have a failed sum check stop the pipeline rather than warn it. In an automated run nobody is watching, and an invoice whose lines do not add up should never flow onward into a valuation on the assumption that someone will notice later.

What it will not guess

It will not convert units for you. It will not decide that «6x500ml» means six units rather than one. It will not map a supplier's code to your SKU. Every one of those is a decision where a wrong answer is applied consistently and silently, which makes it exactly the kind of thing that should be recorded by a person once rather than inferred every time.

It also does not value stock or decide accounting policy. FIFO, weighted average and the treatment of landed cost are yours; this produces the inputs they operate on.

And nothing is kept: the original file is deleted immediately after extraction, processing runs on EU-hosted infrastructure over TLS, and documents are never used to train AI models — the security page has the detail.

See the lines from your own supplier

Extract one real invoice free — no registration — and check the quantities and unit prices against the paper.

Frequently asked questions

Keep reading