From 826753d38da7e16acebc9c740bd5c9e0010b953d Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Wed, 3 Jun 2026 15:54:33 -0300 Subject: [PATCH 1/2] [ADD] mis_builder_bi_sql_editor: add new module --- mis_builder_bi_sql_editor/README.rst | 146 ++++++ mis_builder_bi_sql_editor/__init__.py | 1 + mis_builder_bi_sql_editor/__manifest__.py | 25 + .../data/mis_builder_bi_sql_line_cron.xml | 14 + mis_builder_bi_sql_editor/models/__init__.py | 4 + .../models/bi_sql_view.py | 111 ++++ .../models/mis_builder_bi_sql_line.py | 49 ++ .../models/mis_report.py | 28 + .../models/mis_report_instance.py | 46 ++ mis_builder_bi_sql_editor/pyproject.toml | 3 + .../readme/CONTRIBUTORS.md | 3 + .../readme/DESCRIPTION.md | 2 + mis_builder_bi_sql_editor/readme/USAGE.md | 49 ++ .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 4770 bytes .../static/description/index.html | 489 ++++++++++++++++++ mis_builder_bi_sql_editor/tests/__init__.py | 1 + .../tests/test_mis_builder_bi_sql_line.py | 29 ++ .../views/bi_sql_view.xml | 31 ++ .../views/mis_builder_bi_sql_line.xml | 42 ++ .../views/mis_report.xml | 19 + .../views/mis_report_instance.xml | 24 + 22 files changed, 1119 insertions(+) create mode 100644 mis_builder_bi_sql_editor/README.rst create mode 100644 mis_builder_bi_sql_editor/__init__.py create mode 100644 mis_builder_bi_sql_editor/__manifest__.py create mode 100644 mis_builder_bi_sql_editor/data/mis_builder_bi_sql_line_cron.xml create mode 100644 mis_builder_bi_sql_editor/models/__init__.py create mode 100644 mis_builder_bi_sql_editor/models/bi_sql_view.py create mode 100644 mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py create mode 100644 mis_builder_bi_sql_editor/models/mis_report.py create mode 100644 mis_builder_bi_sql_editor/models/mis_report_instance.py create mode 100644 mis_builder_bi_sql_editor/pyproject.toml create mode 100644 mis_builder_bi_sql_editor/readme/CONTRIBUTORS.md create mode 100644 mis_builder_bi_sql_editor/readme/DESCRIPTION.md create mode 100644 mis_builder_bi_sql_editor/readme/USAGE.md create mode 100644 mis_builder_bi_sql_editor/security/ir.model.access.csv create mode 100644 mis_builder_bi_sql_editor/static/description/icon.png create mode 100644 mis_builder_bi_sql_editor/static/description/index.html create mode 100644 mis_builder_bi_sql_editor/tests/__init__.py create mode 100644 mis_builder_bi_sql_editor/tests/test_mis_builder_bi_sql_line.py create mode 100644 mis_builder_bi_sql_editor/views/bi_sql_view.xml create mode 100644 mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml create mode 100644 mis_builder_bi_sql_editor/views/mis_report.xml create mode 100644 mis_builder_bi_sql_editor/views/mis_report_instance.xml diff --git a/mis_builder_bi_sql_editor/README.rst b/mis_builder_bi_sql_editor/README.rst new file mode 100644 index 0000000..24103d9 --- /dev/null +++ b/mis_builder_bi_sql_editor/README.rst @@ -0,0 +1,146 @@ +========================= +MIS Builder BI SQL Editor +========================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:41e107b1dbd1b78c2a4318f783b10b9e30119cb8d9ed1d515c4e2c1673ea8220 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-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%2Fmis--builder--contrib-lightgray.png?logo=github + :target: https://github.com/OCA/mis-builder-contrib/tree/18.0/mis_builder_bi_sql_editor + :alt: OCA/mis-builder-contrib +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/mis-builder-contrib-18-0/mis-builder-contrib-18-0-mis_builder_bi_sql_editor + :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/mis-builder-contrib&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module make the BI SQL Editor query models compatible with MIS +Builder. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +Create a query with SQL BI Editor: + +- Use the BI SQL Editor to create your query. +- Make sure your query includes the required fields: x_credit, x_debit, + x_account_id, x_date and x_company_id. +- Optionally, you can include the x_analytic_account_id field for + analytical account support. + +Field Requirements: + +- \`x_credit\`: Must have type float. +- \`x_debit\`: Must have type float. +- \`x_date\`: Must have the date type. +- \`x_account_id\`: Must have the type many2one and be associated with + the account.account model. +- \`x_company_id\`: Must have the type many2one and be associated with + the res.company model. +- x_analytic_account_id (optional): Must have the type many2one and be + associated with the account.analytic.account model. + +Activate MIS Builder in the query model: + +- Once your query meets the above requirements, click the “Activate MIS + Builder” button. +- This will signal that the query should be used in the "Refresh MIS + Builder BI SQL Lines" cron. +- Refreshing materialized view will also create new lines in the model + (if there are new lines). + +Remove MIS Builder in the query model: + +- If you no longer need MIS Builder compatibility, click the "Remove MIS + Builder" button. +- This will delete the rows and columns related to your BI SQL model. + +Create MIS Builder report: + +- When creating a MIS Builder Report, select "BI SQL MIS Builder Line" + as the source. +- Afterwards, select the BI SQL View you want to use (The view must have + MIS Builder activated). +- When creating kpis for this report, you can use MIS expressions to + filter the fields in your query. +- To do this, it is necessary to use the name of the BI SQL View. +- Example: bal[][('x_bi_sql_view_mis.x_name', '=', 'test')]. +- This will filter out the lines in your query that have the x_name + field with "test" as the value. + +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 +------- + +* Escodoo + +Contributors +------------ + +- `Escodoo `__: + + - Marcel Savegnago + - Wesley Oliveira + +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. + +.. |maintainer-WesleyOliveira98| image:: https://github.com/WesleyOliveira98.png?size=40px + :target: https://github.com/WesleyOliveira98 + :alt: WesleyOliveira98 + +Current `maintainer `__: + +|maintainer-WesleyOliveira98| + +This module is part of the `OCA/mis-builder-contrib `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mis_builder_bi_sql_editor/__init__.py b/mis_builder_bi_sql_editor/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/mis_builder_bi_sql_editor/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mis_builder_bi_sql_editor/__manifest__.py b/mis_builder_bi_sql_editor/__manifest__.py new file mode 100644 index 0000000..3b42e99 --- /dev/null +++ b/mis_builder_bi_sql_editor/__manifest__.py @@ -0,0 +1,25 @@ +# Copyright 2025 - TODAY, Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "MIS Builder BI SQL Editor", + "summary": """ + Integrate MIS Builder to BI SQL Editor""", + "version": "18.0.1.0.0", + "license": "AGPL-3", + "author": "Escodoo," "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/mis-builder-contrib", + "depends": ["mis_builder", "bi_sql_editor"], + "data": [ + "views/bi_sql_view.xml", + "views/mis_builder_bi_sql_line.xml", + "views/mis_report_instance.xml", + "views/mis_report.xml", + "security/ir.model.access.csv", + "data/mis_builder_bi_sql_line_cron.xml", + ], + "installable": True, + "application": True, + "development_status": "Alpha", + "maintainers": ["WesleyOliveira98"], +} diff --git a/mis_builder_bi_sql_editor/data/mis_builder_bi_sql_line_cron.xml b/mis_builder_bi_sql_editor/data/mis_builder_bi_sql_line_cron.xml new file mode 100644 index 0000000..814c1ef --- /dev/null +++ b/mis_builder_bi_sql_editor/data/mis_builder_bi_sql_line_cron.xml @@ -0,0 +1,14 @@ + + + + + Refresh MIS Builder BI SQL Lines + + code + model._create_mis_builder_bi_sql_lines() + + 1 + days + + diff --git a/mis_builder_bi_sql_editor/models/__init__.py b/mis_builder_bi_sql_editor/models/__init__.py new file mode 100644 index 0000000..c47ddd7 --- /dev/null +++ b/mis_builder_bi_sql_editor/models/__init__.py @@ -0,0 +1,4 @@ +from . import bi_sql_view +from . import mis_builder_bi_sql_line +from . import mis_report_instance +from . import mis_report diff --git a/mis_builder_bi_sql_editor/models/bi_sql_view.py b/mis_builder_bi_sql_editor/models/bi_sql_view.py new file mode 100644 index 0000000..75a48ad --- /dev/null +++ b/mis_builder_bi_sql_editor/models/bi_sql_view.py @@ -0,0 +1,111 @@ +# Copyright 2025 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class BiSQLView(models.Model): + + _inherit = "bi.sql.view" + + mis_builder_compatible = fields.Boolean( + compute="_compute_mis_builder_compatible", + default=False, + ) + mis_builder_activated = fields.Boolean(default=False) + + @api.depends() + def _compute_mis_builder_compatible(self): + compatible = True + model_sql_fields = self.bi_sql_view_field_ids + credit_field = model_sql_fields.filtered( + lambda x: x.name == "x_credit" and x.ttype == "float" + ) + debit_field = model_sql_fields.filtered( + lambda x: x.name == "x_debit" and x.ttype == "float" + ) + account_field = model_sql_fields.filtered( + lambda x: x.name == "x_account_id" and x.ttype == "many2one" + ) + date_field = model_sql_fields.filtered( + lambda x: x.name == "x_date" and x.ttype == "date" + ) + company_field = model_sql_fields.filtered( + lambda x: x.name == "x_company_id" and x.ttype == "many2one" + ) + analytic_account_field = model_sql_fields.filtered( + lambda x: x.name == "x_analytic_account_id" and x.ttype == "many2one" + ) + + if ( + not credit_field + or not debit_field + or not account_field + or account_field.many2one_model_id.model != "account.account" + or not date_field + or not company_field + or company_field.many2one_model_id.model != "res.company" + or ( + analytic_account_field + and analytic_account_field.many2one_model_id.model + != "account.analytic.account" + ) + ): + compatible = False + + self.mis_builder_compatible = compatible + + def activate_mis_builder(self): + if self.mis_builder_compatible: + model_id = ( + self.env["ir.model"] + .search([("model", "=", "mis.builder.bi.sql.line")]) + .id + ) + self.env["ir.model.fields"].create( + { + "name": self.view_name, + "model_id": model_id, + "state": "manual", + "ttype": "many2one", + "relation": self.model_name, + } + ) + self.mis_builder_activated = True + + def remove_mis_builder(self): + if self.mis_builder_compatible and self.mis_builder_activated: + self.env["mis.builder.bi.sql.line"].search( + [("bi_sql_model", "=", self.model_id.id)] + ).unlink() + + model_id = ( + self.env["ir.model"] + .search([("model", "=", "mis.builder.bi.sql.line")]) + .id + ) + self.env["ir.model.fields"].search( + [ + ("name", "=", self.view_name), + ("model_id", "=", model_id), + ] + ).unlink() + + self.mis_builder_activated = False + + def button_set_draft(self): + if self.mis_builder_activated: + self.remove_mis_builder() + return super().button_set_draft() + + def button_refresh_materialized_view(self): + super().button_refresh_materialized_view() + if self.mis_builder_activated: + model = self.env["mis.builder.bi.sql.line"] + model._create_mis_builder_bi_sql_lines() + + def copy(self, default=None): + self.ensure_one() + default = dict(default or {}) + default["mis_builder_activated"] = False + return super().copy(default) diff --git a/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py b/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py new file mode 100644 index 0000000..b3cf42d --- /dev/null +++ b/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py @@ -0,0 +1,49 @@ +# Copyright 2025 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class MisBuilderBiSqlLine(models.Model): + _name = "mis.builder.bi.sql.line" + _description = "MIS Builder BI SQL Line" + + credit = fields.Float() + debit = fields.Float() + account_id = fields.Many2one(comodel_name="account.account") + date = fields.Date() + company_id = fields.Many2one(comodel_name="res.company") + analytic_account_id = fields.Many2one(comodel_name="account.analytic.account") + bi_sql_model = fields.Many2one(comodel_name="ir.model") + res_id = fields.Integer() + + def _create_mis_builder_bi_sql_lines(self): + sql_view_ids = self.env["bi.sql.view"].search( + [ + ("mis_builder_compatible", "=", True), + ("mis_builder_activated", "=", True), + ] + ) + for sql_view in sql_view_ids: + res = self.env[sql_view.model_id.model].search([]) + for line in res: + mis_sql_line = self.env["mis.builder.bi.sql.line"].search( + [ + ("bi_sql_model", "=", sql_view.model_id.id), + ("res_id", "=", line.id), + ], + limit=1, + ) + if not mis_sql_line: + vals = { + "credit": line.x_credit, + "debit": line.x_debit, + "account_id": line.x_account_id.id, + "date": line.x_date, + "company_id": line.x_company_id.id, + "analytic_account_id": line.x_analytic_account_id.id or False, + "bi_sql_model": sql_view.model_id.id, + "res_id": line.id, + } + vals[sql_view.view_name] = line.id + self.create(vals) diff --git a/mis_builder_bi_sql_editor/models/mis_report.py b/mis_builder_bi_sql_editor/models/mis_report.py new file mode 100644 index 0000000..54974f8 --- /dev/null +++ b/mis_builder_bi_sql_editor/models/mis_report.py @@ -0,0 +1,28 @@ +# Copyright 2025 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class MisReport(models.Model): + + _inherit = "mis.report" + + bi_sql_view = fields.Many2one( + string="BI SQL View", + comodel_name="bi.sql.view", + domain=[("mis_builder_activated", "=", True)], + ) + bi_sql_view_required = fields.Boolean( + default=False, compute="_compute_bi_sql_view_required" + ) + + @api.depends("move_lines_source") + def _compute_bi_sql_view_required(self): + for record in self: + model_id = ( + self.env["ir.model"] + .search([("model", "=", "mis.builder.bi.sql.line")]) + .id + ) + record.bi_sql_view_required = record.move_lines_source.id == model_id diff --git a/mis_builder_bi_sql_editor/models/mis_report_instance.py b/mis_builder_bi_sql_editor/models/mis_report_instance.py new file mode 100644 index 0000000..4acfd24 --- /dev/null +++ b/mis_builder_bi_sql_editor/models/mis_report_instance.py @@ -0,0 +1,46 @@ +# Copyright 2025 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class MisReportInstancePeriod(models.Model): + _inherit = "mis.report.instance.period" + + bi_sql_view = fields.Many2one( + string="BI SQL View", + comodel_name="bi.sql.view", + domain=[("mis_builder_activated", "=", True)], + ) + bi_sql_view_required = fields.Boolean( + default=False, compute="_compute_bi_sql_view_required" + ) + + @api.depends("source", "source_aml_model_id") + def _compute_bi_sql_view_required(self): + for record in self: + if record.source == "actuals_alt": + model_id = ( + self.env["ir.model"] + .search([("model", "=", "mis.builder.bi.sql.line")]) + .id + ) + record.bi_sql_view_required = record.source_aml_model_id.id == model_id + else: + record.bi_sql_view_required = False + + def _get_additional_move_line_filter(self): + domain = super()._get_additional_move_line_filter() + if self.bi_sql_view: + domain = domain + [("bi_sql_model", "=", self.bi_sql_view.model_id.id)] + return domain + + +class MisReportInstance(models.Model): + _inherit = "mis.report.instance" + + bi_sql_view = fields.Many2one( + string="BI SQL View", + comodel_name="bi.sql.view", + related="report_id.bi_sql_view", + ) diff --git a/mis_builder_bi_sql_editor/pyproject.toml b/mis_builder_bi_sql_editor/pyproject.toml new file mode 100644 index 0000000..4231d0c --- /dev/null +++ b/mis_builder_bi_sql_editor/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mis_builder_bi_sql_editor/readme/CONTRIBUTORS.md b/mis_builder_bi_sql_editor/readme/CONTRIBUTORS.md new file mode 100644 index 0000000..e1ffbca --- /dev/null +++ b/mis_builder_bi_sql_editor/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- [Escodoo](https://www.escodoo.com.br): + - Marcel Savegnago \ + - Wesley Oliveira \ diff --git a/mis_builder_bi_sql_editor/readme/DESCRIPTION.md b/mis_builder_bi_sql_editor/readme/DESCRIPTION.md new file mode 100644 index 0000000..262b1c7 --- /dev/null +++ b/mis_builder_bi_sql_editor/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module make the BI SQL Editor query models compatible with MIS +Builder. diff --git a/mis_builder_bi_sql_editor/readme/USAGE.md b/mis_builder_bi_sql_editor/readme/USAGE.md new file mode 100644 index 0000000..413a7e8 --- /dev/null +++ b/mis_builder_bi_sql_editor/readme/USAGE.md @@ -0,0 +1,49 @@ +To use this module, you need to: + +Create a query with SQL BI Editor: + +- Use the BI SQL Editor to create your query. +- Make sure your query includes the required fields: x_credit, x_debit, + x_account_id, x_date and x_company_id. +- Optionally, you can include the x_analytic_account_id field for + analytical account support. + +Field Requirements: + +- \`x_credit\`: Must have type float. +- \`x_debit\`: Must have type float. +- \`x_date\`: Must have the date type. +- \`x_account_id\`: Must have the type many2one and be associated with + the account.account model. +- \`x_company_id\`: Must have the type many2one and be associated with + the res.company model. +- x_analytic_account_id (optional): Must have the type many2one and be + associated with the account.analytic.account model. + +Activate MIS Builder in the query model: + +- Once your query meets the above requirements, click the “Activate MIS + Builder” button. +- This will signal that the query should be used in the "Refresh MIS + Builder BI SQL Lines" cron. +- Refreshing materialized view will also create new lines in the model + (if there are new lines). + +Remove MIS Builder in the query model: + +- If you no longer need MIS Builder compatibility, click the "Remove MIS + Builder" button. +- This will delete the rows and columns related to your BI SQL model. + +Create MIS Builder report: + +- When creating a MIS Builder Report, select "BI SQL MIS Builder Line" + as the source. +- Afterwards, select the BI SQL View you want to use (The view must have + MIS Builder activated). +- When creating kpis for this report, you can use MIS expressions to + filter the fields in your query. +- To do this, it is necessary to use the name of the BI SQL View. +- Example: bal\[\]\[('x_bi_sql_view_mis.x_name', '=', 'test')\]. +- This will filter out the lines in your query that have the x_name + field with "test" as the value. diff --git a/mis_builder_bi_sql_editor/security/ir.model.access.csv b/mis_builder_bi_sql_editor/security/ir.model.access.csv new file mode 100644 index 0000000..1a41153 --- /dev/null +++ b/mis_builder_bi_sql_editor/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_mis_builder_bi_sql_line,access_mis_builder_bi_sql_line,model_mis_builder_bi_sql_line,base.group_user,1,0,0,0 +manage_mis_builder_bi_sql_line,manage_mis_builder_bi_sql_line,model_mis_builder_bi_sql_line,account.group_account_manager,1,1,1,1 diff --git a/mis_builder_bi_sql_editor/static/description/icon.png b/mis_builder_bi_sql_editor/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1afa781fabb8088818f3940ef56711e6281bd31e GIT binary patch literal 4770 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 literal 0 HcmV?d00001 diff --git a/mis_builder_bi_sql_editor/static/description/index.html b/mis_builder_bi_sql_editor/static/description/index.html new file mode 100644 index 0000000..bb85390 --- /dev/null +++ b/mis_builder_bi_sql_editor/static/description/index.html @@ -0,0 +1,489 @@ + + + + + +MIS Builder BI SQL Editor + + + +

