Most invoice problems start before the invoice
Ask a credit controller why an invoice is 60 days overdue and you’ll rarely hear “the customer has no money”. You’ll hear that it went to the wrong email, didn’t have a PO number, quoted last year’s price, or had one disputed line and the customer’s accounts team parked the whole thing.
Each of those is cheap to catch before posting and expensive to fix after. Once an invoice is out, the fix is a credit note, a reissue, a new payment term clock and an awkward email. Before posting, it’s a message on screen.
So we think about invoicing as a set of gates. What must be true about this customer, this invoice and this reference before it’s allowed to become a real document?
In practice the gates fall into three groups. Customer gates: this customer needs a PO, a site code, a named contact. Document gates: this reference hasn’t been used, the amount is within what was ordered, the tax template matches the customer’s country. Approval gates: this invoice is large or unusual enough that a second person looks at it. Most businesses need a handful of these, not dozens. The trick is writing down the ones your credit controller already checks in their head, then letting the system do the checking.
Inside the invoice management system we generate
On Odoo, invoices are account.move records. The addon adds customer-level requirements on res.partner, constraints on the invoice, and a check in _post so nothing is posted without passing. It uses the existing Reference field rather than inventing a new one, because the sales order’s customer reference already lands there. Disputes get their own model with chatter, so the conversation stays attached to the invoice.
On ERPNext, the Sales Invoice already has a customer PO field (po_no). The Frappe app adds a validate hook, a flag on Customer shipped as a fixture, an Invoice Dispute DocType and, if you want one, a review Workflow before submit. Print Formats get the PO and site reference placed where your customers expect them.
If you’re on Odoo and wondering whether Studio could do this instead, our comparison of Odoo Studio and a custom module shows where Studio runs out.
Example: a customer that bounces invoices
A facilities company cleans and maintains buildings for a hospital group with 14 sites. The hospital’s accounts payable team rejects any invoice without a valid PO number, and they don’t always say so quickly. Payment terms are 45 days, and a rejected invoice restarts the clock.
Last month the company raised 60 invoices to the group, averaging $3,200 each. Nine went out without a PO. Every one came back, some after three weeks. That’s roughly $28,800 of revenue arriving a month or more late, for a missing text field.
With the module, the hospital group is flagged as PO-required. An accounts clerk tries to post an invoice for the east wing contract without a reference and gets a clear message. Two days later, someone types last month’s PO number from the wrong email. The duplicate check stops it and names the earlier invoice. Nothing clever. Just two checks that someone used to do by eye at 5pm.
Things we won’t automate for you
- Posting supplier bills straight from OCR. Reading a PDF into a draft saves typing. Posting it unreviewed is how you pay the same bill twice.
- Editing posted invoices. Corrections go through credit notes. Both platforms are built around that, and so is every audit.
- Your own tax engine. Tax rules belong in the localisation and tax configuration. We’ll add checks around them, never a parallel calculation.
- Automatic reminders to disputed invoices. A customer who has raised a dispute and then gets a “your invoice is overdue” email will not be in a hurry to pay.
Where invoicing connects
Invoice quality depends on what came before. Clean sales orders make clean invoices, and vendor bills are far easier to check against disciplined purchase management. Once posted, everything lands in the ledger, and our page on a custom accounting module covers the controls that sit there.
Teams building on Odoo can read more about how addons are structured on our Odoo module development page.