diff --git a/spreadsheet_dashboard_subscription_oca/README.rst b/spreadsheet_dashboard_subscription_oca/README.rst new file mode 100644 index 00000000..219d847b --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/README.rst @@ -0,0 +1,111 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +======================================= +Subscription OCA Spreadsheet Dashboards +======================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f1ffb09d1dc8f9a4a2d46af8273e5e4dd79b3e6e6f6fae841fa49a7434cd02c0 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fspreadsheet-lightgray.png?logo=github + :target: https://github.com/OCA/spreadsheet/tree/19.0/spreadsheet_dashboard_subscription_oca + :alt: OCA/spreadsheet +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/spreadsheet-19-0/spreadsheet-19-0-spreadsheet_dashboard_subscription_oca + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/spreadsheet&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds spreadsheet dashboards for subscriptions, built on top +of the community ``spreadsheet_dashboard`` engine and the analysis +models provided by ``subscription_oca``. No enterprise dependency is +required. + +It ships four ready-to-use dashboards under the **Dashboards** +application, in a dedicated *Subscriptions* group: + +- **Subscriptions**: monthly/annual recurring revenue, active + subscriptions and average MRR, with breakdowns by template, product + category, sales team, salesperson, start month and stage. +- **Salesperson**: recurring revenue and number of subscriptions broken + down by salesperson and sales team. +- **MRR Evolution**: net/new/churned MRR and the cumulated MRR over + time, with a monthly new-vs-churn breakdown. MRR change events are + derived from the current state of the subscriptions (a positive event + at the start date and a negative one at the closing date); mid-life + expansion/contraction is not tracked, which would require a dedicated + MRR event log. +- **Retention**: cohort sizes and recurring revenue per start month, + plus a retention/survival curve built from the start and closing + dates. + +All dashboards expose global filters (salesperson, sales team, customer, +template) and refresh automatically from the subscription analysis +models. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Open the **Dashboards** application. The four dashboards are available +in the *Subscriptions* group. Use the filters at the top (salesperson, +sales team, customer, template) to narrow down the figures. The data is +aggregated from the ``sale.subscription.report``, +``sale.subscription.mrr.report`` and +``sale.subscription.retention.report`` analysis models and refreshes +automatically. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Domatix + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/spreadsheet `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/spreadsheet_dashboard_subscription_oca/__init__.py b/spreadsheet_dashboard_subscription_oca/__init__.py new file mode 100644 index 00000000..a161af09 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2026 Domatix - Alvaro Domatix +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import models diff --git a/spreadsheet_dashboard_subscription_oca/__manifest__.py b/spreadsheet_dashboard_subscription_oca/__manifest__.py new file mode 100644 index 00000000..97974a86 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2026 Domatix - Alvaro Domatix +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Subscription OCA Spreadsheet Dashboards", + "version": "19.0.1.0.0", + "license": "AGPL-3", + "author": "Domatix, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/spreadsheet", + "category": "Productivity/Dashboard", + "summary": "Spreadsheet dashboards for subscriptions (MRR, salesperson)", + "depends": ["spreadsheet_dashboard", "subscription_oca"], + "data": [ + "security/ir.model.access.csv", + "report/sql_report_views.xml", + "data/spreadsheet_dashboards.xml", + ], + "auto_install": True, + "development_status": "Beta", +} diff --git a/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json b/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json new file mode 100644 index 00000000..ddab7c8f --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json @@ -0,0 +1,707 @@ +{ + "version": "18.5.10", + "sheets": [ + { + "id": "dashboard", + "name": "Dashboard", + "colNumber": 22, + "rowNumber": 80, + "rows": {}, + "cols": { + "0": { + "size": 50 + }, + "1": { + "size": 50 + }, + "2": { + "size": 50 + }, + "3": { + "size": 50 + }, + "4": { + "size": 50 + }, + "5": { + "size": 50 + }, + "6": { + "size": 50 + }, + "7": { + "size": 50 + }, + "8": { + "size": 50 + }, + "9": { + "size": 50 + }, + "10": { + "size": 50 + }, + "11": { + "size": 50 + }, + "12": { + "size": 50 + }, + "13": { + "size": 50 + }, + "14": { + "size": 50 + }, + "15": { + "size": 50 + }, + "16": { + "size": 50 + }, + "17": { + "size": 50 + }, + "18": { + "size": 50 + }, + "19": { + "size": 50 + }, + "20": { + "size": 50 + }, + "21": { + "size": 50 + } + }, + "merges": [], + "cells": {}, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [ + { + "id": "cccccccc-0000-0000-0000-000000000001", + "width": 345, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Net MRR", + "color": "#1f2937", + "bold": true + }, + "background": "#EFF6FF", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C1", + "chartId": "cccccccc-0000-0000-0000-000000000001" + }, + "offset": { + "x": 16, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000002", + "width": 345, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "New MRR (all time)", + "color": "#1f2937", + "bold": true + }, + "background": "#F0FDF4", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C2", + "chartId": "cccccccc-0000-0000-0000-000000000002" + }, + "offset": { + "x": 377, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000003", + "width": 345, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Churned MRR (all time)", + "color": "#1f2937", + "bold": true + }, + "background": "#FEF2F2", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C3", + "chartId": "cccccccc-0000-0000-0000-000000000003" + }, + "offset": { + "x": 738, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000010", + "width": 1068, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Net MRR Over Time" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["event_date:month"], + "measure": "mrr_change", + "order": null, + "resModel": "sale.subscription.mrr.report", + "mode": "line", + "cumulatedStart": true + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [], + "groupBy": ["event_date:month"], + "orderBy": [] + }, + "type": "odoo_line", + "dataSets": [{}], + "chartId": "cccccccc-0000-0000-0000-000000000010", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_mrr_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "cumulative": true, + "cumulatedStart": true + }, + "offset": { + "x": 16, + "y": 172 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000011", + "width": 1068, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR Change by Month & Type" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["event_date:month", "event_type"], + "measure": "mrr_change", + "order": null, + "resModel": "sale.subscription.mrr.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [], + "groupBy": ["event_date:month", "event_type"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "cccccccc-0000-0000-0000-000000000011", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_mrr_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "stacked": true + }, + "offset": { + "x": 16, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000012", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR Change by Type" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["event_type"], + "measure": "mrr_change", + "order": null, + "resModel": "sale.subscription.mrr.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [], + "groupBy": ["event_type"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "cccccccc-0000-0000-0000-000000000012", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_mrr_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 16, + "y": 932 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000013", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "New MRR by Template" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["template_id"], + "measure": "mrr_change", + "order": null, + "resModel": "sale.subscription.mrr.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["event_type", "=", "new"]], + "groupBy": ["template_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "cccccccc-0000-0000-0000-000000000013", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_mrr_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 558, + "y": 932 + }, + "col": 0, + "row": 0 + }, + { + "id": "cccccccc-0000-0000-0000-000000000014", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "New MRR by Salesperson" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["user_id"], + "measure": "mrr_change", + "order": null, + "resModel": "sale.subscription.mrr.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["event_type", "=", "new"]], + "groupBy": ["user_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "cccccccc-0000-0000-0000-000000000014", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_mrr_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 16, + "y": 1312 + }, + "col": 0, + "row": 0 + } + ], + "tables": [], + "areGridLinesVisible": false, + "isVisible": true, + "headerGroups": [], + "comments": {} + }, + { + "id": "data", + "name": "Data", + "colNumber": 8, + "rowNumber": 30, + "rows": {}, + "cols": {}, + "merges": [], + "cells": { + "A1": "=_t(\"MRR KPIs\")", + "B1": "=PIVOT.VALUE(1,\"mrr_change:sum\")", + "B2": "=PIVOT.VALUE(2,\"mrr_change:sum\")", + "B3": "=PIVOT.VALUE(3,\"mrr_change:sum\")", + "C1": "=IFERROR(FORMAT.LARGE.NUMBER(B1))", + "C2": "=IFERROR(FORMAT.LARGE.NUMBER(B2))", + "C3": "=IFERROR(FORMAT.LARGE.NUMBER(B3))" + }, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [], + "tables": [], + "areGridLinesVisible": true, + "isVisible": false, + "headerGroups": [], + "comments": {} + } + ], + "styles": {}, + "formats": {}, + "borders": {}, + "revisionId": "START_REVISION", + "uniqueFigureIds": true, + "settings": { + "locale": { + "name": "English (US)", + "code": "en_US", + "thousandsSeparator": ",", + "decimalSeparator": ".", + "dateFormat": "m/d/yyyy", + "timeFormat": "hh:mm:ss a", + "formulaArgSeparator": ",", + "weekStart": 7 + } + }, + "pivots": { + "1": { + "type": "ODOO", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "context": {}, + "domain": [], + "id": "1", + "measures": [ + { + "id": "mrr_change:sum", + "fieldName": "mrr_change", + "aggregator": "sum" + }, + { + "id": "__count", + "fieldName": "__count" + } + ], + "model": "sale.subscription.mrr.report", + "name": "KPIs 1", + "sortedColumn": null, + "formulaId": "1", + "columns": [], + "rows": [] + }, + "2": { + "type": "ODOO", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "context": {}, + "domain": [["event_type", "=", "new"]], + "id": "2", + "measures": [ + { + "id": "mrr_change:sum", + "fieldName": "mrr_change", + "aggregator": "sum" + } + ], + "model": "sale.subscription.mrr.report", + "name": "KPIs 2", + "sortedColumn": null, + "formulaId": "2", + "columns": [], + "rows": [] + }, + "3": { + "type": "ODOO", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "event_date", + "type": "datetime", + "offset": 0 + } + }, + "context": {}, + "domain": [["event_type", "=", "churn"]], + "id": "3", + "measures": [ + { + "id": "mrr_change:sum", + "fieldName": "mrr_change", + "aggregator": "sum" + } + ], + "model": "sale.subscription.mrr.report", + "name": "KPIs 3", + "sortedColumn": null, + "formulaId": "3", + "columns": [], + "rows": [] + } + }, + "pivotNextId": 4, + "customTableStyles": {}, + "globalFilters": [ + { + "id": "55555555-5555-5555-5555-555555555555", + "type": "date", + "label": "Period", + "defaultValue": "last_90_days" + }, + { + "id": "11111111-1111-1111-1111-111111111111", + "type": "relation", + "label": "Salesperson", + "defaultValueDisplayNames": [], + "modelName": "res.users" + }, + { + "id": "22222222-2222-2222-2222-222222222222", + "type": "relation", + "label": "Sales Team", + "defaultValueDisplayNames": [], + "modelName": "crm.team" + }, + { + "id": "33333333-3333-3333-3333-333333333333", + "type": "relation", + "label": "Customer", + "defaultValueDisplayNames": [], + "modelName": "res.partner" + }, + { + "id": "44444444-4444-4444-4444-444444444444", + "type": "relation", + "label": "Template", + "defaultValueDisplayNames": [], + "modelName": "sale.subscription.template" + } + ], + "lists": {}, + "listNextId": 1, + "chartOdooMenusReferences": { + "cccccccc-0000-0000-0000-000000000001": "subscription_oca.sale_subscription_menu", + "cccccccc-0000-0000-0000-000000000002": "subscription_oca.sale_subscription_menu", + "cccccccc-0000-0000-0000-000000000003": "subscription_oca.sale_subscription_menu" + } +} diff --git a/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json b/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json new file mode 100644 index 00000000..20676439 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json @@ -0,0 +1,528 @@ +{ + "version": "18.5.10", + "sheets": [ + { + "id": "dashboard", + "name": "Dashboard", + "colNumber": 22, + "rowNumber": 80, + "rows": {}, + "cols": { + "0": { + "size": 50 + }, + "1": { + "size": 50 + }, + "2": { + "size": 50 + }, + "3": { + "size": 50 + }, + "4": { + "size": 50 + }, + "5": { + "size": 50 + }, + "6": { + "size": 50 + }, + "7": { + "size": 50 + }, + "8": { + "size": 50 + }, + "9": { + "size": 50 + }, + "10": { + "size": 50 + }, + "11": { + "size": 50 + }, + "12": { + "size": 50 + }, + "13": { + "size": 50 + }, + "14": { + "size": 50 + }, + "15": { + "size": 50 + }, + "16": { + "size": 50 + }, + "17": { + "size": 50 + }, + "18": { + "size": 50 + }, + "19": { + "size": 50 + }, + "20": { + "size": 50 + }, + "21": { + "size": 50 + } + }, + "merges": [], + "cells": {}, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [ + { + "id": "dddddddd-0000-0000-0000-000000000001", + "width": 526, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Subscriptions (cohorts)", + "color": "#1f2937", + "bold": true + }, + "background": "#EFF6FF", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C1", + "chartId": "dddddddd-0000-0000-0000-000000000001" + }, + "offset": { + "x": 16, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "dddddddd-0000-0000-0000-000000000002", + "width": 526, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "MRR at Start", + "color": "#1f2937", + "bold": true + }, + "background": "#FFF7ED", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C2", + "chartId": "dddddddd-0000-0000-0000-000000000002" + }, + "offset": { + "x": 558, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "dddddddd-0000-0000-0000-000000000010", + "width": 1068, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Retention Curve (active subscriptions by month since start)" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["period_index"], + "measure": "__count", + "order": null, + "resModel": "sale.subscription.retention.report", + "mode": "line" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [], + "groupBy": ["period_index"], + "orderBy": [] + }, + "type": "odoo_line", + "dataSets": [{}], + "chartId": "dddddddd-0000-0000-0000-000000000010", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_retention_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "cohort_date", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 16, + "y": 172 + }, + "col": 0, + "row": 0 + }, + { + "id": "dddddddd-0000-0000-0000-000000000011", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Subscriptions by Cohort (start month)" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["cohort_date:month"], + "measure": "__count", + "order": null, + "resModel": "sale.subscription.retention.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["period_index", "=", 0]], + "groupBy": ["cohort_date:month"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "dddddddd-0000-0000-0000-000000000011", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_retention_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "cohort_date", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 16, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "dddddddd-0000-0000-0000-000000000012", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Cohort (start month)" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["cohort_date:month"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.retention.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["period_index", "=", 0]], + "groupBy": ["cohort_date:month"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "dddddddd-0000-0000-0000-000000000012", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_retention_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "cohort_date", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 558, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "dddddddd-0000-0000-0000-000000000013", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Cohort MRR by Template" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["template_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.retention.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["period_index", "=", 0]], + "groupBy": ["template_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "dddddddd-0000-0000-0000-000000000013", + "actionXmlId": "spreadsheet_dashboard_subscription_oca.action_sale_subscription_retention_report", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "cohort_date", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 16, + "y": 932 + }, + "col": 0, + "row": 0 + } + ], + "tables": [], + "areGridLinesVisible": false, + "isVisible": true, + "headerGroups": [], + "comments": {} + }, + { + "id": "data", + "name": "Data", + "colNumber": 8, + "rowNumber": 30, + "rows": {}, + "cols": {}, + "merges": [], + "cells": { + "A1": "=_t(\"Retention KPIs\")", + "B1": "=PIVOT.VALUE(1,\"__count\")", + "B2": "=PIVOT.VALUE(1,\"recurring_monthly:sum\")", + "C1": "=IFERROR(FORMAT.LARGE.NUMBER(B1))", + "C2": "=IFERROR(FORMAT.LARGE.NUMBER(B2))" + }, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [], + "tables": [], + "areGridLinesVisible": true, + "isVisible": false, + "headerGroups": [], + "comments": {} + } + ], + "styles": {}, + "formats": {}, + "borders": {}, + "revisionId": "START_REVISION", + "uniqueFigureIds": true, + "settings": { + "locale": { + "name": "English (US)", + "code": "en_US", + "thousandsSeparator": ",", + "decimalSeparator": ".", + "dateFormat": "m/d/yyyy", + "timeFormat": "hh:mm:ss a", + "formulaArgSeparator": ",", + "weekStart": 7 + } + }, + "pivots": { + "1": { + "type": "ODOO", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "cohort_date", + "type": "datetime", + "offset": 0 + } + }, + "context": {}, + "domain": [["period_index", "=", 0]], + "id": "1", + "measures": [ + { + "id": "recurring_monthly:sum", + "fieldName": "recurring_monthly", + "aggregator": "sum" + }, + { + "id": "__count", + "fieldName": "__count" + } + ], + "model": "sale.subscription.retention.report", + "name": "KPIs 1", + "sortedColumn": null, + "formulaId": "1", + "columns": [], + "rows": [] + } + }, + "pivotNextId": 2, + "customTableStyles": {}, + "globalFilters": [ + { + "id": "55555555-5555-5555-5555-555555555555", + "type": "date", + "label": "Period", + "defaultValue": "last_90_days" + }, + { + "id": "11111111-1111-1111-1111-111111111111", + "type": "relation", + "label": "Salesperson", + "defaultValueDisplayNames": [], + "modelName": "res.users" + }, + { + "id": "22222222-2222-2222-2222-222222222222", + "type": "relation", + "label": "Sales Team", + "defaultValueDisplayNames": [], + "modelName": "crm.team" + }, + { + "id": "33333333-3333-3333-3333-333333333333", + "type": "relation", + "label": "Customer", + "defaultValueDisplayNames": [], + "modelName": "res.partner" + }, + { + "id": "44444444-4444-4444-4444-444444444444", + "type": "relation", + "label": "Template", + "defaultValueDisplayNames": [], + "modelName": "sale.subscription.template" + } + ], + "lists": {}, + "listNextId": 1, + "chartOdooMenusReferences": { + "dddddddd-0000-0000-0000-000000000001": "subscription_oca.sale_subscription_menu", + "dddddddd-0000-0000-0000-000000000002": "subscription_oca.sale_subscription_menu" + } +} diff --git a/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json b/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json new file mode 100644 index 00000000..01670c5a --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json @@ -0,0 +1,691 @@ +{ + "version": "18.5.10", + "sheets": [ + { + "id": "dashboard", + "name": "Dashboard", + "colNumber": 22, + "rowNumber": 80, + "rows": {}, + "cols": { + "0": { + "size": 50 + }, + "1": { + "size": 50 + }, + "2": { + "size": 50 + }, + "3": { + "size": 50 + }, + "4": { + "size": 50 + }, + "5": { + "size": 50 + }, + "6": { + "size": 50 + }, + "7": { + "size": 50 + }, + "8": { + "size": 50 + }, + "9": { + "size": 50 + }, + "10": { + "size": 50 + }, + "11": { + "size": 50 + }, + "12": { + "size": 50 + }, + "13": { + "size": 50 + }, + "14": { + "size": 50 + }, + "15": { + "size": 50 + }, + "16": { + "size": 50 + }, + "17": { + "size": 50 + }, + "18": { + "size": 50 + }, + "19": { + "size": 50 + }, + "20": { + "size": 50 + }, + "21": { + "size": 50 + } + }, + "merges": [], + "cells": {}, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [ + { + "id": "bbbbbbbb-0000-0000-0000-000000000001", + "width": 345, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Monthly Recurring Revenue", + "color": "#1f2937", + "bold": true + }, + "background": "#FFF7ED", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "Data!C2", + "humanize": false, + "keyValue": "Data!C1", + "chartId": "bbbbbbbb-0000-0000-0000-000000000001", + "baselineDescr": { + "text": "ARR" + } + }, + "offset": { + "x": 16, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000002", + "width": 345, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Active Subscriptions", + "color": "#1f2937", + "bold": true + }, + "background": "#F0FDF4", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C3", + "chartId": "bbbbbbbb-0000-0000-0000-000000000002" + }, + "offset": { + "x": 377, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000003", + "width": 345, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Avg MRR / Subscription", + "color": "#1f2937", + "bold": true + }, + "background": "#FAF5FF", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C4", + "chartId": "bbbbbbbb-0000-0000-0000-000000000003" + }, + "offset": { + "x": 738, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000010", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Salesperson" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["user_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["user_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "bbbbbbbb-0000-0000-0000-000000000010", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 16, + "y": 172 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000011", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR share by Salesperson" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["user_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["user_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "bbbbbbbb-0000-0000-0000-000000000011", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 558, + "y": 172 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000012", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Subscriptions by Salesperson" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["user_id"], + "measure": "__count", + "order": null, + "resModel": "sale.subscription.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["user_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "bbbbbbbb-0000-0000-0000-000000000012", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 16, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000013", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Sales Team" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["crm_team_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["crm_team_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "bbbbbbbb-0000-0000-0000-000000000013", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 558, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000014", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Subscriptions by Sales Team" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["crm_team_id"], + "measure": "__count", + "order": null, + "resModel": "sale.subscription.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["crm_team_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "bbbbbbbb-0000-0000-0000-000000000014", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 16, + "y": 932 + }, + "col": 0, + "row": 0 + }, + { + "id": "bbbbbbbb-0000-0000-0000-000000000015", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Salesperson & Template" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["user_id", "template_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["user_id", "template_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "bbbbbbbb-0000-0000-0000-000000000015", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "stacked": true + }, + "offset": { + "x": 558, + "y": 932 + }, + "col": 0, + "row": 0 + } + ], + "tables": [], + "areGridLinesVisible": false, + "isVisible": true, + "headerGroups": [], + "comments": {} + }, + { + "id": "data", + "name": "Data", + "colNumber": 8, + "rowNumber": 30, + "rows": {}, + "cols": {}, + "merges": [], + "cells": { + "A1": "=_t(\"Salesperson KPIs\")", + "B1": "=PIVOT.VALUE(1,\"recurring_monthly:sum\")", + "B2": "=PIVOT.VALUE(1,\"recurring_yearly:sum\")", + "B3": "=PIVOT.VALUE(1,\"__count\")", + "B4": "=IFERROR(B1/B3,0)", + "C1": "=IFERROR(FORMAT.LARGE.NUMBER(B1))", + "C2": "=IFERROR(FORMAT.LARGE.NUMBER(B2))", + "C3": "=IFERROR(FORMAT.LARGE.NUMBER(B3))", + "C4": "=IFERROR(FORMAT.LARGE.NUMBER(B4))" + }, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [], + "tables": [], + "areGridLinesVisible": true, + "isVisible": false, + "headerGroups": [], + "comments": {} + } + ], + "styles": {}, + "formats": {}, + "borders": {}, + "revisionId": "START_REVISION", + "uniqueFigureIds": true, + "settings": { + "locale": { + "name": "English (US)", + "code": "en_US", + "thousandsSeparator": ",", + "decimalSeparator": ".", + "dateFormat": "m/d/yyyy", + "timeFormat": "hh:mm:ss a", + "formulaArgSeparator": ",", + "weekStart": 7 + } + }, + "pivots": { + "1": { + "type": "ODOO", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "context": {}, + "domain": [["in_progress", "=", true]], + "id": "1", + "measures": [ + { + "id": "recurring_monthly:sum", + "fieldName": "recurring_monthly", + "aggregator": "sum" + }, + { + "id": "recurring_yearly:sum", + "fieldName": "recurring_yearly", + "aggregator": "sum" + }, + { + "id": "__count", + "fieldName": "__count" + } + ], + "model": "sale.subscription.report", + "name": "KPIs 1", + "sortedColumn": null, + "formulaId": "1", + "columns": [], + "rows": [] + } + }, + "pivotNextId": 2, + "customTableStyles": {}, + "globalFilters": [ + { + "id": "55555555-5555-5555-5555-555555555555", + "type": "date", + "label": "Period", + "defaultValue": "last_90_days" + }, + { + "id": "11111111-1111-1111-1111-111111111111", + "type": "relation", + "label": "Salesperson", + "defaultValueDisplayNames": [], + "modelName": "res.users" + }, + { + "id": "22222222-2222-2222-2222-222222222222", + "type": "relation", + "label": "Sales Team", + "defaultValueDisplayNames": [], + "modelName": "crm.team" + }, + { + "id": "33333333-3333-3333-3333-333333333333", + "type": "relation", + "label": "Customer", + "defaultValueDisplayNames": [], + "modelName": "res.partner" + }, + { + "id": "44444444-4444-4444-4444-444444444444", + "type": "relation", + "label": "Template", + "defaultValueDisplayNames": [], + "modelName": "sale.subscription.template" + } + ], + "lists": {}, + "listNextId": 1, + "chartOdooMenusReferences": { + "bbbbbbbb-0000-0000-0000-000000000001": "subscription_oca.sale_subscription_menu", + "bbbbbbbb-0000-0000-0000-000000000002": "subscription_oca.sale_subscription_menu", + "bbbbbbbb-0000-0000-0000-000000000003": "subscription_oca.sale_subscription_menu" + } +} diff --git a/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json b/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json new file mode 100644 index 00000000..534b5415 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json @@ -0,0 +1,718 @@ +{ + "version": "18.5.10", + "sheets": [ + { + "id": "dashboard", + "name": "Dashboard", + "colNumber": 22, + "rowNumber": 80, + "rows": {}, + "cols": { + "0": { + "size": 50 + }, + "1": { + "size": 50 + }, + "2": { + "size": 50 + }, + "3": { + "size": 50 + }, + "4": { + "size": 50 + }, + "5": { + "size": 50 + }, + "6": { + "size": 50 + }, + "7": { + "size": 50 + }, + "8": { + "size": 50 + }, + "9": { + "size": 50 + }, + "10": { + "size": 50 + }, + "11": { + "size": 50 + }, + "12": { + "size": 50 + }, + "13": { + "size": 50 + }, + "14": { + "size": 50 + }, + "15": { + "size": 50 + }, + "16": { + "size": 50 + }, + "17": { + "size": 50 + }, + "18": { + "size": 50 + }, + "19": { + "size": 50 + }, + "20": { + "size": 50 + }, + "21": { + "size": 50 + } + }, + "merges": [], + "cells": {}, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [ + { + "id": "aaaaaaaa-0000-0000-0000-000000000001", + "width": 255, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Monthly Recurring Revenue", + "color": "#1f2937", + "bold": true + }, + "background": "#FFF7ED", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "Data!C2", + "humanize": false, + "keyValue": "Data!C1", + "chartId": "aaaaaaaa-0000-0000-0000-000000000001", + "baselineDescr": { + "text": "ARR" + } + }, + "offset": { + "x": 16, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000002", + "width": 255, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Annual Recurring Revenue", + "color": "#1f2937", + "bold": true + }, + "background": "#EFF6FF", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C2", + "chartId": "aaaaaaaa-0000-0000-0000-000000000002" + }, + "offset": { + "x": 287, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000003", + "width": 255, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Active Subscriptions", + "color": "#1f2937", + "bold": true + }, + "background": "#F0FDF4", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C3", + "chartId": "aaaaaaaa-0000-0000-0000-000000000003" + }, + "offset": { + "x": 558, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000004", + "width": 255, + "height": 132, + "tag": "chart", + "data": { + "type": "scorecard", + "title": { + "text": "Avg MRR / Subscription", + "color": "#1f2937", + "bold": true + }, + "background": "#FAF5FF", + "baselineColorUp": "#00A04A", + "baselineColorDown": "#DC6965", + "baselineMode": "text", + "baseline": "", + "humanize": false, + "keyValue": "Data!C4", + "chartId": "aaaaaaaa-0000-0000-0000-000000000004" + }, + "offset": { + "x": 829, + "y": 16 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000010", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Template" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["template_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["template_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "aaaaaaaa-0000-0000-0000-000000000010", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 16, + "y": 172 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000011", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Start Month" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["date_start:month"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "line" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["date_start:month"], + "orderBy": [] + }, + "type": "odoo_line", + "dataSets": [{}], + "chartId": "aaaaaaaa-0000-0000-0000-000000000011", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 558, + "y": 172 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000012", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Product Category" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["categ_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["categ_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "aaaaaaaa-0000-0000-0000-000000000012", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 16, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000013", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Sales Team" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["crm_team_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["crm_team_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "aaaaaaaa-0000-0000-0000-000000000013", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 558, + "y": 552 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000014", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "MRR by Salesperson" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["user_id"], + "measure": "recurring_monthly", + "order": null, + "resModel": "sale.subscription.report", + "mode": "pie" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["user_id"], + "orderBy": [] + }, + "type": "odoo_pie", + "dataSets": [{}], + "chartId": "aaaaaaaa-0000-0000-0000-000000000014", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + } + }, + "offset": { + "x": 16, + "y": 932 + }, + "col": 0, + "row": 0 + }, + { + "id": "aaaaaaaa-0000-0000-0000-000000000015", + "width": 526, + "height": 360, + "tag": "chart", + "data": { + "title": { + "text": "Subscriptions by Stage" + }, + "background": "#FFFFFF", + "legendPosition": "top", + "metaData": { + "groupBy": ["stage_id"], + "measure": "__count", + "order": null, + "resModel": "sale.subscription.report", + "mode": "bar" + }, + "searchParams": { + "comparison": null, + "context": {}, + "domain": [["in_progress", "=", true]], + "groupBy": ["stage_id"], + "orderBy": [] + }, + "type": "odoo_bar", + "dataSets": [{}], + "chartId": "aaaaaaaa-0000-0000-0000-000000000015", + "actionXmlId": "subscription_oca.sale_subscription_report_action", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "stacked": false + }, + "offset": { + "x": 558, + "y": 932 + }, + "col": 0, + "row": 0 + } + ], + "tables": [], + "areGridLinesVisible": false, + "isVisible": true, + "headerGroups": [], + "comments": {} + }, + { + "id": "data", + "name": "Data", + "colNumber": 8, + "rowNumber": 30, + "rows": {}, + "cols": {}, + "merges": [], + "cells": { + "A1": "=_t(\"Subscription KPIs\")", + "B1": "=PIVOT.VALUE(1,\"recurring_monthly:sum\")", + "B2": "=PIVOT.VALUE(1,\"recurring_yearly:sum\")", + "B3": "=PIVOT.VALUE(1,\"__count\")", + "B4": "=IFERROR(B1/B3,0)", + "C1": "=IFERROR(FORMAT.LARGE.NUMBER(B1))", + "C2": "=IFERROR(FORMAT.LARGE.NUMBER(B2))", + "C3": "=IFERROR(FORMAT.LARGE.NUMBER(B3))", + "C4": "=IFERROR(FORMAT.LARGE.NUMBER(B4))" + }, + "styles": {}, + "formats": {}, + "borders": {}, + "conditionalFormats": [], + "dataValidationRules": [], + "figures": [], + "tables": [], + "areGridLinesVisible": true, + "isVisible": false, + "headerGroups": [], + "comments": {} + } + ], + "styles": {}, + "formats": {}, + "borders": {}, + "revisionId": "START_REVISION", + "uniqueFigureIds": true, + "settings": { + "locale": { + "name": "English (US)", + "code": "en_US", + "thousandsSeparator": ",", + "decimalSeparator": ".", + "dateFormat": "m/d/yyyy", + "timeFormat": "hh:mm:ss a", + "formulaArgSeparator": ",", + "weekStart": 7 + } + }, + "pivots": { + "1": { + "type": "ODOO", + "fieldMatching": { + "11111111-1111-1111-1111-111111111111": { + "chain": "user_id", + "type": "many2one" + }, + "22222222-2222-2222-2222-222222222222": { + "chain": "crm_team_id", + "type": "many2one" + }, + "33333333-3333-3333-3333-333333333333": { + "chain": "partner_id", + "type": "many2one" + }, + "44444444-4444-4444-4444-444444444444": { + "chain": "template_id", + "type": "many2one" + }, + "55555555-5555-5555-5555-555555555555": { + "chain": "date_start", + "type": "datetime", + "offset": 0 + } + }, + "context": {}, + "domain": [["in_progress", "=", true]], + "id": "1", + "measures": [ + { + "id": "recurring_monthly:sum", + "fieldName": "recurring_monthly", + "aggregator": "sum" + }, + { + "id": "recurring_yearly:sum", + "fieldName": "recurring_yearly", + "aggregator": "sum" + }, + { + "id": "__count", + "fieldName": "__count" + } + ], + "model": "sale.subscription.report", + "name": "KPIs 1", + "sortedColumn": null, + "formulaId": "1", + "columns": [], + "rows": [] + } + }, + "pivotNextId": 2, + "customTableStyles": {}, + "globalFilters": [ + { + "id": "55555555-5555-5555-5555-555555555555", + "type": "date", + "label": "Period", + "defaultValue": "last_90_days" + }, + { + "id": "11111111-1111-1111-1111-111111111111", + "type": "relation", + "label": "Salesperson", + "defaultValueDisplayNames": [], + "modelName": "res.users" + }, + { + "id": "22222222-2222-2222-2222-222222222222", + "type": "relation", + "label": "Sales Team", + "defaultValueDisplayNames": [], + "modelName": "crm.team" + }, + { + "id": "33333333-3333-3333-3333-333333333333", + "type": "relation", + "label": "Customer", + "defaultValueDisplayNames": [], + "modelName": "res.partner" + }, + { + "id": "44444444-4444-4444-4444-444444444444", + "type": "relation", + "label": "Template", + "defaultValueDisplayNames": [], + "modelName": "sale.subscription.template" + } + ], + "lists": {}, + "listNextId": 1, + "chartOdooMenusReferences": { + "aaaaaaaa-0000-0000-0000-000000000001": "subscription_oca.sale_subscription_menu", + "aaaaaaaa-0000-0000-0000-000000000002": "subscription_oca.sale_subscription_menu", + "aaaaaaaa-0000-0000-0000-000000000003": "subscription_oca.sale_subscription_menu", + "aaaaaaaa-0000-0000-0000-000000000004": "subscription_oca.sale_subscription_menu" + } +} diff --git a/spreadsheet_dashboard_subscription_oca/data/spreadsheet_dashboards.xml b/spreadsheet_dashboard_subscription_oca/data/spreadsheet_dashboards.xml new file mode 100644 index 00000000..4bad0df6 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/data/spreadsheet_dashboards.xml @@ -0,0 +1,114 @@ + + + + Subscriptions + 150 + + + + Subscriptions + + + + + 10 + True + + + + Salesperson + + + + + 20 + True + + + + MRR Evolution + + + + + 30 + True + + + + Retention + + + + + 40 + True + + diff --git a/spreadsheet_dashboard_subscription_oca/i18n/es.po b/spreadsheet_dashboard_subscription_oca/i18n/es.po new file mode 100644 index 00000000..7fc246f4 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/i18n/es.po @@ -0,0 +1,429 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * spreadsheet_dashboard_subscription_oca +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 19.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2026-06-22 17:34+0000\n" +"PO-Revision-Date: 2026-06-22 17:34+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "ARR" +msgstr "ARR" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Active Subscriptions" +msgstr "Suscripciones activas" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Annual Recurring Revenue" +msgstr "Ingresos recurrentes anuales" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Avg MRR / Subscription" +msgstr "MRR medio / suscripción" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields.selection,name:spreadsheet_dashboard_subscription_oca.selection__sale_subscription_mrr_report__event_type__churn +msgid "Churn" +msgstr "Baja" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "Churned MRR (all time)" +msgstr "MRR perdido (histórico)" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__cohort_date +msgid "Cohort (start month)" +msgstr "Cohorte (mes de inicio)" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "Cohort MRR by Template" +msgstr "MRR de cohorte por plantilla" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__user_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__user_id +msgid "Commercial agent" +msgstr "Comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__company_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__company_id +msgid "Company" +msgstr "Compañía" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__company_currency_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__company_currency_id +msgid "Company Currency" +msgstr "Divisa de la compañía" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__partner_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__partner_id +msgid "Customer" +msgstr "Cliente" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__display_name +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__event_date +msgid "Event date" +msgstr "Fecha del evento" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__event_type +msgid "Event type" +msgstr "Tipo de evento" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__id +msgid "ID" +msgstr "ID" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "MRR Change by Month & Type" +msgstr "Variación de MRR por mes y tipo" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "MRR Change by Type" +msgstr "Variación de MRR por tipo" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:spreadsheet.dashboard,name:spreadsheet_dashboard_subscription_oca.spreadsheet_dashboard_subscription_oca_mrr_evolution +msgid "MRR Evolution" +msgstr "Evolución del MRR" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "MRR KPIs" +msgstr "KPIs de MRR" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "MRR at Start" +msgstr "MRR inicial" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "MRR by Cohort (start month)" +msgstr "MRR por cohorte (mes de inicio)" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "MRR by Product Category" +msgstr "MRR por categoría de producto" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "MRR by Sales Team" +msgstr "MRR por equipo de ventas" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "MRR by Salesperson" +msgstr "MRR por comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +msgid "MRR by Salesperson & Template" +msgstr "MRR por comercial y plantilla" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "MRR by Start Month" +msgstr "MRR por mes de inicio" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "MRR by Template" +msgstr "MRR por plantilla" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__mrr_change +msgid "MRR change" +msgstr "Variación de MRR" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +msgid "MRR share by Salesperson" +msgstr "Reparto de MRR por comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Monthly Recurring Revenue" +msgstr "Ingresos recurrentes mensuales" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__recurring_monthly +msgid "Monthly recurring revenue" +msgstr "Ingresos recurrentes mensuales" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__period_index +msgid "Months since start" +msgstr "Meses desde el inicio" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "Net MRR" +msgstr "MRR neto" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "Net MRR Over Time" +msgstr "MRR neto a lo largo del tiempo" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields.selection,name:spreadsheet_dashboard_subscription_oca.selection__sale_subscription_mrr_report__event_type__new +msgid "New" +msgstr "Alta" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "New MRR (all time)" +msgstr "MRR nuevo (histórico)" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "New MRR by Salesperson" +msgstr "MRR nuevo por comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +msgid "New MRR by Template" +msgstr "MRR nuevo por plantilla" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:spreadsheet.dashboard,name:spreadsheet_dashboard_subscription_oca.spreadsheet_dashboard_subscription_oca_retention +msgid "Retention" +msgstr "Retención" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "Retention Curve (active subscriptions by month since start)" +msgstr "Curva de retención (suscripciones activas por mes desde el inicio)" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "Retention KPIs" +msgstr "KPIs de retención" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__crm_team_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__crm_team_id +msgid "Sale team" +msgstr "Equipo de ventas" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Sales Team" +msgstr "Equipo de ventas" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: model:spreadsheet.dashboard,name:spreadsheet_dashboard_subscription_oca.spreadsheet_dashboard_subscription_oca_salesperson +msgid "Salesperson" +msgstr "Comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +msgid "Salesperson KPIs" +msgstr "KPIs de comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__subscription_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__subscription_id +msgid "Subscription" +msgstr "Suscripción" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Subscription KPIs" +msgstr "KPIs de suscripciones" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model,name:spreadsheet_dashboard_subscription_oca.model_sale_subscription_mrr_report +msgid "Subscription MRR Evolution" +msgstr "Evolución del MRR de suscripciones" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model,name:spreadsheet_dashboard_subscription_oca.model_sale_subscription_retention_report +msgid "Subscription Retention" +msgstr "Retención de suscripciones" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_mrr_report__template_id +#: model:ir.model.fields,field_description:spreadsheet_dashboard_subscription_oca.field_sale_subscription_retention_report__template_id +msgid "Subscription template" +msgstr "Plantilla de suscripción" + +#. module: spreadsheet_dashboard_subscription_oca +#: model:spreadsheet.dashboard,name:spreadsheet_dashboard_subscription_oca.spreadsheet_dashboard_subscription_oca_subscriptions +#: model:spreadsheet.dashboard.group,name:spreadsheet_dashboard_subscription_oca.spreadsheet_dashboard_group_subscription_oca +msgid "Subscriptions" +msgstr "Suscripciones" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "Subscriptions (cohorts)" +msgstr "Suscripciones (cohortes)" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +msgid "Subscriptions by Cohort (start month)" +msgstr "Suscripciones por cohorte (mes de inicio)" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +msgid "Subscriptions by Sales Team" +msgstr "Suscripciones por equipo de ventas" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +msgid "Subscriptions by Salesperson" +msgstr "Suscripciones por comercial" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Subscriptions by Stage" +msgstr "Suscripciones por etapa" + +#. module: spreadsheet_dashboard_subscription_oca +#. odoo-javascript +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/Domatix/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/mrr_evolution_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/retention_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/salesperson_dashboard.osheet.json:0 +#: code:addons/spreadsheet_dashboard_subscription_oca/data/files/subscriptions_dashboard.osheet.json:0 +msgid "Template" +msgstr "Plantilla" diff --git a/spreadsheet_dashboard_subscription_oca/models/__init__.py b/spreadsheet_dashboard_subscription_oca/models/__init__.py new file mode 100644 index 00000000..115ccbd7 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/models/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2026 Domatix - Alvaro Domatix +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import sale_subscription_mrr_report +from . import sale_subscription_retention_report diff --git a/spreadsheet_dashboard_subscription_oca/models/sale_subscription_mrr_report.py b/spreadsheet_dashboard_subscription_oca/models/sale_subscription_mrr_report.py new file mode 100644 index 00000000..39103a2e --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/models/sale_subscription_mrr_report.py @@ -0,0 +1,91 @@ +# Copyright 2026 Domatix - Alvaro Domatix +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models, tools + + +class SaleSubscriptionMrrReport(models.Model): + """MRR change events derived from the current state of the subscriptions. + + There is no stored MRR event log in ``subscription_oca``. This SQL view + reconstructs an approximate one from what we do have: a positive ``new`` + event at the start date of every subscription and a negative ``churn`` + event at the closing date of the closed ones (the end date when set, + otherwise the last write date as a fallback). Cumulating ``mrr_change`` + over time therefore yields the net active MRR. Mid-life expansion and + contraction are not tracked (that would require a real event log). + """ + + _name = "sale.subscription.mrr.report" + _description = "Subscription MRR Evolution" + _auto = False + _rec_name = "subscription_id" + _order = "event_date desc" + + subscription_id = fields.Many2one( + comodel_name="sale.subscription", string="Subscription", readonly=True + ) + partner_id = fields.Many2one( + comodel_name="res.partner", string="Customer", readonly=True + ) + template_id = fields.Many2one( + comodel_name="sale.subscription.template", + string="Subscription template", + readonly=True, + ) + user_id = fields.Many2one( + comodel_name="res.users", string="Commercial agent", readonly=True + ) + crm_team_id = fields.Many2one( + comodel_name="crm.team", string="Sale team", readonly=True + ) + company_id = fields.Many2one( + comodel_name="res.company", string="Company", readonly=True + ) + company_currency_id = fields.Many2one( + comodel_name="res.currency", string="Company Currency", readonly=True + ) + event_date = fields.Date(string="Event date", readonly=True) + event_type = fields.Selection( + [("new", "New"), ("churn", "Churn")], + string="Event type", + readonly=True, + ) + mrr_change = fields.Monetary( + string="MRR change", + currency_field="company_currency_id", + readonly=True, + ) + + def _query(self): + return """ + SELECT + (sub.id * 2 + ev.n) AS id, + sub.id AS subscription_id, + sub.partner_id AS partner_id, + sub.template_id AS template_id, + sub.user_id AS user_id, + sub.crm_team_id AS crm_team_id, + sub.company_id AS company_id, + sub.company_currency_id AS company_currency_id, + ev.event_date AS event_date, + ev.event_type AS event_type, + ev.mrr_change AS mrr_change + FROM sale_subscription sub + LEFT JOIN sale_subscription_stage stage + ON stage.id = sub.stage_id + CROSS JOIN LATERAL ( + VALUES + (0, sub.date_start, 'new', sub.recurring_monthly), + (1, COALESCE(sub.date, sub.write_date::date), 'churn', + -sub.recurring_monthly) + ) AS ev(n, event_date, event_type, mrr_change) + WHERE sub.active = TRUE + AND ev.event_date IS NOT NULL + AND (ev.event_type = 'new' OR stage.type = 'post') + """ + + def init(self): + tools.drop_view_if_exists(self.env.cr, self._table) + self.env.cr.execute( + f"CREATE OR REPLACE VIEW {self._table} AS ({self._query()})" + ) diff --git a/spreadsheet_dashboard_subscription_oca/models/sale_subscription_retention_report.py b/spreadsheet_dashboard_subscription_oca/models/sale_subscription_retention_report.py new file mode 100644 index 00000000..90d19341 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/models/sale_subscription_retention_report.py @@ -0,0 +1,96 @@ +# Copyright 2026 Domatix - Alvaro Domatix +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models, tools + + +class SaleSubscriptionRetentionReport(models.Model): + """Retention cohorts derived from the current state of the subscriptions. + + Each subscription is expanded into one row per elapsed month between its + start date and either its closing date (for churned ones) or today (for + the ones still running). Grouping by ``cohort_date`` (the start month) and + ``period_index`` (months since the start) gives a retention/survival matrix + without needing a stored event log. + """ + + _name = "sale.subscription.retention.report" + _description = "Subscription Retention" + _auto = False + _rec_name = "subscription_id" + _order = "cohort_date desc, period_index" + + subscription_id = fields.Many2one( + comodel_name="sale.subscription", string="Subscription", readonly=True + ) + partner_id = fields.Many2one( + comodel_name="res.partner", string="Customer", readonly=True + ) + template_id = fields.Many2one( + comodel_name="sale.subscription.template", + string="Subscription template", + readonly=True, + ) + user_id = fields.Many2one( + comodel_name="res.users", string="Commercial agent", readonly=True + ) + crm_team_id = fields.Many2one( + comodel_name="crm.team", string="Sale team", readonly=True + ) + company_id = fields.Many2one( + comodel_name="res.company", string="Company", readonly=True + ) + company_currency_id = fields.Many2one( + comodel_name="res.currency", string="Company Currency", readonly=True + ) + cohort_date = fields.Date(string="Cohort (start month)", readonly=True) + period_index = fields.Integer(string="Months since start", readonly=True) + recurring_monthly = fields.Monetary( + string="Monthly recurring revenue", + currency_field="company_currency_id", + readonly=True, + ) + + def _query(self): + return """ + SELECT + (sub.id * 1000 + gs.idx) AS id, + sub.id AS subscription_id, + sub.partner_id AS partner_id, + sub.template_id AS template_id, + sub.user_id AS user_id, + sub.crm_team_id AS crm_team_id, + sub.company_id AS company_id, + sub.company_currency_id AS company_currency_id, + date_trunc('month', sub.date_start)::date AS cohort_date, + gs.idx AS period_index, + sub.recurring_monthly AS recurring_monthly + FROM sale_subscription sub + LEFT JOIN sale_subscription_stage stage + ON stage.id = sub.stage_id + CROSS JOIN LATERAL ( + SELECT CASE + WHEN stage.type = 'post' + THEN COALESCE(sub.date, sub.write_date::date) + ELSE CURRENT_DATE + END AS d + ) AS ref + CROSS JOIN LATERAL generate_series( + 0, + LEAST( + GREATEST(0, ( + EXTRACT(YEAR FROM age(ref.d, sub.date_start)) * 12 + + EXTRACT(MONTH FROM age(ref.d, sub.date_start)) + )::int), + 60 + ) + ) AS gs(idx) + WHERE sub.active = TRUE + AND sub.date_start IS NOT NULL + AND sub.date_start <= CURRENT_DATE + """ + + def init(self): + tools.drop_view_if_exists(self.env.cr, self._table) + self.env.cr.execute( + f"CREATE OR REPLACE VIEW {self._table} AS ({self._query()})" + ) diff --git a/spreadsheet_dashboard_subscription_oca/pyproject.toml b/spreadsheet_dashboard_subscription_oca/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/spreadsheet_dashboard_subscription_oca/readme/DESCRIPTION.md b/spreadsheet_dashboard_subscription_oca/readme/DESCRIPTION.md new file mode 100644 index 00000000..3dd1d979 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/readme/DESCRIPTION.md @@ -0,0 +1,22 @@ +This module adds spreadsheet dashboards for subscriptions, built on top of the +community ``spreadsheet_dashboard`` engine and the analysis models provided by +``subscription_oca``. No enterprise dependency is required. + +It ships four ready-to-use dashboards under the **Dashboards** application, in a +dedicated *Subscriptions* group: + +* **Subscriptions**: monthly/annual recurring revenue, active subscriptions and + average MRR, with breakdowns by template, product category, sales team, + salesperson, start month and stage. +* **Salesperson**: recurring revenue and number of subscriptions broken down by + salesperson and sales team. +* **MRR Evolution**: net/new/churned MRR and the cumulated MRR over time, with a + monthly new-vs-churn breakdown. MRR change events are derived from the current + state of the subscriptions (a positive event at the start date and a negative + one at the closing date); mid-life expansion/contraction is not tracked, which + would require a dedicated MRR event log. +* **Retention**: cohort sizes and recurring revenue per start month, plus a + retention/survival curve built from the start and closing dates. + +All dashboards expose global filters (salesperson, sales team, customer, +template) and refresh automatically from the subscription analysis models. diff --git a/spreadsheet_dashboard_subscription_oca/readme/USAGE.md b/spreadsheet_dashboard_subscription_oca/readme/USAGE.md new file mode 100644 index 00000000..b8746d15 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/readme/USAGE.md @@ -0,0 +1,6 @@ +Open the **Dashboards** application. The four dashboards are available in the +*Subscriptions* group. Use the filters at the top (salesperson, sales team, +customer, template) to narrow down the figures. The data is aggregated from the +``sale.subscription.report``, ``sale.subscription.mrr.report`` and +``sale.subscription.retention.report`` analysis models and refreshes +automatically. diff --git a/spreadsheet_dashboard_subscription_oca/report/sql_report_views.xml b/spreadsheet_dashboard_subscription_oca/report/sql_report_views.xml new file mode 100644 index 00000000..5be5f5b1 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/report/sql_report_views.xml @@ -0,0 +1,249 @@ + + + + + sale.subscription.mrr.report.search + sale.subscription.mrr.report + + + + + + + + + + + + + + + + + + + + + + + sale.subscription.mrr.report.graph + sale.subscription.mrr.report + + + + + + + + + + sale.subscription.mrr.report.pivot + sale.subscription.mrr.report + + + + + + + + + + + sale.subscription.mrr.report.list + sale.subscription.mrr.report + + + + + + + + + + + + + + + + + + MRR Evolution + sale.subscription.mrr.report + graph,pivot,list + + {"search_default_groupby_event_date": 1} + +