+

MIS Builder BI SQL Editor

+ + +

Alpha License: AGPL-3 OCA/mis-builder-contrib Translate me on Weblate Try me on Runboat

+

This module make the BI SQL Editor query models compatible with MIS +Builder.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+

Create a query with SQL BI Editor:

+
    +
  • Use the BI SQL Editor to create your query.
  • +
  • Make sure your query includes the required fields: x_credit, x_debit, +x_account_id, x_date and x_company_id.
  • +
  • Optionally, you can include the x_analytic_account_id field for +analytical account support.
  • +
+

Field Requirements:

+
    +
  • `x_credit`: Must have type float.
  • +
  • `x_debit`: Must have type float.
  • +
  • `x_date`: Must have the date type.
  • +
  • `x_account_id`: Must have the type many2one and be associated with +the account.account model.
  • +
  • `x_company_id`: Must have the type many2one and be associated with +the res.company model.
  • +
  • x_analytic_account_id (optional): Must have the type many2one and be +associated with the account.analytic.account model.
  • +
+

Activate MIS Builder in the query model:

+
    +
  • Once your query meets the above requirements, click the “Activate MIS +Builder” button.
  • +
  • This will signal that the query should be used in the “Refresh MIS +Builder BI SQL Lines” cron.
  • +
  • Refreshing materialized view will also create new lines in the model +(if there are new lines).
  • +
