Finance / Controls and reporting · 2026
Mdingi Building Supply
A month-end close in Excel, controls tested on generated books with planted errors, and a 13-week cash forecast
- 32 of 32plain problems found, on each of two companies the checks had never seen
- 0false alarms, and none of 19 innocent look-alikes flagged
- 241exceptions in the workbook, the same as Python's over 24 months
- R9.0mof the R10m overdraft unused at the low point of the board's scenario
Mdingi Building Supply is a made-up builder's merchant with five branches and about R263m of sales a year. I generated two years of its books, around 290,000 ledger lines, and planted errors in them, with the answer key kept in a file the checks never read. The checks were tuned on development companies, frozen, and then run once on two companies they had not seen. On each they found all 32 plain errors with no false alarms and flagged none of the 19 look-alikes, but missed most of the deliberately small errors. The month-end close runs in an Excel macro workbook that enforces the order of the steps and keeps the preparer and reviewer apart, and a 13-week cash forecast is recomputed from the books for each scenario.
- 01
The Control Centre workbook
The close is an Excel macro workbook, since Excel is where analysts close months. The month is set on the Control Centre sheet and six steps run in order: import and validate, reconcile the bank, run the controls, review the exceptions, produce the management pack, close the month.
Below the steps the sheet records the month's state: checks passed, items still open, the preparer and the reviewer.

After February closed: 24 checks passed, the R1.10m bank difference fully explained, ten exceptions raised and none left unreviewed. - 02
Validation and bank reconciliation
The month's extract is validated first. Each table's row count and control total must match its manifest. The trial balance must balance for the month and to date, every account must be in the chart, and the bank's running balance must hold.
Book and bank are then matched by reference, so the difference is a list of named items rather than a balancing figure. In February, 26 items explain the whole R1.10m. Three are still open seven bank days later, and they become exceptions.

Book R3.53m, bank R4.63m, nothing unexplained. - 03
Controls and exception review
The controls look for duplicate supplier invoices and payments, invoices billed over the goods received, supplier VAT that does not recompute, unverified changes to a supplier's bank details, risky manual journals, manual entries to control, bank, fixed asset and revenue accounts, postings after a month has closed, and subledgers that disagree with the ledger.
February raises ten exceptions. One is a supplier invoice paid twice. Another is a R240,000 journal to sales labelled only 'Adjustment': it trips three checks and puts the debtors ledger out by the same amount. The rest are items carried from earlier months, each shown with last month's conclusion beside it.
An exception counts as reviewed only with a decision and a written reason. Each decision is stamped with who made it and when.

February's ten exceptions with their decisions and reasons. - 04
Management pack
The management pack is formulas over the trial balance and nothing else. It shows the month and the year to date against budget, each branch, the balance sheet, and debtor, stock and creditor days.
Because it has no macros, the pack works with macros switched off. A test recalculates it outside Excel with pycel and compares it with Python.

February's branches and balance sheet, straight from the trial balance. - 05
Close rules and the log
Close month is refused while any exception is open, before the previous month has closed, if the bank reconciliation leaves anything unexplained, or if the pack is older than the last import. The first run records the preparer's sign-off, and a second run by the same person is refused, so a different reviewer has to close the month. A closed month cannot be re-run.
The workbook's checks are written in VBA, separately from the Python ones. A self-test inside Excel compares the two across all 24 months: the same 241 exceptions, none missing and none extra.

February in the log. The close is refused with ten items open, refused again when the preparer tries to close, and then closed by T. Naidoo. - 06
13-week cash forecast
The board's scenario is sales down 15%, stock suppliers paid in 30 days and stock 8% dearer. Scaling last year's cash lines by a percentage does not capture this, because the timing depends on what each customer owes and how late they usually pay, which Friday payment run each supplier invoice falls into, and when salaries, SARS and finance costs go out. The forecast is therefore recomputed from the books for each scenario.
In that scenario the bank is R1.0m overdrawn in the week of 20 April, with R9.0m of the facility unused. Customers paying 20 days later has a larger effect than the three changes combined. On a company it was not built on, the forecast error was R0.8m one week ahead, R1.1m four weeks ahead and R3.3m at week thirteen.

The board's scenario on the summary page.
Other outputs
Decision report
A memo to the financial director on the year: Gqeberha keeping R4.38 of every R100 it sold against R6.42 the year before, customers taking about 70 days to pay on mostly 30-day terms, and three matters to settle before the year is signed.
Business analysis documents
User stories for the analyst, reviewer, financial director, branch managers and auditor; process maps of the close, an exception's life and the year-end sample; and acceptance criteria that each point to the test that shows them, or say plainly when none does.
Year-end audit
Payment samples that anyone can redraw from their settings, and an evidence register with a hash of every document examined, so a later edit shows.
Summary page
A public page with the year's results, the branches, working capital, the cash forecast and how the checks performed, for readers who do not open the workbook.
Limitations
- Small, deliberate errors. The hard versions were found 2 of 4 and 1 of 4 times. A price 5–9% under list and an invoice a fraction over what was delivered got through.
- A fake supplier with clean details. No check raised it. The year-end payment sample holds it open until its registration and VAT number are confirmed outside the books.
- Corrections. An error nobody corrects is raised every month. Clearing it records a decision; it does not fix the books.
- Payroll, pricing, order splits and cut-off need more detail than a workbook can hold, so those checks run in Python at the year end.