Skip to content

Software Engineering

Why an invoice should keep a snapshot of the details used to create it

A client changes their address and a catalog price changes next month. Mavri keeps the business, customer and line details on each document so later edits do not rewrite billing history.

By · Published · 5 min read

A customer's address changes. A product gets a new price. The business updates its bank details. Those are ordinary edits to reusable records, but they should not rewrite the invoice that was issued last month. In Mavri, a document keeps a snapshot of the business, customer, line items and presentation details used when it was made.

A live reference changes the past

If an invoice stores only customer_id and reads the customer's current address every time it renders, editing the customer changes every old invoice on screen. The same bug appears when line items point only to a mutable product catalog: changing a description or price alters the historical document, even though the customer received the earlier version.

The interface may look correct at first. The problem surfaces months later when someone reprints a document, resolves a dispute or tries to understand why a total differs from today's catalog. A historical document needs to answer what was sent, not what the reusable record says now.

Copy the values that define the transaction

When a user adds a client or catalog item to a quote or invoice, Mavri copies the relevant values into the document: names and contact details, line descriptions, quantities, prices, tax choices, currency, bank information and selected style. The reusable client and catalog records remain useful for the next document; they are not the source of truth for the one already created.

That is denormalization with a specific boundary. The catalog is the source for defaults when composing a new document. The document snapshot is the source for rendering that document later. Keeping the two roles separate makes the behaviour understandable to the person using the app.

Quotes need the same care as invoices

A quote may sit for weeks while the business changes its catalog or terms. If the customer accepts the quote, converting it to an invoice should carry forward the agreed details. Re-reading the current catalog during conversion can silently change the offer between acceptance and billing.

Mavri converts an accepted quote into an invoice using the values already recorded on the quote. It also keeps the quote and resulting invoice as distinct documents, so the trail remains legible. Users can still deliberately edit a draft; the important boundary is that changing reusable defaults does not silently mutate an existing document.

What snapshots cost

A snapshot duplicates data. If the business name changes, old invoices retain the old name; if an address was wrong, the operator has to correct the document deliberately or issue a new one, depending on its state and local rules. That is more storage and more explicit editing than a normalized database with live foreign-key lookups.

For invoices and accepted quotes, that cost is useful. A billing record should preserve the facts used at the time, while the account profile should remain easy to update for future work. The design should make this distinction visible, and the app should never imply that a PDF export or an electronic format by itself proves legal compliance.

A practical test for any invoicing app

Before adopting billing software, create a quote with a real customer and one catalog item. Change the customer's address and the item's description, then reopen the quote and convert it. If the old values have changed without an explicit document edit, the app is reading mutable defaults where it should preserve a transaction snapshot.

This is one small data-model choice with a direct consequence for trust. Invoicing software should make it easy to reuse records and hard to accidentally rewrite what a customer already agreed to.

The same app handles retried webhooks without duplicate invoices and runs from one container and one origin. The full write-up of the product is in the Mavri case study; the Mavri website has the install guide and docs.

References

Author

Raktim Ranjit is a software engineer and the founder of NodeDR Infotech. He builds and maintains the software described here.

Have something in mind?

Let’s build something useful.

Tell me about the idea, product, or workflow you’re working through.

Tap to say hello