+

Remove MIS Builder in the query model:

+
    +
  • If you no longer need MIS Builder compatibility, click the “Remove MIS +Builder” button.
  • +
  • This will delete the rows and columns related to your BI SQL model.
  • +
+

Create MIS Builder report:

+
    +
  • When creating a MIS Builder Report, select “BI SQL MIS Builder Line” +as the source.
  • +
  • Afterwards, select the BI SQL View you want to use (The view must have +MIS Builder activated).
  • +
  • When creating kpis for this report, you can use MIS expressions to +filter the fields in your query.
  • +
  • To do this, it is necessary to use the name of the BI SQL View.
  • +
  • Example: bal[][(‘x_bi_sql_view_mis.x_name’, ‘=’, ‘test’)].
  • +
  • This will filter out the lines in your query that have the x_name +field with “test” as the value.
  • +
+
+
+

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

+
    +
  • Escodoo
  • +
+
+
+

Contributors

+ +
+
+

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.

+

Current maintainer:

+

WesleyOliveira98

+

This module is part of the OCA/mis-builder-contrib project on GitHub.

+

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

+
+
+
+ + diff --git a/mis_builder_bi_sql_editor/tests/__init__.py b/mis_builder_bi_sql_editor/tests/__init__.py new file mode 100644 index 0000000..f6aaa3d --- /dev/null +++ b/mis_builder_bi_sql_editor/tests/__init__.py @@ -0,0 +1 @@ +from . import test_mis_builder_bi_sql_line diff --git a/mis_builder_bi_sql_editor/tests/test_mis_builder_bi_sql_line.py b/mis_builder_bi_sql_editor/tests/test_mis_builder_bi_sql_line.py new file mode 100644 index 0000000..f94eaa0 --- /dev/null +++ b/mis_builder_bi_sql_editor/tests/test_mis_builder_bi_sql_line.py @@ -0,0 +1,29 @@ +# Copyright 2025 - TODAY, Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.addons.base.tests.common import BaseCommon + + +class TestMisBuilderBiSqlLine(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company = cls.env.ref("base.main_company") + + def test_create_line(self): + line = self.env["mis.builder.bi.sql.line"].create( + { + "credit": 100.0, + "debit": 0.0, + "company_id": self.company.id, + } + ) + self.assertEqual(line.credit, 100.0) + self.assertEqual(line.company_id, self.company) + + def test_report_filter_without_bi_sql_view(self): + period = self.env["mis.report.instance.period"] + self.assertTrue( + hasattr(period, "_get_additional_move_line_filter"), + "mis.report.instance.period must expose _get_additional_move_line_filter", + ) diff --git a/mis_builder_bi_sql_editor/views/bi_sql_view.xml b/mis_builder_bi_sql_editor/views/bi_sql_view.xml new file mode 100644 index 0000000..4cbc6f2 --- /dev/null +++ b/mis_builder_bi_sql_editor/views/bi_sql_view.xml @@ -0,0 +1,31 @@ + + + + + bi.sql.view.form (in mis_builder_bi_sql_editor) + bi.sql.view + + +
+
+ + + + + +
+
diff --git a/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml b/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml new file mode 100644 index 0000000..16fe401 --- /dev/null +++ b/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml @@ -0,0 +1,42 @@ + + + + + + mis.builder.bi.sql.line.form + mis.builder.bi.sql.line + +
+ + + + + + + + + + + + +
+
+
+ + + mis.builder.bi.sql.line.list + mis.builder.bi.sql.line + + + + + + + + + + + + +
diff --git a/mis_builder_bi_sql_editor/views/mis_report.xml b/mis_builder_bi_sql_editor/views/mis_report.xml new file mode 100644 index 0000000..be70e22 --- /dev/null +++ b/mis_builder_bi_sql_editor/views/mis_report.xml @@ -0,0 +1,19 @@ + + + + + mis.report.view.form (in mis_builder_bi_sql_editor) + mis.report + + + + + + + + diff --git a/mis_builder_bi_sql_editor/views/mis_report_instance.xml b/mis_builder_bi_sql_editor/views/mis_report_instance.xml new file mode 100644 index 0000000..d5e7e22 --- /dev/null +++ b/mis_builder_bi_sql_editor/views/mis_report_instance.xml @@ -0,0 +1,24 @@ + + + + + mis.report.instance.period.form (in mis_builder_bi_sql_editor) + mis.report.instance.period + + + + + + + + From da1cac3a6034c4918c7f6761d5e4d9ebc50e6f38 Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Wed, 3 Jun 2026 19:02:12 -0300 Subject: [PATCH 2/2] [IMP] mis_builder_bi_sql_editor: code refactor update to v18 --- .../models/bi_sql_view.py | 96 +++++++++---------- .../models/mis_builder_bi_sql_line.py | 26 ++--- .../models/mis_report.py | 1 - .../views/mis_builder_bi_sql_line.xml | 2 - .../views/mis_report.xml | 2 +- .../views/mis_report_instance.xml | 2 +- 6 files changed, 64 insertions(+), 65 deletions(-) diff --git a/mis_builder_bi_sql_editor/models/bi_sql_view.py b/mis_builder_bi_sql_editor/models/bi_sql_view.py index 75a48ad..baaec34 100644 --- a/mis_builder_bi_sql_editor/models/bi_sql_view.py +++ b/mis_builder_bi_sql_editor/models/bi_sql_view.py @@ -5,57 +5,56 @@ class BiSQLView(models.Model): - _inherit = "bi.sql.view" mis_builder_compatible = fields.Boolean( compute="_compute_mis_builder_compatible", - default=False, ) mis_builder_activated = fields.Boolean(default=False) - @api.depends() + @api.depends( + "bi_sql_view_field_ids.name", + "bi_sql_view_field_ids.ttype", + "bi_sql_view_field_ids.many2one_model_id", + ) def _compute_mis_builder_compatible(self): - compatible = True - model_sql_fields = self.bi_sql_view_field_ids - credit_field = model_sql_fields.filtered( - lambda x: x.name == "x_credit" and x.ttype == "float" - ) - debit_field = model_sql_fields.filtered( - lambda x: x.name == "x_debit" and x.ttype == "float" - ) - account_field = model_sql_fields.filtered( - lambda x: x.name == "x_account_id" and x.ttype == "many2one" - ) - date_field = model_sql_fields.filtered( - lambda x: x.name == "x_date" and x.ttype == "date" - ) - company_field = model_sql_fields.filtered( - lambda x: x.name == "x_company_id" and x.ttype == "many2one" - ) - analytic_account_field = model_sql_fields.filtered( - lambda x: x.name == "x_analytic_account_id" and x.ttype == "many2one" - ) - - if ( - not credit_field - or not debit_field - or not account_field - or account_field.many2one_model_id.model != "account.account" - or not date_field - or not company_field - or company_field.many2one_model_id.model != "res.company" - or ( - analytic_account_field - and analytic_account_field.many2one_model_id.model - != "account.analytic.account" + for record in self: + model_sql_fields = record.bi_sql_view_field_ids + credit_field = model_sql_fields.filtered( + lambda x: x.name == "x_credit" and x.ttype == "float" + ) + debit_field = model_sql_fields.filtered( + lambda x: x.name == "x_debit" and x.ttype == "float" + ) + account_field = model_sql_fields.filtered( + lambda x: x.name == "x_account_id" and x.ttype == "many2one" + ) + date_field = model_sql_fields.filtered( + lambda x: x.name == "x_date" and x.ttype == "date" + ) + company_field = model_sql_fields.filtered( + lambda x: x.name == "x_company_id" and x.ttype == "many2one" + ) + analytic_account_field = model_sql_fields.filtered( + lambda x: x.name == "x_analytic_account_id" and x.ttype == "many2one" + ) + record.mis_builder_compatible = not ( + not credit_field + or not debit_field + or not account_field + or account_field.many2one_model_id.model != "account.account" + or not date_field + or not company_field + or company_field.many2one_model_id.model != "res.company" + or ( + analytic_account_field + and analytic_account_field.many2one_model_id.model + != "account.analytic.account" + ) ) - ): - compatible = False - - self.mis_builder_compatible = compatible def activate_mis_builder(self): + self.ensure_one() if self.mis_builder_compatible: model_id = ( self.env["ir.model"] @@ -74,6 +73,7 @@ def activate_mis_builder(self): self.mis_builder_activated = True def remove_mis_builder(self): + self.ensure_one() if self.mis_builder_compatible and self.mis_builder_activated: self.env["mis.builder.bi.sql.line"].search( [("bi_sql_model", "=", self.model_id.id)] @@ -99,13 +99,13 @@ def button_set_draft(self): return super().button_set_draft() def button_refresh_materialized_view(self): - super().button_refresh_materialized_view() + res = super().button_refresh_materialized_view() if self.mis_builder_activated: - model = self.env["mis.builder.bi.sql.line"] - model._create_mis_builder_bi_sql_lines() + self.env["mis.builder.bi.sql.line"]._create_mis_builder_bi_sql_lines() + return res - def copy(self, default=None): - self.ensure_one() - default = dict(default or {}) - default["mis_builder_activated"] = False - return super().copy(default) + def copy_data(self, default=None): + vals_list = super().copy_data(default=default) + for vals in vals_list: + vals["mis_builder_activated"] = False + return vals_list diff --git a/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py b/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py index b3cf42d..617dd4d 100644 --- a/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py +++ b/mis_builder_bi_sql_editor/models/mis_builder_bi_sql_line.py @@ -24,18 +24,18 @@ def _create_mis_builder_bi_sql_lines(self): ("mis_builder_activated", "=", True), ] ) + vals_list = [] for sql_view in sql_view_ids: - res = self.env[sql_view.model_id.model].search([]) - for line in res: - mis_sql_line = self.env["mis.builder.bi.sql.line"].search( - [ - ("bi_sql_model", "=", sql_view.model_id.id), - ("res_id", "=", line.id), - ], - limit=1, + existing_res_ids = set( + self.search([("bi_sql_model", "=", sql_view.model_id.id)]).mapped( + "res_id" ) - if not mis_sql_line: - vals = { + ) + for line in self.env[sql_view.model_id.model].search([]): + if line.id in existing_res_ids: + continue + vals_list.append( + { "credit": line.x_credit, "debit": line.x_debit, "account_id": line.x_account_id.id, @@ -44,6 +44,8 @@ def _create_mis_builder_bi_sql_lines(self): "analytic_account_id": line.x_analytic_account_id.id or False, "bi_sql_model": sql_view.model_id.id, "res_id": line.id, + sql_view.view_name: line.id, } - vals[sql_view.view_name] = line.id - self.create(vals) + ) + if vals_list: + self.create(vals_list) diff --git a/mis_builder_bi_sql_editor/models/mis_report.py b/mis_builder_bi_sql_editor/models/mis_report.py index 54974f8..1701713 100644 --- a/mis_builder_bi_sql_editor/models/mis_report.py +++ b/mis_builder_bi_sql_editor/models/mis_report.py @@ -5,7 +5,6 @@ class MisReport(models.Model): - _inherit = "mis.report" bi_sql_view = fields.Many2one( diff --git a/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml b/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml index 16fe401..bc43000 100644 --- a/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml +++ b/mis_builder_bi_sql_editor/views/mis_builder_bi_sql_line.xml @@ -2,7 +2,6 @@ - mis.builder.bi.sql.line.form mis.builder.bi.sql.line @@ -38,5 +37,4 @@ - diff --git a/mis_builder_bi_sql_editor/views/mis_report.xml b/mis_builder_bi_sql_editor/views/mis_report.xml index be70e22..76c9ed3 100644 --- a/mis_builder_bi_sql_editor/views/mis_report.xml +++ b/mis_builder_bi_sql_editor/views/mis_report.xml @@ -7,7 +7,7 @@ mis.report - + - +