Skip to content
Every figure traces to a ledger row, or the deliverable does not render

The computation engine

Five places it refuses, and one place it concludes

The engine is deterministic. It parses every row or names the one it could not, computes against the rate set for the assessment year, refuses a year nobody has reviewed rates for, cross-foots every table it produces, and stops before a word is drafted if the result does not tie. What it will not do is produce a number that has nothing behind it.

The arithmetic

No floating-point number touches a rupee

The dullest rule in the product and the one the rest of it rests on. Money is an exact decimal in the database, in the engine and in the browser, and the arithmetic layer raises on a float rather than quietly converting one — by the time a float arrives the precision is already gone, so the fix belongs upstream of the conversion.

Exact decimals end to end

Every monetary column is a fixed-precision decimal, every figure is parsed from text rather than from a float, and rounding happens once at the boundary rather than at each step. Intermediate rounding is how a schedule stops tying to its own lines, and it is invisible until it is embarrassing.

A float is an error, not an input

The money layer raises when handed one instead of coercing it. That is deliberately inconvenient: a coercion here would silently accept the one input that cannot be made exact again, and every figure downstream would inherit it.

The console does no arithmetic

Money reaches the browser as a decimal string and is displayed, not calculated with. A figure computed in a browser is a figure the deliverable cannot trace, which by this product’s own rules means it could never have been rendered anyway.

A figure that cannot be read is not a zero

A malformed amount raises rather than being coerced. A silent zero flows into a total and reconciles perfectly with nothing, which is worse than a row that stops and asks a person to look at it.

What it changes

Five thousand rows, reconciled twice

The same bank reconciliation over the same 5,000 rows, run in exact decimals and then in floating point. The interesting figure is not the total — it is what the difference comes to when it should be nothing at all.

Exact decimal arithmetic

0.00

The reconciliation ties to exactly zero

The same rows in floating point

−0.000000358

A residual, from nothing but the arithmetic

A residual that small is worse than a large one. It is too small to be a missing entry and too small to chase, so it gets described as a rounding difference and written off — and the next time a genuine difference of a few paise appears it is written off the same way, because the reconciliation has already taught everybody that it never quite reaches zero. A reconciliation that ties to zero is a control. One that ties to approximately zero is a habit.

Both figures are printed side by side by the project’s own checks, so the claim on this page is something the build asserts rather than something we remembered to be true.

Rates are data

Effective-dated, checksummed, and refused when they are missing

Slabs, surcharge bands and depreciation rates are rows keyed by assessment year, loaded from one reviewed source per year. They are not constants in a file that somebody edits in the third week of July.

  • A rate set exists per assessment year and per regime, and a computation names the year it is for rather than inheriting the current one.
  • An assessment year with no reviewed rate set is refused. It is never computed with last year’s numbers, which produces a figure of the right shape and the wrong amount.
  • Every computation records the checksum of the rate set that produced it, so a figure can be tied back to the exact rates it was computed under months later.
  • What will be applied is readable before a computation runs, rather than inferred afterwards from the result.
  • Surcharge is banded properly and marginal relief is applied — without it, a rupee over a threshold can cost a six-figure sum, which is the arithmetic error most likely to survive review because the total still looks plausible.

Rates as code is the defect that keeps professional software out of professional use. It means the software is only correct for the year somebody last edited it, and it fails by producing an answer rather than by producing an error.

The arithmetic gate

Nothing is drafted for a set of books that does not add up

The gate sits between the computation and everything that renders, which is the last point at which every figure exists and nothing has yet been drafted, rendered or exported. A gate placed after the drafting would still block the document, but only after the model calls the firm has already paid for.

  • Every table the engine produces is cross-footed — totals against their lines, and the statements against each other.
  • A job whose figures do not tie ends naming the account and the amount it is out by, and no document is written at all.
  • That end state is not a failure. A failed job is something that went wrong in this system and is a support ticket; a blocked one is this system working, and is a correction to make in the books.
  • The gate also blocks a computation nobody wrote a check for, which is the hole a gate like this usually dies of — an unchecked table is not a passing table.
  • There is no bypass. Not a parameter, not a setting, not an exemption for one kind of job, and the build fails if somebody adds one.

