Reports

A Report That Changes When You Look Twice

The same outstanding figure exported twice in one day, differing by 53,100 with nothing apparently changed in between. The four causes of an unstable number, a worked example where the difference decomposes into two named events, and what an export has to carry for a second person to reproduce it.

ReproducibilityReportingReceivablesAudit TrailNoxOrigin

On the first of the month, at nine in the morning, somebody exports the outstanding figure for August. At five in the afternoon the same person exports it again, with the same filter, and the number is different. Nothing in the business changed in between, or so the export says. This is the moment at which a reporting tool stops being believed, and it is almost never the tool's fault: a number that was true at nine and superseded at five is not a defect. A number that was true at nine and gives no indication that it was true only at nine is unusable, because there is no way to compare it with anything.

The reason this matters more than it looks is that a business meeting is mostly an argument from a number. Somebody brings a figure, somebody else brings a different figure, and the discussion that follows is only as good as the numbers in it. If the numbers are not reproducible — if the second person cannot get the first person's figure from the same records by the same route — then the meeting is not about the business at all. It is about which export somebody ran, and that is a conversation with no possible conclusion.

This article takes one month-end figure through one day and shows exactly what moved it. Four causes account for nearly all of the instability people meet in practice, and none of them is a calculation error. All four are the same class of problem: a report that has no moment it is true as of, reading records whose meaning depends on when you look.

Four causes, and they are not the same size

Worth separating, because one of them is a design failure that can be designed out and the other three are facts about the world that cannot be. Teams tend to address all four with the same instinct, which is to add a warning, and that instinct works on exactly one of them.

Why a figure moves between two exports of an unchanged period

A state read live rather than derived

A stored status, a counter, or a flag on the row that is recomputed or read at the moment you open the report. Nothing was entered, so nothing looks like it changed, and the figure simply has no history. This is the one cause that is genuinely a design failure, and the fix is to derive the state from records rather than hold it.

A payment allocated after the first export

Money arrived on the 30th and somebody recorded the allocation on the 1st. Both exports are correct. The first is a statement about the records as they stood at nine, and the second is a statement about the records as they stood at five, and the records genuinely differed.

A late record carrying an earlier date

An invoice dated the 28th is entered on the 1st, so a report whose period is defined by document date moves after the period is closed. The document belongs to August and always did. It was simply not in the system when August was reported.

A filter or a setting changed between the two

The report definition was edited in the afternoon. Both figures are correct for the definition in force when they were run, and neither carries any evidence that the definition moved, so the change presents itself as a business result.

The first card is the one to dwell on, because the other three are honest and it is the only one that is a choice somebody made. If a report reads a stored status, the figure has no as-of moment at all, because the value in the row is whatever it is now. It is not even a figure that was true earlier — it is a figure that has no earlier. The other three produce two honest figures at two different moments, and an honest pair is comparable. A single figure with no moment is not comparable with anything.

Worked example: one figure, two exports, eight hours apart

Everything below is invented so the arithmetic is checkable. The invoices, the client, the payment and the timings are ours; none of it is a customer or a measured result. The 18% rate appears only so the totals can be verified, and the rate and treatment that actually apply are for your own chartered accountant to confirm. Days past due are counted as the number of days between the due date and 31 August, so the figures can be reproduced by hand.

Invoices open on 31 August (worked example, illustrative)

InvoiceIssuedDueTaxableGST at 18%GrossDays past due on 31 Aug
INV-310112 Aug11 Sep1,00,00018,0001,18,000not yet due
INV-310420 Aug19 Sep40,0007,20047,200not yet due
INV-30883 Aug2 Sep60,00010,80070,800not yet due
INV-30665 Jul4 Aug25,0004,50029,50027
INV-30511 Jun1 Jul12,0002,16014,16061
INV-30424 May3 Jun35,0006,30041,30089
INV-30302 Apr2 May80,00014,40094,400121
Total open——3,52,00063,3604,15,360—

The first export: outstanding as at 31 August, taken at 09:00 on 1 September (worked example — arithmetic shown)

Ageing bandInvoices in itArithmeticFigure
Not yet dueINV-3101, INV-3104, INV-30881,18,000 + 47,200 + 70,8002,36,000
0–15 daysnone—0
16–30 daysINV-30664,500 taxable is inside the 29,500 gross29,500
31–60 daysnone—0
61–90 daysINV-3051, INV-304214,160 + 41,30055,460
Over 90 daysINV-303094,40094,400
Total7 invoices2,36,000 + 0 + 29,500 + 0 + 55,460 + 94,4004,15,360

The total is checkable two ways and they agree: the seven gross values add to 4,15,360, and the taxable column adds to 3,52,000 with a tax component of 63,360, and 3,52,000 + 63,360 = 4,15,360. That figure is now in somebody's inbox with the label outstanding as at 31 August, and it is true.

09:00, 1 September — first export. Outstanding as at 31 August is 4,15,360, split 2,36,000 not yet due, 29,500 in the 16–30 band, 55,460 in the 61–90 band, and 94,400 over 90 days. Nothing has been entered into the system since 31 August, so this figure and the state of the records agree.

14:10 — a payment is allocated. A client transfers 70,800 and the allocation is recorded against INV-3030, the oldest open invoice, which is the stated default policy. INV-3030's outstanding becomes 94,400 − 70,800 = 23,600. No invoice was created, cancelled or edited. The money simply arrived, which is the normal event.

16:20 — a late invoice is entered. INV-3109 is created with an invoice date of 28 August: 15,000 taxable, 2,700 tax, 17,700 gross, due 27 September. It belongs to August and always did. It was not in the system when August was first reported, and nothing about the entry was an error.

17:00 — second export. The same report, the same filter, the same label, eight hours later.

The second export: outstanding as at 31 August, taken at 17:00 on 1 September (worked example — arithmetic shown)

Ageing bandInvoices in itArithmeticFigure
Not yet dueINV-3101, INV-3104, INV-3088, INV-31092,36,000 + 17,7002,53,700
0–15 daysnone—0
16–30 daysINV-3066unchanged29,500
31–60 daysnone—0
61–90 daysINV-3051, INV-3042unchanged55,460
Over 90 daysINV-3030, after the allocation94,400 − 70,80023,600
Total8 invoices2,53,700 + 29,500 + 55,460 + 23,6003,62,260

Both exports carry the identical label. They differ by 4,15,360 − 3,62,260 = 53,100, and that difference decomposes exactly: 70,800 of allocation against INV-3030, less 17,700 for the late invoice, and 70,800 − 17,700 = 53,100. Both are correct. The second is not a correction of the first, and this is the point: it is a statement about a different set of records.

The damage is done entirely by the label. Outstanding as at 31 August is a true description of the first export and a false description of the second, because the allocation happened on 1 September and a report cannot measure a state that had not been reached yet. Yet the second figure is the one a reader will use, because it is the later one, and it carries a date that means it should equal the earlier one. That is a genuine trap, and it is not fixed by being careful.

The third reading, and why it is the right one

There is a third answer, and it is the one a reproducible figure requires. Outstanding as at the close of 31 August, computed from the records as they stood at that moment, is 4,15,360 — the first figure — and the later entries are simply not in scope for it. That requires the system to be able to answer a question about the past rather than only about the present, which is a different and more demanding capability than being able to report now.

It also produces a pair of figures that can sit side by side, which is where the value actually is. As at 31 August: 4,15,360. As at 17:00 on 1 September: 3,62,260. Movement of 53,100, itemised as 70,800 allocated and 17,700 invoiced. Now the two exports are not a contradiction to be argued about. They are two true statements with a documented difference between them, and a meeting can spend its time on the 70,800 — was that payment expected, is that client in trouble, is the oldest invoice now off the danger band — which is a conversation about the business rather than about the software.

The ageing bands matter here more than the total, and the worked example shows why. On 31 August the business has 94,400 sitting 121 days past due, which is the line item somebody actually needs to act on. By 17:00 on 1 September that invoice has 23,600 left in the same band, because the oldest debt got the money. The proportion of the book in the over-90 band has moved from 94,400 ÷ 4,15,360 to 23,600 ÷ 3,62,260 without a single new document being issued. Neither percentage is wrong. They are measurements of two different moments, and a reader who is not told which moment is being shown cannot act on either.

What makes a figure reproducible

Four things, and it is worth noticing that three of them are about the export rather than the arithmetic. The arithmetic in the tables above was never in doubt. What was missing was everything that lets a second person reach the same place.