+ No MRR events yet +

+

+ Reconstruction of the monthly recurring revenue changes over + time: a "new" event when a subscription starts and a "churn" + event when one is closed. Cumulate it to see the net active MRR. +

+
+
+ + + + sale.subscription.retention.report.search + sale.subscription.retention.report + + + + + + + + + + + + + + + + + + + sale.subscription.retention.report.graph + sale.subscription.retention.report + + + + + + + + + + sale.subscription.retention.report.pivot + sale.subscription.retention.report + + + + + + + + + + + sale.subscription.retention.report.list + sale.subscription.retention.report + + + + + + + + + + + + + + + + + + Retention Analysis + sale.subscription.retention.report + pivot,graph,list + + {"search_default_groupby_cohort_date": 1} + +

+ No cohorts yet +

+

+ Retention cohorts built from the current subscriptions. Each + cohort groups the subscriptions that started the same month and + tracks the still-active recurring revenue over the following + months. +

+
+
+ + + + + +
diff --git a/spreadsheet_dashboard_subscription_oca/security/ir.model.access.csv b/spreadsheet_dashboard_subscription_oca/security/ir.model.access.csv new file mode 100644 index 00000000..1c9192e8 --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sale_subscription_mrr_report,sale.subscription.mrr.report,model_sale_subscription_mrr_report,sales_team.group_sale_salesman,1,0,0,0 +access_sale_subscription_retention_report,sale.subscription.retention.report,model_sale_subscription_retention_report,sales_team.group_sale_salesman,1,0,0,0 diff --git a/spreadsheet_dashboard_subscription_oca/static/description/index.html b/spreadsheet_dashboard_subscription_oca/static/description/index.html new file mode 100644 index 00000000..57e5f94c --- /dev/null +++ b/spreadsheet_dashboard_subscription_oca/static/description/index.html @@ -0,0 +1,457 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Subscription OCA Spreadsheet Dashboards

