AWRA OpsHub Search
Accounting controls

A number that is confidently wrong is worse than one that is missing.

A blank cell gets investigated. A total that is neatly formatted, carries no warning and happens to be nonsense gets pasted into a board pack. Two of the three controls on this page were written because we shipped exactly that, found it, and fixed the class rather than the instance — which is the part worth telling you about.

The defect that produced the rule

Our aging report summed dollars into shillings and printed the result with no currency on it.

It had been doing it for a while, and nothing looked wrong. The report ran, the columns lined up, the total was formatted to two decimal places like every other total in the product. It was only found when a workspace that trades in more than one currency looked closely at a figure that felt slightly high. The sweep that followed found the same shape on the dashboard, in the top-customers report and in credit-hold exposure — all of them sitting on one shared helper that assumed every amount was in the same currency and had two decimal places.

Why nothing caught it

Every workspace we had looked at closely traded in one currency, and in one currency the broken code and the correct code produce identical output. The bug was invisible from the inside and obvious from a market we had not sat in. That is the usual shape of this class of defect, and it is why the fix was a rule rather than a patch.

Why a converted total would not have fixed it

The tempting repair is to convert everything to one currency and add it up. But a converted display total needs a decision about which rate and as at when; it moves between two viewings of the same closed period; and a total struck at today's rate reconciles to nothing. The ledger converts once, at the rate recorded on each document, and a figure at any other rate matches none of its entries. You would have replaced a wrong number with an unstable one.

What replaced it

One rule, applied everywhere a single money figure is shown: display the largest single-currency total, label it with its code, and disclose how many other currencies sit behind it. No rate is required, the figure is true at every viewing, and the reader knows there is more — which the old single number never told them.

Rule one

Never add unlike currencies. Never convert to make them like.

The rule has two halves and the second is the one people argue with, so it is worth being explicit about what it costs and what it buys. It costs you a single all-in number. It buys you a number that can be reconciled, that does not move, and that nobody has to caveat in a meeting.

Where a single figure has to be shown

A dashboard tile, a summary line, a card at the top of a report — anywhere the layout has room for one number. The largest single-currency slice leads, labelled, with a disclosure of the remainder alongside it.

Any surface that knows the workspace's base currency passes it through, and that currency then leads whenever it is present. This matters more than it sounds. Without a rate the only available ordering is by nominal amount, and nominal amounts are not comparable: 215,000 shillings sorts above 38,400 dollars while being worth a fraction of it. Leading with the currency the reader thinks in is both more meaningful and more stable, because it does not reshuffle as balances move.

Where a whole report is involved

A report is scoped to one currency rather than summarised across several. You choose the currency, the rows are the rows in that currency, and the totals at the bottom are real totals of real rows. Running it three times for three currencies gives you three reports you can each hand to somebody, which is more useful than one you have to explain.

The nominal ordering described opposite is only ever used to sequence the disclosed remainder. It is never used to claim one exposure is larger than another, because without a rate that claim cannot be made honestly.

If you want a consolidated figure across currencies at a rate you control, that is a legitimate thing to want and it is in the ledger below as work we would do — with the rate and its as-at date stored on the record, so the number can be reproduced later. What we will not do is produce it silently.

The ledger is the one place a conversion happens, and it happens once. A foreign-currency invoice, credit note, customer payment, supplier bill, supplier payment, withholding entry, online collection or till sale posts in your base currency at the exchange rate recorded on that document. When a payment settles at a different rate, the realised difference is booked to an exchange gains and losses account. A document with no rate recorded posts nothing: it shows that it is waiting for a rate, and the refusal is in the audit trail.

Rule two

“UGX 1,234.56” is not a rounding infelicity. It is an amount that cannot exist.

Money was stored at two decimal places in 104 columns and formatted with two decimal places everywhere, on an assumption nobody had ever written down: that every currency has two. Of the 137 currencies the product ships tax profiles for, 105 do. 32 do not, and they miss in both directions.

26

currencies at zero places

The larger half, and the one nobody had noticed. It covers 38 of the 188 country rows we ship. XOF alone is the eight UEMOA states and XAF the six CEMAC states — so this is most of francophone West and Central Africa, plus Japan, Korea, Vietnam, Indonesia, Iceland and Hungary.

ALL BIF CLP COP DJF GNF HUF IDR IQD ISK JPY KMF KRW LAK LBP MGA MMK PKR PYG RWF SOS UGX VND VUV XAF XOF

6

currencies at three places

The half that had been noticed, because it is the one that visibly loses money. A Tunisian tax total of 201.900 was being stored and displayed as 201.90 — a real difference, silently discarded on every line.

BHD JOD KWD LYD OMR TND

105

currencies at two places

The assumption, which was right three-quarters of the time. Being right three-quarters of the time is what let it live for as long as it did: any single-market workspace could run for years without meeting the other quarter.

