Skip to content

[IMP] subscription_oca: compute MRR and ARR#1443

Closed
alvaro-domatix wants to merge 1 commit into
OCA:19.0from
alvaro-domatix:19.0-imp-subscription_oca-mrr-arr
Closed

[IMP] subscription_oca: compute MRR and ARR#1443
alvaro-domatix wants to merge 1 commit into
OCA:19.0from
alvaro-domatix:19.0-imp-subscription_oca-mrr-arr

Conversation

@alvaro-domatix
Copy link
Copy Markdown

Problem

sale.subscription.recurring_total is the sum of the line price_subtotal without normalising to a single cadence. A yearly subscription that bills 1 200 € once a year and a monthly one that bills 100 € a month look very different in the list view even though they generate identical recurring revenue. Aggregating across cadences is impossible — the basic management question "how much do I bill per month?" can only be answered by exporting to a spreadsheet and dividing case by case.

Solution

Add two new stored computed monetary fields on sale.subscription:

  • recurring_monthly — monthly recurring revenue (MRR), summed from a per-line recurring_monthly.
  • recurring_yearly — twelve times the monthly figure (ARR).

The line-level recurring_monthly divides price_subtotal by the number of months in the line's period. The factor is 1 / 30.4375 for days, 7 / 30.4375 for weeks, 1.0 for months and 12.0 for years, multiplied by recurring_interval. So a 100 €/week line yields ≈ 434.82 €/month, a 1 200 €/year line yields 100 €/month, a 300 € line every 3 months yields 100 €/month.

UI changes:

  • Form view: new stat button showing MRR and ARR side by side.
  • List view: recurring_monthly (sum footer, optional show) and recurring_yearly (optional hide).
  • Search view: new "With recurring revenue" filter (recurring_monthly > 0).

No existing field is renamed, dropped or otherwise altered (see §0.4 of the internal compatibility checklist). Pure additive change.

Migration

-u subscription_oca triggers a normal ORM recompute. No data script. Estimate roughly two seconds per ten thousand subscription lines on commodity hardware.

How to test

  1. Install the module and create a template with recurring_rule_type = months, recurring_interval = 1. Add a subscription line with a 100 € product → recurring_monthly = 100, recurring_yearly = 1200.
  2. Switch the template to yearsrecurring_monthly = 100 / 12 ≈ 8.33.
  3. Switch to weeks, interval 1 → recurring_monthly = 100 * 30.4375 / 7 ≈ 434.82.
  4. Switch to months, interval 3 → recurring_monthly = 100 / 3 ≈ 33.33.
  5. Open the subscription list view → MRR column is summable.
  6. Apply the search filter "With recurring revenue" → only subscriptions with positive MRR remain.

The bundled tests in tests/test_subscription_mrr.py cover all of the above plus aggregation across lines and recompute after qty or template changes.

Add two stored computed monetary fields on `sale.subscription`:

* `recurring_monthly` — sum of the subscription lines normalised to a
  monthly amount (Monthly Recurring Revenue).
* `recurring_yearly` — twelve times the monthly figure (Annual
  Recurring Revenue).

Each line also exposes its own `recurring_monthly`, derived from
`price_subtotal` and the template recurrence. A line that bills every
N `days`, `weeks`, `months` or `years` is converted to months using
30.4375 average days per month for sub-monthly cadences and a direct
multiplier otherwise, then divided by the `recurring_interval`.

This makes subscriptions of different cadences directly comparable and
sum-able, so reports can answer the basic "how much do I bill per
month?" question without external spreadsheets.

The fields are visible as a new MRR/ARR stat button on the
subscription form, as optional columns with sum aggregation on the
list view, and as a "With recurring revenue" filter on the search
view.

Migration: pure ORM recompute on `-u subscription_oca`. Expect roughly
two seconds per ten thousand subscription lines.
@alvaro-domatix alvaro-domatix force-pushed the 19.0-imp-subscription_oca-mrr-arr branch from 25e1ba6 to 6a3da2d Compare May 27, 2026 16:55
@alvaro-domatix
Copy link
Copy Markdown
Author

Closing to keep iterating locally; will resubmit when ready.

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