+ +

Beta License: AGPL-3 OCA/spreadsheet Translate me on Weblate Try me on Runboat

+

This module adds spreadsheet dashboards for subscriptions, built on top +of the community spreadsheet_dashboard engine and the analysis +models provided by subscription_oca. No enterprise dependency is +required.

+

It ships four ready-to-use dashboards under the Dashboards +application, in a dedicated Subscriptions group:

+
    +
  • Subscriptions: monthly/annual recurring revenue, active +subscriptions and average MRR, with breakdowns by template, product +category, sales team, salesperson, start month and stage.
  • +
  • Salesperson: recurring revenue and number of subscriptions broken +down by salesperson and sales team.
  • +
  • MRR Evolution: net/new/churned MRR and the cumulated MRR over +time, with a monthly new-vs-churn breakdown. MRR change events are +derived from the current state of the subscriptions (a positive event +at the start date and a negative one at the closing date); mid-life +expansion/contraction is not tracked, which would require a dedicated +MRR event log.
  • +
  • Retention: cohort sizes and recurring revenue per start month, +plus a retention/survival curve built from the start and closing +dates.
  • +
+

All dashboards expose global filters (salesperson, sales team, customer, +template) and refresh automatically from the subscription analysis +models.

+

Table of contents

+ +
+

Usage

+

Open the Dashboards application. The four dashboards are available +in the Subscriptions group. Use the filters at the top (salesperson, +sales team, customer, template) to narrow down the figures. The data is +aggregated from the sale.subscription.report, +sale.subscription.mrr.report and +sale.subscription.retention.report analysis models and refreshes +automatically.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Domatix
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/spreadsheet project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ +