| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Discuss (mail) |
| Community Apps Dependencies | Show |
| Lines of code | 3687 |
| Technical Name |
eh_account_recurring_invoices |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Discuss (mail) |
| Community Apps Dependencies | Show |
| Lines of code | 3687 |
| Technical Name |
eh_account_recurring_invoices |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
Recurring Invoices Pro
Template-driven recurring customer invoices on Community, with a self-healing cron and concurrency-safe issuance that never double-bills a period.
Why this module
Recurring Invoices Pro
The cadence is real, not a calendar trick
An arbitrary N interval over five built-in units (day, week, month, quarter, year). Every 2 weeks, every 6 months, monthly, quarterly, yearly are all settings. Bound the run with an end date or a maximum invoice count, and the template finishes itself.
One bad template never freezes the queue
The daily cron isolates each template in its own savepoint. A generation failure rolls back the partial draft, the schedule still advances, and the captured error is parked on the template, so the cron never retries a broken record forever or stalls the others behind it.
Standard invoices, yours to keep
Output is plain account.move out_invoice records, so core reconciliation, the customer statement, and every report already understand it. LGPL-3 source on disk, no activation key, no phone-home, no recurring licence.
Day in the life
A billing clerk reprices a subscription mid-cycle and lets the rest run itself.
Twelve monthly retainer templates sit active, each issuing a draft invoice on its own day for review. One client moves to a higher tier mid-month. The clerk opens the proration wizard on that template: in a single savepoint it books a credit note for the unused calendar days, issues a new-price invoice for the remainder, and reprices the template going forward, so a credit can never land without its matching charge. Overnight, the daily cron walks every due template, generates each in its own savepoint, and advances the schedules. One template references a product that was archived, so its generation fails; the cron rolls back that partial draft, still advances its next run, and records the error on the template. The clerk sees the parked template in the morning, fixes the line, and the other eleven invoices are already waiting in draft, untouched.
Edge cases
The cases most modules quietly ignore.
In the shipped code today, each one a place where a cheaper module silently does the wrong thing.
Manual issuance takes a SELECT FOR UPDATE row lock and invalidates the cache before reading the next-run date, so a double-click or browser retry serialises: the second request issues the NEXT period instead of double-billing the current one.
If even advancing the next-run date fails, it is retried in its own savepoint and the template is parked with the captured error and logged at ERROR level, so one stuck record never makes every later cron tick retry it forever.
A failed generation rolls back the partial draft move, but the template's next-run date still advances and the error is recorded, so a single bad period does not freeze the whole cadence.
Proration refuses ambiguous cases instead of guessing: multi-line templates and zero-days-remaining are rejected with explicit UserError remedies rather than producing a wrong credit.
The credit note, the new-price invoice, and the template reprice all commit under one savepoint, so a partial failure cannot leave a credit note without its matching charge.
Configuring a recurrence longer than 12 months (for example interval unit accidentally set to year) raises a soft onchange warning before the schedule is saved.
A finished template cannot be silently reactivated, and a template without lines cannot be activated or generated, so empty or zombie schedules never start issuing.
Template code is validated against a strict identifier pattern and is unique per company, preventing collisions when several companies share the database.
What is inside
Built to do the job, end to end.
- Recurring template. One template per billing arrangement: customer, sale journal, payment term, fiscal position, default ref and narration, with multi-line products, descriptions, per-line income accounts, quantities, unit prices and taxes.
- Cadence engine. Arbitrary N interval over day, week, month, quarter or year, bounded by an optional end date or maximum invoice count. The template advances itself and finishes when the limit is reached.
- Daily generation cron. Dispatches every active template whose next run is due, each in its own savepoint, with per-template error isolation and self-healing advance so the queue keeps moving even when one template fails.
- Manual generate now. A lock-safe catch-up button that issues one invoice and advances the schedule under a row lock, so concurrent requests cannot double-bill the same period.
- Proration wizard. Atomic mid-cycle price change: calendar-day pro-rata credit note, new-price invoice and template reprice in a single savepoint, with explicit guards against ambiguous inputs.
- Lifecycle and counters. Pause and resume that keeps the cadence intact, draft-by-default with optional per-template auto-post, and readonly counters for total generated, last run timestamp, last generated move and last error.
Honest about the edges
What this does not do, so nothing surprises you.
- Invoices are issued in the company currency. The template inherits the company currency and cannot bill in a non-company currency, so there is no per-template or per-customer foreign-currency option.
- This module does not email or send the generated invoice. It creates the account.move and only optionally posts it when auto-post is set; delivery is left to your standard Odoo flows.
- Reconciliation, the customer statement and portal behaviour are core Odoo, not added here. The module generates standard out_invoice records and relies on core for everything downstream.
- There is no dedicated append-only audit-log model. Each generation stamps last run, last generated move, count and last error on the template, and proration changes are logged to the template chatter.
- Multi-company is supported with a sale journal and per-line income accounts, but currency is fixed to the company currency as noted above.
recurring invoices Odoo 19 Community, recurring customer invoices Odoo, subscription billing Odoo Community, recurring invoice template Odoo, automatic invoice generation cron Odoo, mid-period proration credit note Odoo, recurring invoice cadence daily weekly monthly quarterly yearly, auto-post recurring invoices Odoo
Please log in to comment on this module