The place count comes from the internationalisation data already bundled with the framework rather than a table we keep by hand, because a hand-kept list is a second copy of a fact somebody else maintains. One consequence worth knowing before you check our figures against a standards document: that data answers “how many digits is this currency written with in practice”, which for a few currencies with an inflated-away subunit is fewer than the formal standard still assigns. The sharpest case is the Iraqi dinar, formally three places and written with none.

Rule three

There are five ways to pay a supplier. A control on one of them is theatre.

This is the control that finance teams ask for and that is most often built wrongly: refuse to release payment when the goods received do not agree with the order. The wrong way to build it is a check in the screen where you noticed the problem. The other four routes stay open, and whoever needs to get paid finds one.

WebPay from the purchase order
APIProgrammatic release
ManualRecording a payment made elsewhere
M-PesaB2B and B2C transfers
PaystackCard and bank rails

one gate, one definition of “may this be paid”

Those five paths write into two different ledgers, which is the other half of why a per-screen check could never work. Every one of them now calls the same gate before releasing anything, so the answer to “can this be paid” is defined in one place and cannot differ by route.

What the gate decides

One of these blocks by default and one only warns, and we would defend the difference.

A control that is right in principle and wrong on the first day gets switched off on the second. These defaults are chosen so that a working business can install the product on a Monday without anything legitimate being refused.

Blocks

The received quantity disagrees with the order

This is the control being asked for. What arrived does not match what was ordered, so the invoice sitting behind it is not yet trustworthy and the payment does not go. It blocks by default, on every one of the five routes.

Warns

Nothing has been received yet

Deposits, prepayments and proforma terms are legitimate and common, and a product that refused them outright would break working businesses on the day it shipped. So this warns rather than blocks — and an organisation whose policy is that nothing is paid before receipt turns the setting on and it blocks.

Overrides

Somebody decides to pay past a failed match

Possible, and it should be. It requires a permission that is deliberately not the same one as approving a purchase order — approving an order is routine work, paying past a failed match is not, and collapsing the two would hand the second to everyone who legitimately has the first. It also requires a written reason, and it is stamped with who did it and when.

Read this one carefully

Closing a period here refuses a backdated entry. It does not refuse the sale you make today.

There is a period close in the product, and it is a lock. It holds the month, the status, who closed it and when, any notes they left, and — if the month was reopened — who reopened it and when. Every journal entry is checked against it as it is written, edited or deleted, whichever part of the product is writing it.

What it refuses

A manual journal dated into a closed month is refused, with the month named, and the person dates it in an open month or reopens the closed one in front of colleagues. An entry already sitting in a closed month cannot be edited, and an edit cannot move an entry into one either. A posted entry is never deleted in any month, open or closed: it is reversed, and the original stays on the ledger beside the entries that undo it.

The lock is enforced on the ledger entry itself rather than on each screen, because there are a dozen things that post — sales, invoices, payments, payroll, expenses, supplier payments, depreciation, manual journals — and a lock any one of them forgot would be a lock that did not exist.

What it does instead of refusing, and why

A posting the product makes for you — a till sale, a payment received — is dated today rather than chosen by a person. If an accountant has closed the current month early, that posting lands on the first day of the next open month rather than failing a sale halfway through. Nothing lands in the closed month; the posting moves forward, and its date says so.

What closing a month does not do is post year-end closing entries. Retained earnings on the statements is the profit to date, computed rather than closed into equity by entry, and that is in the ledger below.

This is the sort of thing that normally reaches a customer as “period close” on a feature list and is understood as a lock. If you are comparing products on this row, ask each of them the same question: does closing a period refuse a posting into it, or record that it was closed?

Three more refusals

A reconciliation that cannot be finished with a difference, and two figures that cannot overshoot.

The period lock is the control most people ask about. These three sit beside it, and each one turns a number that would otherwise be typed into a number the system works out and holds you to.

A bank statement completes at zero, and then it is locked

Reconciling a bank account to a statement date works out the ledger balance, the receipts and payments still outstanding, and the difference to the statement. It will not complete while any statement line on or before that date is still unmatched, or while the difference is anything but zero, and it will not complete a date earlier than the last one already reconciled.

Completing it locks every line it cleared, so a matched receipt cannot quietly be unmatched next month to make a different statement agree. A line entered into the books from the statement is refused if its month is closed.

How bank reconciliation works →

Depreciation lands on salvage to the cent; withholding cannot be over-remitted

A month’s depreciation is charged once per asset however many times the run is pressed. No charge takes book value below salvage and the last one is whatever is left, so an asset ends on its salvage value exactly. A run into a closed month, or a month that has not started, is refused.

Withholding tax deducted from supplier bills sits in a liability until it is paid over. A remittance larger than what is outstanding for its month is refused, so the liability can reach zero and never go past it.

How withholding tax works →

Before you quote this to a controller

The finance-control rows, answered exactly.

Accounting controls — what the arithmetic actually does

