Skip to content

[19.0][FIX] subscription_oca: avoid duplicated invoices per period#1473

Open
alvaro-domatix wants to merge 1 commit into
OCA:19.0from
alvaro-domatix:19.0-fix-subscription_oca-duplicate-invoices
Open

[19.0][FIX] subscription_oca: avoid duplicated invoices per period#1473
alvaro-domatix wants to merge 1 commit into
OCA:19.0from
alvaro-domatix:19.0-fix-subscription_oca-duplicate-invoices

Conversation

@alvaro-domatix

Copy link
Copy Markdown

Prevents a subscription from being invoiced twice for the same billing period.

If the recurring cron fails mid-batch and is relaunched, or if the manual invoice action is triggered again before the recurring date has advanced, the subscription otherwise produces two invoices for the same period. Two helpers are added on sale.subscription:

  • _get_existing_invoice_for_period(start, end) returns the first non-cancelled invoice whose lines link back to the subscription for that period (cancelled invoices do not block, since they can legitimately be re-issued);
  • _can_create_invoice_for_period(start, end) is the boolean wrapper.

manual_invoice raises a UserError with the formatted period when a blocking invoice exists; generate_invoice (cron path) logs a warning and returns False so the batch continues with the next subscription. Invoicing the next period is intentionally left allowed — a second call after the recurring date has advanced bills the following cycle, which is not a duplicate.

Depends on #1441 (track invoice periods on move lines): the guard searches by the subscription_period_start/end fields introduced there. The PR is opened against 19.0, so the diff currently includes the #1441 commit; once it merges, this auto-retargets to the duplicate-prevention changes only. It also shares the generate_invoice/manual_invoice area with #1440 (centralize recurring date computation) and will need a small rebase if #1440 lands first.

@alvaro-domatix alvaro-domatix force-pushed the 19.0-fix-subscription_oca-duplicate-invoices branch 2 times, most recently from af45e1d to e0d565c Compare June 25, 2026 17:57
If the cron failed mid-batch and was relaunched, or if a user clicked
the manual invoice action twice, the subscription happily produced two
invoices for the same billing period. There was no defense against
duplicates at the model level.

This change adds two helpers on sale.subscription:

* _get_existing_invoice_for_period(period_start, period_end): returns
  the first account.move whose lines link back to this subscription
  with the given period and whose state is not 'cancel'. Cancelled
  invoices do not block, since they can legitimately be re-issued.
* _can_create_invoice_for_period(period_start, period_end): the boolean
  wrapper used by callers.

manual_invoice raises a UserError with the formatted period when a
blocking invoice exists, so the user can act on it. generate_invoice
(called by the cron) logs a warning and returns False so the batch
continues with the next subscription.

The existing _collect_all_sub_test_results helper called create_invoice
and manual_invoice in immediate succession on the same period, which
under the new policy would mean creating duplicates. The fixture now
advances recurring_next_date between the two calls so it tests the
intended two-period workflow rather than the previously unprotected
duplicate.
@alvaro-domatix alvaro-domatix force-pushed the 19.0-fix-subscription_oca-duplicate-invoices branch from e0d565c to 7e8dd03 Compare June 25, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants