
Customer Portal: Statement of Account & Payments
A statement of account in the customer portal: every open item, how old it is, the total owed, as a PDF - and a way to report what they paid.
Available for Odoo 16.0, Odoo 17.0, Odoo 18.0, Odoo 19.0. Technical name bambooforge_customer_portal.
Customer Portal: Statement of Account & Payments
Odoo Community's portal lists a customer's invoices and lets them pay one. It never tells them what they owe altogether, never shows how old any of it is, and gives them nowhere to say we paid this on Tuesday, here is the reference.
So the question that starts every collection call — what is outstanding, and what have you already sent us — gets answered by exporting a spreadsheet and attaching it to an email.
The statement
Every posted, unpaid invoice and credit note, oldest first: the document, the reference the customer's own accounts department filed it under, the dates, the original amount and what is left on it. Then a total, in one figure, at the top of the page.
A credit note reduces what is owed rather than adding to it — which sounds obvious until you have seen a statement where it did the opposite.
How old it is
Five bands: not yet due, 1–30, 31–60, 61–90, and more than 90 days.
Measured from the due date, not the invoice date. A document on sixty-day terms is not an overdue account in its second week, and an ageing report that says it is will be argued with rather than paid. That one decision is the difference between a statement a customer acts on and a statement a customer replies to.
The bands always add up to the total. There is a test that fails if they ever stop doing so.
As a PDF
One button on the portal page. The customer gets the same statement as a document they can file or forward, without anybody in your office producing it.
Telling you what they paid
The other half. The customer ticks which invoices a payment covers, says how much and when, gives the reference their bank will show, and attaches the remittance document.
It arrives in your accounts department beside the ledger, never in it. Matching one drafts an account.payment for somebody to check against the bank before posting. The figures came from outside; a portal that posts receipts unread is a portal that writes into your ledger.
The list shows, per advice, what the customer announced against what the invoices they ticked actually come to, and says so when the two differ. That gap is nearly always a part payment, a deduction, or an invoice they have forgotten — and all three are worth seeing before the payment is drafted, not after.
Nobody can create a remittance advice by hand, in any group. What a customer told you is evidence; somebody who could type one could also type the payment they wish had arrived, and afterwards nothing would tell the two apart.
What the page will not do
The statement is scoped to the logged-in customer's own commercial partner and the contacts under it, in a company they already have posted documents in. Never a partner or a company named in the request — a page that reports on whoever the URL says is a way to read somebody else's ledger one identifier at a time.
An invoice ticked on the form is checked against that customer's own open items, in the controller and again as a database constraint. A zero or negative amount is refused. A payment dated in the future is refused, because it has not happened. Uploads are PDF, PNG or JPEG, up to 10 MB.
Invoices belonging to a branch of the same customer do appear, and can be ticked — a statement that shows only one contact's invoices never matches what the customer's own accounts department is looking at.
Series
Community 16.0, 17.0, 18.0 and 19.0.
Screens