What AWRA OpsHub does today

  • One money figure is never a sum of unlike currencies — the largest single-currency total leads, labelled, with the remainder disclosed rather than absorbed.
  • Conversion happens once, at the rate recorded on the document — never at today's rate — so a figure reads the same at every viewing and can be reconciled against a ledger that actually holds it.
  • An exchange rate entered on the invoice and the supplier bill, on the web, through the API and in the app, and kept on the document.
  • Foreign-currency documents posted in base currency at their recorded rate — invoices, credit notes, customer payments, supplier bills, supplier payments, withholding, online collections and till sales — and nothing posted for a document with no rate, which shows that it is waiting for one.
  • Realised exchange gain or loss booked to an exchange gains and losses account when a payment settles at a different rate from its document.
  • Correction commands that re-post older foreign-currency journals written before the conversion existed.
  • Maker-checker on supplier bills — whoever entered or last edited a bill cannot approve it, unless nobody else active holds the permission to approve bills.
  • Approval rules by amount on supplier bills, set per workspace — a bill in an amount band you choose, optionally for one department, collects each step of an ordered chain of roles or named people before it can be paid, and a changed bill starts the chain again. With no rule, a bill approves on the permission and maker-checker alone.
  • Decimal places read from the currency, across all 137 shipped currencies — 26 at zero places, 6 at three, 105 at two.
  • A base currency leads when the surface knows one, so ordering is meaningful rather than an artefact of nominal size.
  • A single payment gate across all five payment routes and both payment ledgers, with one definition of whether an order may be paid.
  • A quantity discrepancy blocks payment by default; payment before receipt warns by default and blocks when you turn the setting on.
  • Override of the payment gate behind its own permission, separate from purchase-order approval, requiring a written reason and stamped with who and when.
  • A period close that locks the month — a manual journal dated into a closed month is refused, an entry already in one cannot be edited, and a posting the product makes for you rolls forward to the first open day — with who closed it, who reopened it, when, and their notes.
  • Manual journals for the accruals, opening balances and corrections no business document makes, each balanced, referenced, dated by the person posting it and refused for a closed month.
  • Maker-checker on manual journals — drafts, an approval step you switch on for your organization with an optional amount threshold, an author who cannot approve their own entry, and a rejection that carries its reason.
  • Reversal instead of deletion — a posted entry can never be deleted, in an open month or a closed one; reversing a journal posts the mirror entries and the original stays on the ledger.
  • A month-end close checklist — automatic checks for journals awaiting posting or approval, bank accounts reconciled to month end, depreciation posted, pending petty cash, a balancing trial balance, unclassified accounts and the previous month closed, beside your own steps, each ticked or skipped with a reason. It informs the close; it does not block it.
  • A bank reconciliation that completes only at zero difference, with every statement line up to its date matched, entered or ignored, and the lines it cleared locked once it is done.
  • Depreciation charged once per asset per month, never below salvage, landing on salvage to the cent, and refused for a closed month or one that has not started.
  • A withholding tax remittance capped at what is outstanding for its month, so the liability reaches zero and never past it.
  • A hash-sealed audit trail underneath all of it, with no delete button in the interface.
  • Twelve segregation-of-duties conflicts — raise and approve a purchase order, capture and approve a bill, build and approve a payment run, run and approve payroll and more — flagged on an Access Conflicts screen and warned about when a role or user is saved; on a single bill, a manual journal and a payment run, the second step is refused to whoever did the first.

More we can add to your workspace

  • Year-end closing entries, so a closed year moves its profit into retained earnings by entry rather than the statements computing profit to date.
  • A consolidated multi-currency total at a rate you control, with the rate and its as-at date stored on the record so the figure can be reproduced months later.
  • Automatic revaluation of open foreign-currency balances at period end, with the unrealised gain or loss posted for you — the realised gain or loss on settlement is already booked.
  • Segregation-of-duties enforcement that refuses to save a role or user holding both sides of a conflict, rather than warning — being built.
  • Recurring journal templates for the accruals and prepayments that are the same every month.
  • A close checklist that holds the month open until every automatic check passes, for organizations that want the checklist to block a close rather than inform it.

Where we point you to a specialist

  • We will not decide whether a charge is recoverable, deductible or capital. That is an adviser's judgement about your circumstances, and a software vendor willing to make it in a sales meeting is selling you a liability rather than a feature.
  • We point you to your accountant on which basis of accounting your figures should be prepared on. The system records what happened and when; how that is presented in a statutory account is their determination.
  • We will not sign a statutory return on your behalf. Where we file to a revenue authority — Kenya's eTIMS is the live example — we transmit what you issued and record what came back, and the declaration remains yours.
  • We will not produce a single all-in figure across currencies without a rate you chose. Not because it is hard, but because the resulting number cannot be reconciled to anything and reads as though it can.

Everything in the middle column sits on top of controls that already exist — the period lock, the payment gate, the currency layer. If one of those rows is the one your controller keeps asking about, tell us and we will scope it.

Help Center

Need a quick answer while you read?

Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.

Search all approved AWRA public help articles.

Open Help Center