The three checks a member runs by hand

A difference is not just a number, it is a clue about what caused it. Before reporting the block, the gate runs the three tests anybody does with a pencil — and says plainly when none of them fires rather than guessing.

  • An account carrying the difference

    One account out by exactly the amount is usually an entry posted once instead of twice, or to the wrong side. The gate names it if it finds one.

  • An account carrying half of it

    A difference of twice an account’s balance is the signature of an amount posted to the wrong side — debited where it should have been credited.

  • The divisible-by-nine test

    A difference that divides by nine points at a transposition: two digits swapped somewhere. It is the oldest check in the trade and it still works.

This is the one rule on this page with no exception anywhere in the software. When it was first switched on it immediately blocked a fixture whose trial balance had been out by ₹1,99,598.70 since the day it was written, and had passed every test until then. The fixture was corrected; the gate was not weakened.

Nothing is dropped silently

Every row is accounted for, and the arithmetic says so

The commonest way a reconciliation goes wrong is not a bad match. It is rows that never arrived, in a file that looked like it imported cleanly.

  • Parsed plus rejected plus duplicate must equal the number of rows submitted. That is a database constraint rather than a convention, so it cannot hold everywhere except where it matters.
  • Every rejected row is kept exactly as the file wrote it, with the reason it was refused, and shown on a screen rather than written to a log.
  • An unrecognised format is an error. A parser that returns an empty ledger on a file it did not understand produces a reconciliation that balances beautifully over nothing.
  • A truncated export names the byte offset where it stopped, instead of returning the rows it managed to read as though they were all of them.
  • Client narrations are treated as hostile input everywhere: parsed on the server, rendered as text in the console, and neutralised on the way into a spreadsheet.

Reconciliation

An item that is three months old reads as three months old

Matching is the visible half of a reconciliation. The half that decides whether it is any good is what happens to the items that did not match, at the end of the period, when somebody has to do it all again.

Carry-forward on the row fingerprint

An item still outstanding in March appears in April pointing at its predecessor and keeping the period it was first raised in. A cheque uncleared since January reads as three months old rather than as a new item every month — which is the difference between an ageing that means something and one that resets itself.

A cleared item carries its narration

In the schema, not by convention. A cleared item with no explanation is indistinguishable from one somebody deleted because it was inconvenient, and it is the first thing a peer reviewer looks for.

The proposer cannot approve their own adjustment

A database constraint rather than a rule in a controller. Role and identity are two separate controls: an articled assistant may not approve at all, and a manager may approve but not their own.

An unsupported kind is refused

Bank, GST and TDS have real matching workflows. A kind that does not is refused rather than reconciled to an empty result that reports as complete.

Provenance

Every figure has a line, and every line has its row

The separation this product is built on: the arithmetic produces figures, the drafting produces prose, and the two are joined only where a figure can name where it came from.

  1. 01

    A figure in the deliverable

    Rendered from a computation line and nowhere else. A number written into a drafted paragraph with no line behind it is a blocking error, demonstrated against a case deliberately prompted to produce one.

  2. 02

    The computation line

    Carries the amount, what it is, the schedule it belongs to, the rate set it was computed under and a reference to the source it came from.

  3. 03

    The working paper

    The schedule a reviewer actually reads, with its tickmarks and its cross-references to the other papers that support it.

  4. 04

    The ledger row

    The row that was imported, including the rows that were rejected and why. Nothing is dropped silently: parsed plus rejected plus duplicate equals what was submitted.

Every read and every export writes an audit row with the actor and the time. "Who exported this client’s working papers, and when" is a query rather than an investigation — and the answer is retained for as long as the statute requires the papers themselves to be.

Bring a reconciliation you have already had to defend

The fastest way to judge this is against a real one. Which difference took the longest to find, what a reviewer sent back, and how long the schedule took to assemble by hand.

Get in touch

Talk to the people building it

No chatbot and no ticket queue. Tell us what your practice actually looks like — how many members sign, how many prepare, which of audit, tax and compliance you do most of — and someone who works on the software will reply.

info@legosphere.com

Please keep client names, PANs, GSTINs, account numbers and ledger extracts out of this box — it is an ordinary enquiry form, not a channel for a live engagement.