divan van rooyen / dvr
← home

writing3 min read

You can’t audit your way out of bad source data

Reporting problems usually get attacked at the reporting end: a new dashboard, a warehouse, another reconciliation. In a production business the number was normally wrong long before any of that saw it.

// where the numbers start

At a food manufacturer, I built the system that records production. There was no real-time instrumentation on the plant. Every number in the financials began with a person typing on a plant floor. Cost of sales, wastage, indirect costs: all of it traced back to a production run someone captured.

Before that system, capture lived in a very large spreadsheet, and the result was then re-keyed into SAP by hand. Two manual steps, each with its own chance to be wrong, sitting directly upstream of the financial statements.

// the point

If capture is wrong, nothing downstream can rescue it.

Month-end reconciliation finds errors after they have already reached the ledger. Analytics built on bad capture is a faster route to the wrong answer, presented more convincingly. The effort belongs at the point of entry: structure, validation, and a workflow that makes the correct entry the easy one and the wrong one difficult.

It is less glamorous than a dashboard. It is also where the money is.

// the workflow has to be true

The trap at the point of capture is designing for the process document rather than for the plant. If the workflow does not match how the floor actually operates, operators work around it. And once they are working around it, the numbers the system produces are fiction, however elegant the reports look.

So the job was as much about understanding how production genuinely ran (multiple products, several types of production run) as about writing the system. Much of the specification turned out to be a transcription of the old spreadsheet, which meant working out what the spreadsheet actually did before anything could replace it.

// integration is half accounting

Removing the re-keying meant integrating into SAP. Technically, an integration resolves to an API call. What matters is populating that call correctly, and that is where the accounting logic sits. Which account, which cost centre, which quantity at which value: get those wrong and the integration simply moves errors faster than a person could.

That doesn’t make it purely an accounting job. But someone who understands why a journal is posted builds a better integration than an engineer guessing at the reason. Certainty comes from the two functions working together. Having one person who can do both is efficiency: nothing gets lost in translation between them, and nobody has to guess.

// the same lesson, smaller

It shows up in small businesses too. At a health-tech startup whose finance function I built, gross margin swung from negative to fifty percent between consecutive months, not because the business changed that much, but because it was not being measured the same way twice. No report could have fixed that. A proper costing sheet and one definition of revenue did.

// what to ask before building any reporting

  • Where is each number first recorded, and by whom? If the answer is “it depends”, that is the first thing to fix.
  • What stops a wrong entry at that moment? Validation at capture is cheap. Finding the same error at month-end is not.
  • How many times is it retyped before it reaches the ledger? Every manual hop is another chance to be wrong, and another place nobody is looking.
  • Does the capture workflow match what people actually do? If it doesn’t, they will work around it, and the system will faithfully record the workaround.
  • Who owns the definition? A number with three owners has three definitions. One agreed definition, produced the same way every month, beats any amount of downstream reconciliation.

// the work behind this

Want something like this?

This is the kind of problem I take on: a business question that needs both a defensible number and a system that keeps producing it.

message me on linkedin →

this page:83 kB of code, gzipped0 trackers0 cookiesbuilt in 201 ms