Why a ₹15,000 invoice and a ₹15,000 payment are not the same record
The partial-payment data model, written by the people who build the billing engine: why a paid flag destroys audit history, how invoice, payment, allocation, and state transitions are separated, and where the model still fails.
A ₹15,000 invoice and a ₹15,000 payment are different events, and the gap between them is the entire problem. The invoice is a claim: this is what you owe, under these terms, for this work. The payment is a fact: this much arrived, on this date, by this route, from this person. Fuse the two into one record and you get a number that looks correct and cannot answer any question a business actually asks.
This is not an exotic scenario. A repair job invoiced today and settled in three instalments, a wholesale invoice paid partly by transfer and partly in cash, a sale returned a week after the receipt was reprinted — these are ordinary Indian retail and service cases. Below is the data model we hold ourselves to, why each record is separate, and where it still fails.

What a boolean or a single amount field destroys
The tempting shortcut is `invoices.paid = true`, or `invoices.paid_amount = 15000`. Both work perfectly on the happy path and both destroy the audit history the first time the counter meets reality.
Take a real sequence: invoice ₹15,000 issued on the 3rd; the customer pays ₹5,000 as an advance on the 4th; ₹7,000 arrives by UPI on the 9th; the remaining ₹3,000 is handed over as cash at close on the 12th. With a boolean, the invoice flips from unpaid to paid and every trace of a three-part settlement disappears. With one amount field you can show ₹15,000 received, but you cannot say when the invoice stopped being outstanding, in how many receipts, by which methods, or who accepted each part. The ageing report collapses into a single marker, and day-end cash reconciliation loses the fact that ₹5,000 and ₹7,000 were physically received on different days and belong to different days' cash.
Three ways to represent 'settled' (structural comparison — no measured outcomes)
| Shape | What it stores | What it cannot answer | Where it breaks |
|---|---|---|---|
| Boolean flag | That a payment happened | When, how much, by what method, in how many parts | First partial payment |
| Single amount field | A running total received | The individual receipts, their dates, and the composition | Any settlement split across days or methods |
| Invoice + allocation + payment | Every money event, and how each maps to a claim | Nothing about the settlement itself — but settlement intent still needs a human | Ambiguous remittances and restatements |
The four records, and which one is the truth
We model the claim, the money event, the link between them, and the resulting state as four different things. Keeping them apart is what makes an ageing report a query rather than an investigation.
The four records
Invoice — the claim
Number, date, counterparty, line items, tax breakup, total, terms, due date. Immutable once issued. Corrections do not edit it; they attach a credit or debit note to it, so the original taxable event stays on the record.
Payment — the money event
Amount, method, received-at, the counterparty or account it came from, an external reference if the counter has one, and an idempotency key so a retried submission cannot create a second receipt. A payment may exist before anyone knows which invoice it settles.
Allocation — the link
How much of which payment applies to which invoice. One payment can settle several invoices; one invoice can be settled by several payments. This is the record that makes partial settlement representable without lying about the whole.
State transitions — the projection
Issued, partly allocated, fully allocated, over-allocated, offset by credit note. This is derived from the allocations, not stored. Storing it as a column is what creates two sources of truth that eventually disagree.
Partial payments without a special case
A partial payment should not need a separate feature. If allocation is a first-class record, part payment is just an allocation smaller than the outstanding balance, and the invoice's state is recomputed rather than toggled. The three-part settlement above needs no special handling: three payment records, three allocations, one derived state that reads as fully allocated on the 12th.
The discipline this imposes is useful. Outstanding is not a number someone maintains; it is `invoice total − sum(allocations)`, so it cannot drift out of step with the payments that produced it. When a customer disputes, you are not arguing about a status field — you are reading a list of receipts.
Overpayments, refunds, and credit notes
Each of these is a different event and only one of them is a reversal. Conflating them is the second most common way a billing record becomes indefensible.
How each money event attaches (illustrative structural comparison)
| Event | Record it touches | Effect on the invoice | Must stay visible |
|---|---|---|---|
| Overpayment | Payment with no allocation, or allocated beyond the balance | Invoice settles; the excess becomes a credit balance owed back or carried forward | The customer's claim to the excess and its age |
| Refund of a payment | New payment record plus a reversing allocation | Invoice returns to partly or wholly outstanding | The original receipt and the reason for the reversal |
| Credit note | A new document against the original invoice | Reduces the amount claimable | The original taxable event, unedited |
| Debit note | A new document against the original invoice | Increases the amount claimable | Why the increase happened |
| Cancellation | Status change with a reason | Removes the claim, keeps the record | Who cancelled it and when |
What an ageing report has to read from
An ageing report is only as good as the records behind it
- The invoice total, taken from the issued document rather than a running total on a mutable row
- The sum of allocations per invoice, so partially settled invoices age on the outstanding amount rather than the gross amount
- Allocation dates, so the ageing bucket reflects when money was applied rather than when it happened to arrive
- Credit notes and reversals, because a refunded invoice is not a healthy receivable
- The counterparty's identity, because collection is a queue with an owner, not a total
- An explicit 'as of' moment, because late entry can move an invoice between buckets after the fact
Terms used above
- Invoice
- The claim. What the business is owed, and under what terms.
- Payment
- The money event. What arrived, when, how, and from whom.
- Allocation
- The link that applies part of a payment to part of an invoice.
- Credit balance
- Money received against a customer who is not owed it — refundable or carried forward.
- Credit note
- A new document reducing an earlier invoice, never an edit of it.
Where this design still fails
Three places, stated plainly. First, ambiguous remittances. A single bank credit arriving for four invoices with no remittance advice cannot be allocated by a data model; somebody has to decide, and a system that guesses is lying. The honest behaviour is to hold the payment unallocated, show it as an exception for a human, and let the decision be recorded. Second, restatement. Correcting an issued tax invoice is not a database operation — it is a regulatory event with its own document, and any model that treats it as a field update will eventually produce a number nobody can defend to a tax authority. Third, time. An ageing bucket is a function of an 'as of' moment, and late-entered records move invoices between buckets after the fact. Reports that do not state their as-of moment are not comparable month to month, however correct each one is.
What we have not measured
This article describes a model and the reasoning behind it. It contains no benchmark, no throughput figure, no dispute rate, and no customer data, because we do not have a measured basis for any of those. We have not instrumented allocation write contention, ageing-report query cost at volume, or the real distribution of how Indian SMEs actually settle invoices. Those are the measurements we would want before making a performance or reliability claim, and until they exist the model is a design we are held to, not a proven result.
Frequently asked questions
Should an invoice and its payment live in the same table?
They should be able to sit in the same physical table, but they must be different records with different identities. The invoice is the claim; the payment is the money event; the allocation is the link between them. Fusing them means you cannot represent a part payment, a single payment across several invoices, or a refund that references the original receipt.
How is a part payment actually recorded?
As a payment record with its own amount, method, and received-at, plus an allocation applying some of it to the invoice. The invoice's outstanding amount is then derived as total minus the sum of allocations, rather than stored as a field someone keeps up to date.
What happens if a customer pays more than the invoice?
The excess becomes a credit balance belonging to the customer — refundable or carried forward to the next invoice. It should stay visible with its own age, because untracked overpayments are a quiet way for a small business to hand money back six months later without noticing.
Can staff edit an invoice that has already been paid against?
No. The issued invoice stays as it was, because it is a document somebody may have already filed or used to claim input tax credit. Corrections attach as credit or debit notes referencing the original. Reversals and cancellation are recorded as events with reasons and actors, not as deletions — the same principle described in our storno explainer.
How does splitting the payment record affect GST reporting?
It does not change the taxable event, which stays with the invoice as issued. Partial settlement affects when value is collected, not what was supplied, and corrections are made through credit and debit notes rather than by editing the original document. GST treatment is business-specific — confirm your position with a qualified tax professional rather than relying on a software article.
Can I migrate an existing spreadsheet of outstanding invoices?
Yes, with a decision about cut-off. Decide the date from which NoxOrigin becomes the record of truth, migrate the open invoices with their invoice dates and outstanding amounts, and record already-received amounts as payments with their original received-at dates rather than flattening them into a paid flag. Keep a read-only archive of the old sheet.