What an export has to carry, and the failure each item prevents

  • An explicit as-of moment — a timestamp, not a date, and not a label. This is the item everything else depends on. Without it the figure has no identity, and a figure with no identity cannot be compared, cited or defended
  • The rows, not only the total. A total is a conclusion. The rows are what a second person can re-derive the conclusion from, and re-deriving it is the entire basis on which anybody trusts it
  • The definition of the set — the period, the sites, the states, and every condition that excluded something, with the excluded items itemised. The worked example's whole 53,100 is locatable this way; without it the difference is a rumour
  • Both dates kept apart for anything involving money: the date it arrived and the date it was applied. Late entry and reversals move figures between periods, and a single date cannot distinguish the two cases
  • A record of what changed between two runs, so that when two exports of the same period differ, the first question is answered by the record rather than by argument
  • The derived states re-derivable from the rows — invoice total, sum of live allocations, outstanding — so a figure quoted in a meeting three months ago can be rebuilt rather than merely remembered

The second item deserves a sentence of its own because it is the difference between a tool and a receipt. An export that shows outstanding of 4,15,360 is a screenshot of a conclusion and can be believed or not believed. An export that shows the seven invoices, their gross values, their due dates, and the allocations against them is something a person can check in about four minutes with a calculator, and the check either agrees or produces a specific question. Businesses trust the second kind far more than the first, and the reason is not naivety — it is that the second kind is falsifiable and the first is not.

Why there is no stored 'paid' flag to go stale

This is worth connecting directly to the first card above, because it is the same design decision seen from the other side. An invoice and a payment are different records. Money arrives without knowing which claim it settles, and the decision about which invoice it lands on is a separate, attributable, reversible act — an allocation. 'Paid' is therefore not a field on the invoice. It is a projection of allocations, recomputed as invoice total minus the sum of live allocations, and the state you see — issued, partly allocated, fully allocated, over-allocated, reopened by reversal — is a consequence of that arithmetic rather than something anybody wrote down.

The consequence for this article is direct. There is no stored status for a report to read live, so the first cause on the list — a state read live rather than derived — does not exist in the model. A report cannot be unstable because a flag was not updated, because there is no flag to update. It is still unstable for the other three reasons, and the four of them in the worked example happened with everything derived from records, which is a useful result: it means the remaining causes are about moments and definitions rather than about bookkeeping discipline, and moments and definitions can be specified.

Two boundaries belong with that. First, a derived state still needs a moment to be true as of, and the model does not by itself tell a report which moment to use — that remains a decision about the report, not a fact recovered from the data. Second, the reverse operation needs care. A wrong allocation is corrected by an allocation reversal that names the allocation it reverses, with an author and a reason, and never by editing the payment: the money arrived and is in the bank, so the payment keeps its amount, date, method and reference while the link is what changes. A correction that is a deletion leaves a day's figures wrong and no evidence of why, and it makes the month-end figure irreproducible for a reason that has nothing to do with moments.

The period has to close before the number is worth arguing from

A lot of the instability in the worked example comes from August still being open while somebody reported on it. That is not a mistake by the person exporting, it is what happens when a month is reported while it is still receiving entries. The fix is a boundary rather than a feature: the business day and the period have to be closed by somebody, deliberately, and the close has to capture who closed it, when, and what was in scope.

Where a business runs shifts, the same question appears at a smaller scale every day, and our earlier piece on the business day covers the argument properly. The relevant part here is only this: a period that has not been closed is still being written to, so any figure taken from it is a moving target, and a moving target cannot be compared. We would rather have a period closed on a stated day with a named owner than a period left open indefinitely in the name of accuracy, because a closed period can be re-derived and an open one cannot.

One honest note on maturity: on a dedicated Nox-Billings deployment, shift close and day-end reconciliation are assisted setup. We set them up and validate them with you as part of the deployment rather than handing them over as a self-serve switch, and the reason is precisely this article's subject. A close routine that is not aligned to how your business actually ends its trading period produces a boundary that is technically correct and operationally fictional, and it is much cheaper to get that alignment right at setup than to debug a variance afterwards.

Where this stops, honestly

Three boundaries. First, reproducibility is a property of the read, not a promise that the answer will not change. Money keeps arriving, invoices keep being raised late, and periods keep being restated, and a business that claims its month-end figure can never move is describing a system that has stopped doing its job. The claim worth making is narrower and sufficient: given the records, the moment and the stated set, somebody else reaches the same number. Second, this is an operational record, not the books. A reproducible figure from NoxOrigin is a clean input to statutory accounting, and it does not become a ledger, a trial balance or a return by being well structured. NoxOrigin prepares the invoices, the payments, the allocations and the reports those filings are read from, and it files nothing — no GST returns, no other statutory return, and no posting to your accounts. Third, an as-of figure still depends on the records being right. If a customer exists twice, a month-end figure can be perfectly reproducible and still be about the wrong population, and that failure sits upstream of anything this article describes.

What we have not measured

Nothing here is measured. We have no count of how often month-end figures in the businesses we work with are re-exported because the first one could not be defended, no measured share of reporting disputes that turn out to be a moment or a definition rather than a business result, and no data on how often a late record is entered with an earlier date. The seven invoices, the client, the 70,800 allocation and the timings are arithmetic we constructed so that a 53,100 difference could be decomposed into exactly two events, and all of it is invented. What we would want to instrument before claiming anything: the number of times a period figure is re-exported and why, the share of disagreements resolved by an as-of moment or a definition rather than by new records, the count of late entries carrying a date inside a closed period, and the share of month-end figures that a second person could reproduce from the export alone. Until those are counted, the argument is structural, and the test costs nothing: take your last two month-end exports, put them side by side, and try to decompose the difference into named events. If you can, your reporting is reproducible. If the difference is a number you cannot account for, that is the finding.

Frequently asked questions

I exported the same report twice on the same day and got two different numbers. Which one is wrong?

On the evidence in this article, probably neither — and the useful work is decomposing the difference rather than defending a number. In the worked example the two exports differed by 53,100, and that resolved into exactly two events: a payment of 70,800 allocated against the oldest open invoice, and a late invoice of 17,700 entered with a date inside August. If your difference resolves into named events like that, both exports are true and you now have a documented movement. If it does not, the cause is not in the figures and you should look at what changed between the two runs.

What makes a figure reproducible?

Six things, and only the first is about the moment. An explicit as-of moment, ideally a timestamp rather than a date. The rows behind the total, not only the total, so a second person can re-derive the conclusion. The definition of the set — the period, the sites, the states, and every condition that excluded something, with the excluded items itemised. Both dates kept apart for anything involving money: the date it arrived and the date it was applied. And a record of what changed between two runs, so that when two exports differ the first question is answered by the record rather than by argument.

A figure that changes is not a bug then?

Correct, and we would be suspicious of a tool that promised otherwise. Money keeps arriving, invoices keep being raised late, and periods genuinely do need restating. The claim worth making is narrower and sufficient: given the records, the moment and the stated set, somebody else reaches the same number without asking you a question. A tool that guaranteed a figure never moves would be describing a system that has stopped responding to what happened in the business.

Why is there no stored paid flag that can go stale?

Because paid is not a fact about an invoice, it is a consequence of allocations. A payment is a separate record from the invoice it settles, and outstanding is the invoice total minus the sum of live allocations, recomputed from the records each time a report runs. That removes the failure where a stored status is read live and a figure has no as-of moment at all, because there is no stored value to be out of date. The states you see — issued, partly allocated, fully allocated, over-allocated, reopened by reversal — are arithmetic rather than something a person wrote down.

Someone allocated a payment to the wrong invoice and fixed it. Is that what made the figures move?

It can be, and the correction path matters here. A wrong allocation is reversed by an allocation reversal that names the allocation it reverses and carries an author and a reason. The payment itself is not edited — the money arrived and is in the bank, so its amount, date, method and reference stay as recorded and only the link changes. Editing or deleting the payment instead would falsify a bank fact and quietly break the cash figure for that day, which is a worse reproducibility problem than the one you were trying to fix.

Does the month have to be closed before the figure is worth arguing from?

Yes, and this is the practical heart of it. A period that has not been closed is still receiving entries, so any figure taken from it is a moving target. A closed period can be re-derived; an open one cannot. That applies at the scale of the trading day too — on a dedicated Nox-Billings deployment, shift close and day-end reconciliation are assisted setup, set up and validated with you during the deployment, because a close routine not aligned to how your business actually ends its trading period gives you a technically correct boundary and an operationally fictional one.

Sources and further reading

Continue reading

Looking for the rest of this topic? More in business operations →

ReportsThe Filter That Silently Excludes MoneyRead guide →OperationsWhat a Number Needs Before Two People Compare ItRead guide →ReportsReading a receivables ageing report without guessingRead guide →