← All workInternal tools

PO Processing Tool

Purchase orders arrive as PDFs. Staff re-keyed every line by hand, then checked each price against a book that changes quarterly.

Client
Deerman Sales / PowerCheck
Year
2026–
Role
Design + Development

A manufacturer's rep receives purchase orders as PDFs from dozens of vendors, each in a different layout. Staff re-typed every line item, then verified each part number and price by hand against manufacturer price files. Mistakes surfaced weeks later, on invoices. This tool reads the PDF, matches the parts, flags what doesn't reconcile, and sends the orders out.

The problem

The errors didn't show up until they were expensive

The manual process wasn't just slow, it was silently lossy. A part number mistyped by one character, or a price checked against last quarter's file, produced an order that looked completely normal and went out the door. The mistake surfaced when an invoice didn't match — weeks later, when unwinding it meant a phone call to a customer and a credit.

So speed was never really the goal. Catching the wrong line before it left the building was.

What we built

Upload, parse, match, review, send

A PO is uploaded and run through an AI PDF parser that returns structured line items. Those get normalized, then matched against the manufacturer's price database — both the general catalog and the active price list, which are separate sources with different key fields.

Anything that doesn't reconcile is flagged and surfaced in a review modal, where a human corrects it before anything is sent. Approved orders go out as a manufacturer PO plus a vendor confirmation; flagged lines can instead trigger a customer-correction email.

The human-in-the-loop step is deliberate. The tool is confident enough to do the work and not confident enough to skip the check.

The hard part

Parsing vendor PDFs is not one problem, it's a dozen

Every vendor's PDF is different, and the parser's field naming is non-deterministic — the real part code turns up under a different key depending on the document. Beyond that, the failure modes multiply: the code leads the description instead of sitting in its own column; the code is buried mid-description; OCR turns zeros into the letter O; the part is legitimately all-numeric and looks like a stock number; quantity and price columns are swapped.

Each of those is its own recovery pass, and each one ships as a separate change with a test built from the actual purchase order that exposed it. The real document goes in the test name, so a regression points straight at the case it broke.

The hard part, continued

The invariant that keeps recovery from inventing parts

Aggressive recovery is dangerous in a way that's easy to miss: a heuristic clever enough to pull a part number out of a description is also clever enough to turn an ordinary English word into a bogus part number, and that error looks like valid data all the way down the line.

So every recovery pass obeys two rules without exception. It only touches lines whose existing code is already useless, and it must confirm a candidate exists in the manufacturer database before adopting it. Fuzzy matching tries exact matches first and only considers typo variants for tokens long enough that a coincidence is implausible.

That constraint has held through every new vendor shape. It's the difference between a tool that saves time and one that quietly manufactures wrong orders.

How it runs

A diagnostics loop instead of a support queue

When a PO parses wrong, the user sends a diagnostics blob: the raw parser response, the OCR text, and the stored line items including any human corrections. That last part is the valuable one — a correction is ground truth about what the document actually said.

Root-cause from that, fix it in code, ship one change. Users often ask for a per-vendor template instead, and the honest answer is that the fixes are general and need no configuration — and a template can't repair a code the OCR mangled in the first place.

Stack
  • Next.js 15
  • TypeScript
  • Prisma
  • PostgreSQL
  • NextAuth
  • AI PDF parsing
  • Resend
  • Railway
  • Vitest
Outcome

In daily use. Purchase orders that took manual re-keying and line-by-line price checking now parse, match, and send with a single review step.

Have something like this to build?

Work with us