From 31d73bec04956729e4fdd164b4f713485acfc3d5 Mon Sep 17 00:00:00 2001
From: thien
Date: Wed, 2 Oct 2024 15:05:05 +0700
Subject: [PATCH] [MIG] bi_sql_editor: Migration to 18.0
---
bi_sql_editor/README.rst | 28 ++++--
bi_sql_editor/__manifest__.py | 2 +-
bi_sql_editor/models/bi_sql_view.py | 104 ++++++++++----------
bi_sql_editor/models/bi_sql_view_field.py | 9 +-
bi_sql_editor/readme/CONTRIBUTORS.md | 2 +
bi_sql_editor/readme/CREDITS.md | 1 +
bi_sql_editor/static/description/index.html | 33 ++++---
bi_sql_editor/tests/test_bi_sql_view.py | 3 +-
bi_sql_editor/views/view_bi_sql_view.xml | 76 +++++++-------
9 files changed, 135 insertions(+), 123 deletions(-)
create mode 100644 bi_sql_editor/readme/CREDITS.md
diff --git a/bi_sql_editor/README.rst b/bi_sql_editor/README.rst
index aab31bac0..c4e575dd0 100644
--- a/bi_sql_editor/README.rst
+++ b/bi_sql_editor/README.rst
@@ -17,13 +17,13 @@ BI SQL Editor
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
- :target: https://github.com/OCA/reporting-engine/tree/17.0/bi_sql_editor
+ :target: https://github.com/OCA/reporting-engine/tree/18.0/bi_sql_editor
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/reporting-engine-17-0/reporting-engine-17-0-bi_sql_editor
+ :target: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-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/reporting-engine&target_branch=17.0
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -126,10 +126,10 @@ to make reporting depending on the current companies of the user.
- Finally, click on 'Create UI', to create new menu, action, graph view
and search view.
-.. |image1| image:: https://raw.githubusercontent.com/OCA/reporting-engine/17.0/bi_sql_editor/static/description/01_sql_request.png
-.. |image2| image:: https://raw.githubusercontent.com/OCA/reporting-engine/17.0/bi_sql_editor/static/description/02_security_access.png
-.. |image3| image:: https://raw.githubusercontent.com/OCA/reporting-engine/17.0/bi_sql_editor/static/description/03_field_mapping.png
-.. |image4| image:: https://raw.githubusercontent.com/OCA/reporting-engine/17.0/bi_sql_editor/static/description/04_materialized_view_setting.png
+.. |image1| image:: https://raw.githubusercontent.com/OCA/reporting-engine/18.0/bi_sql_editor/static/description/01_sql_request.png
+.. |image2| image:: https://raw.githubusercontent.com/OCA/reporting-engine/18.0/bi_sql_editor/static/description/02_security_access.png
+.. |image3| image:: https://raw.githubusercontent.com/OCA/reporting-engine/18.0/bi_sql_editor/static/description/03_field_mapping.png
+.. |image4| image:: https://raw.githubusercontent.com/OCA/reporting-engine/18.0/bi_sql_editor/static/description/04_materialized_view_setting.png
Usage
=====
@@ -145,7 +145,7 @@ To use this module, you need to:
- You can switch to 'Graph' or 'tree' views as any report.
-.. |usage-image1| image:: https://raw.githubusercontent.com/OCA/reporting-engine/17.0/bi_sql_editor/static/description/05_reporting_pivot.png
+.. |usage-image1| image:: https://raw.githubusercontent.com/OCA/reporting-engine/18.0/bi_sql_editor/static/description/05_reporting_pivot.png
Bug Tracker
===========
@@ -153,7 +153,7 @@ 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 `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -176,6 +176,8 @@ Contributors
- Guillem Casassas guillem.casassas@forgeflow.com
+- Thien Vo thienvh@trobz.com
+
- This module is highly inspired by the work of
- Onestein: (http://www.onestein.nl/) Module:
@@ -189,6 +191,12 @@ Contributors
grap/odoo-addons-misc/pos_sale_reporting link:
https://github.com/grap/odoo-addons-misc/tree/7.0/pos_sale_reporting
+Other credits
+-------------
+
+The migration of this module from 17.0 to 18.0 was financially supported
+by Camptocamp.
+
Maintainers
-----------
@@ -210,6 +218,6 @@ Current `maintainer `__:
|maintainer-legalsylvain|
-This module is part of the `OCA/reporting-engine `_ project on GitHub.
+This module is part of the `OCA/reporting-engine `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/bi_sql_editor/__manifest__.py b/bi_sql_editor/__manifest__.py
index 7158a635b..96f342c8d 100644
--- a/bi_sql_editor/__manifest__.py
+++ b/bi_sql_editor/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "BI SQL Editor",
"summary": "BI Views builder, based on Materialized or Normal SQL Views",
- "version": "17.0.1.1.0",
+ "version": "18.0.1.0.0",
"license": "AGPL-3",
"category": "Reporting",
"author": "GRAP,Odoo Community Association (OCA)",
diff --git a/bi_sql_editor/models/bi_sql_view.py b/bi_sql_editor/models/bi_sql_view.py
index b57f6597b..f608e6e78 100644
--- a/bi_sql_editor/models/bi_sql_view.py
+++ b/bi_sql_editor/models/bi_sql_view.py
@@ -6,10 +6,11 @@ import logging
from datetime import datetime, timedelta
from psycopg2 import ProgrammingError
+from psycopg2.sql import SQL, Identifier
from odoo import SUPERUSER_ID, _, api, fields, models
from odoo.exceptions import UserError, ValidationError
-from odoo.tools import sql, table_columns
+from odoo.tools import sql
from odoo.tools.safe_eval import safe_eval
_logger = logging.getLogger(__name__)
@@ -44,14 +45,12 @@ class BiSQLView(models.Model):
view_name = fields.Char(
compute="_compute_view_name",
- readonly=True,
store=True,
help="Full name of the SQL view",
)
model_name = fields.Char(
compute="_compute_model_name",
- readonly=True,
store=True,
help="Full Qualified Name of the transient model that will" " be created.",
)
@@ -65,7 +64,6 @@ class BiSQLView(models.Model):
size = fields.Char(
string="Database Size",
- readonly=True,
help="Size of the materialized view and its indexes",
)
@@ -73,8 +71,8 @@ class BiSQLView(models.Model):
view_order = fields.Char(
required=True,
- default="pivot,graph,tree",
- help="Comma-separated text. Possible values:" ' "graph", "pivot" or "tree"',
+ default="pivot,graph,list",
+ help="Comma-separated text. Possible values:" ' "graph", "pivot" or "list"',
)
query = fields.Text(
@@ -111,9 +109,7 @@ class BiSQLView(models.Model):
inverse_name="bi_sql_view_id",
)
- model_id = fields.Many2one(
- string="Odoo Model", comodel_name="ir.model", readonly=True
- )
+ model_id = fields.Many2one(string="Odoo Model", comodel_name="ir.model")
# UI related fields
# 1. Editable fields, which can be set by the user (optional) before
# creating the UI elements
@@ -133,39 +129,30 @@ class BiSQLView(models.Model):
)
# 2. Readonly fields, non editable by the user
- tree_view_id = fields.Many2one(
- string="Odoo Tree View", comodel_name="ir.ui.view", readonly=True
- )
+ tree_view_id = fields.Many2one(string="Odoo List View", comodel_name="ir.ui.view")
- graph_view_id = fields.Many2one(
- string="Odoo Graph View", comodel_name="ir.ui.view", readonly=True
- )
+ graph_view_id = fields.Many2one(string="Odoo Graph View", comodel_name="ir.ui.view")
- pivot_view_id = fields.Many2one(
- string="Odoo Pivot View", comodel_name="ir.ui.view", readonly=True
- )
+ pivot_view_id = fields.Many2one(string="Odoo Pivot View", comodel_name="ir.ui.view")
search_view_id = fields.Many2one(
- string="Odoo Search View", comodel_name="ir.ui.view", readonly=True
+ string="Odoo Search View", comodel_name="ir.ui.view"
)
action_id = fields.Many2one(
- string="Odoo Action", comodel_name="ir.actions.act_window", readonly=True
+ string="Odoo Action", comodel_name="ir.actions.act_window"
)
- menu_id = fields.Many2one(
- string="Odoo Menu", comodel_name="ir.ui.menu", readonly=True
- )
+ menu_id = fields.Many2one(string="Odoo Menu", comodel_name="ir.ui.menu")
cron_id = fields.Many2one(
string="Odoo Cron",
comodel_name="ir.cron",
- readonly=True,
help="Cron Task that will refresh the materialized view",
ondelete="cascade",
)
- rule_id = fields.Many2one(string="Odoo Rule", comodel_name="ir.rule", readonly=True)
+ rule_id = fields.Many2one(string="Odoo Rule", comodel_name="ir.rule")
sequence = fields.Integer(string="sequence")
@@ -183,9 +170,9 @@ class BiSQLView(models.Model):
for rec in self:
if rec.view_order:
for vtype in rec.view_order.split(","):
- if vtype not in ("graph", "pivot", "tree"):
+ if vtype not in ("graph", "pivot", "list"):
raise UserError(
- _("Only graph, pivot or tree views are supported")
+ _("Only graph, pivot or list views are supported")
)
# Compute Section
@@ -244,15 +231,15 @@ class BiSQLView(models.Model):
rec.menu_id.sequence = rec.sequence
return res
- def unlink(self):
+ @api.ondelete(at_uninstall=False)
+ def _check_unlink_constraints(self):
if any(view.state not in ("draft", "sql_valid") for view in self):
raise UserError(
_(
- "You can only unlink draft views."
+ "You can only unlink draft views. "
"If you want to delete them, first set them to draft."
)
)
- return super().unlink()
def copy(self, default=None):
self.ensure_one()
@@ -395,8 +382,7 @@ class BiSQLView(models.Model):
.search([("model", "=", self._name)], limit=1)
.id,
"state": "code",
- "code": "model._refresh_materialized_view_cron(%s)" % self.ids,
- "numbercall": -1,
+ "code": f"model._refresh_materialized_view_cron({self.ids})",
"interval_number": 1,
"interval_type": "days",
"nextcall": now + timedelta(days=1),
@@ -416,11 +402,11 @@ class BiSQLView(models.Model):
self.ensure_one()
return {
"name": self.name,
- "type": "tree",
+ "type": "list",
"model": self.model_id.model,
"arch": """"""
- """{}"""
- """""".format(
+ """{}"""
+ """
""".format(
"".join([x._prepare_tree_field() for x in self.bi_sql_view_field_ids])
),
}
@@ -477,7 +463,7 @@ class BiSQLView(models.Model):
self.ensure_one()
view_mode = self.view_order
first_view = view_mode.split(",")[0]
- if first_view == "tree":
+ if first_view == "list":
view_id = self.tree_view_id.id
elif first_view == "pivot":
view_id = self.pivot_view_id.id
@@ -510,19 +496,22 @@ class BiSQLView(models.Model):
return {
"name": self.name,
"parent_id": self.parent_menu_id.id,
- "action": "ir.actions.act_window,%s" % self.action_id.id,
+ "action": f"ir.actions.act_window,{self.action_id.id}",
"sequence": self.sequence,
}
# Custom Section
def _log_execute(self, req):
- _logger.info("Executing SQL Request %s ..." % req)
+ _logger.info(f"Executing SQL Request {req} ...")
self.env.cr.execute(req)
def _drop_view(self):
for sql_view in self:
self._log_execute(
- f"DROP {sql_view.materialized_text} VIEW IF EXISTS {sql_view.view_name}"
+ SQL("DROP {materialized_text} VIEW IF EXISTS {view_name}").format(
+ materialized_text=SQL(sql_view.materialized_text),
+ view_name=Identifier(sql_view.view_name),
+ )
)
sql_view.size = False
@@ -551,8 +540,11 @@ class BiSQLView(models.Model):
lambda x: x.is_index is True
):
self._log_execute(
- f"CREATE INDEX {sql_field.index_name} ON {sql_view.view_name} "
- f"({sql_field.name});"
+ SQL("CREATE INDEX {index_name} ON {view_name} ({name});").format(
+ index_name=SQL(sql_field.index_name),
+ view_name=Identifier(sql_view.view_name),
+ name=Identifier(sql_field.name),
+ )
)
def _create_model_and_fields(self):
@@ -562,7 +554,7 @@ class BiSQLView(models.Model):
sql_view.rule_id = self.env["ir.rule"].create(self._prepare_rule()).id
# Drop table, created by the ORM
if sql.table_exists(self._cr, sql_view.view_name):
- req = "DROP TABLE %s" % sql_view.view_name
+ req = SQL("DROP TABLE {}").format(Identifier(sql_view.view_name))
self._log_execute(req)
def _create_model_access(self):
@@ -585,28 +577,29 @@ class BiSQLView(models.Model):
def _hook_executed_request(self):
self.ensure_one()
- req = (
+ req = SQL(
"""
SELECT attnum,
attname AS column,
format_type(atttypid, atttypmod) AS type
FROM pg_attribute
- WHERE attrelid = '%s'::regclass
+ WHERE attrelid = '{view_name}'::regclass
AND NOT attisdropped
AND attnum > 0
ORDER BY attnum;"""
- % self.view_name
- )
+ ).format(view_name=Identifier(self.view_name))
self._log_execute(req)
return self.env.cr.fetchall()
def _prepare_request_check_execution(self):
self.ensure_one()
- return f"CREATE VIEW {self.view_name} AS ({self.query});"
+ return SQL("CREATE VIEW {view_name} AS ({query});").format(
+ view_name=Identifier(self.view_name), query=SQL(self.query)
+ )
def _prepare_request_for_execution(self):
self.ensure_one()
- query = (
+ query = SQL(
"""
SELECT
CAST(row_number() OVER () as integer) AS id,
@@ -616,11 +609,14 @@ class BiSQLView(models.Model):
CAST(Null as integer) as write_uid,
my_query.*
FROM
- (%s) as my_query
+ ({}) as my_query
"""
- % self.query
+ ).format(SQL(self.query))
+ return SQL("CREATE {materialized_text} VIEW {view_name} AS ({query});").format(
+ materialized_text=SQL(self.materialized_text),
+ view_name=Identifier(self.view_name),
+ query=query,
)
- return f"CREATE {self.materialized_text} VIEW {self.view_name} AS ({query});"
def _check_execution(self):
"""Ensure that the query is valid, trying to execute it.
@@ -689,8 +685,8 @@ class BiSQLView(models.Model):
def _refresh_size(self):
for sql_view in self:
- req = "SELECT pg_size_pretty(pg_total_relation_size('%s'));" % (
- sql_view.view_name
+ req = SQL("SELECT pg_size_pretty(pg_total_relation_size('{}'));").format(
+ Identifier(sql_view.view_name)
)
self._log_execute(req)
sql_view.size = self.env.cr.fetchone()[0]
@@ -700,7 +696,7 @@ class BiSQLView(models.Model):
# early on install / startup - particularly problematic during upgrade
if model._name.startswith(
self._model_prefix
- ) and "group_operator" in table_columns(self.env.cr, "bi_sql_view_field"):
+ ) and "group_operator" in sql.table_columns(self.env.cr, "bi_sql_view_field"):
# Use SQL instead of ORM, as ORM might not be fully initialised -
# we have no control over the order that fields are defined!
# We are not concerned about user security rules.
diff --git a/bi_sql_editor/models/bi_sql_view_field.py b/bi_sql_editor/models/bi_sql_view_field.py
index f098f20c2..f8bfe2b92 100644
--- a/bi_sql_editor/models/bi_sql_view_field.py
+++ b/bi_sql_editor/models/bi_sql_view_field.py
@@ -149,9 +149,8 @@ class BiSQLViewField(models.Model):
# Compute Section
def _compute_index_name(self):
for sql_field in self:
- sql_field.index_name = "{}_{}".format(
- sql_field.bi_sql_view_id.view_name,
- sql_field.name,
+ sql_field.index_name = (
+ f"{sql_field.bi_sql_view_id.view_name}_{sql_field.name}"
)
# Overload Section
@@ -209,8 +208,8 @@ class BiSQLViewField(models.Model):
field name. Sample :
{'account_id': 'account.account'; 'product_id': 'product.product'}
"""
- relation_fields = self.env["ir.model.fields"].search(
- [("ttype", "=", "many2one")]
+ relation_fields = (
+ self.env["ir.model.fields"].sudo().search([("ttype", "=", "many2one")])
)
res = {}
keys_to_pop = []
diff --git a/bi_sql_editor/readme/CONTRIBUTORS.md b/bi_sql_editor/readme/CONTRIBUTORS.md
index c787a3c70..2f6bce1bb 100644
--- a/bi_sql_editor/readme/CONTRIBUTORS.md
+++ b/bi_sql_editor/readme/CONTRIBUTORS.md
@@ -6,6 +6,8 @@
- Guillem Casassas
+- Thien Vo
+
- This module is highly inspired by the work of
- Onestein: () Module:
OCA/server-tools/bi_view_editor. Link:
diff --git a/bi_sql_editor/readme/CREDITS.md b/bi_sql_editor/readme/CREDITS.md
new file mode 100644
index 000000000..83b3ec91f
--- /dev/null
+++ b/bi_sql_editor/readme/CREDITS.md
@@ -0,0 +1 @@
+The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp.
diff --git a/bi_sql_editor/static/description/index.html b/bi_sql_editor/static/description/index.html
index d4ee7a4f7..f5b63b420 100644
--- a/bi_sql_editor/static/description/index.html
+++ b/bi_sql_editor/static/description/index.html
@@ -8,10 +8,11 @@
/*
:Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
+:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
+Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
-pre.code .ln { color: grey; } /* line numbers */
+pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
-span.problematic {
+span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -368,7 +369,7 @@ ul.auto-toc {
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1acb226c184032febd7db6e48ee618c7e5a6899c4685aa78b5b2e7578ebd9ce9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

This module extends the functionality of reporting, to support creation
of extra custom reports. It allows user to write a custom SQL request.
(Generally, admin users)
@@ -421,10 +422,10 @@ to reduce display duration
Go to Dashboard / Configuration / SQL Views
tip your SQL request
-
+
Select the group(s) that could have access to the view
-
+
Optionnaly, you can add a domain.
@@ -438,7 +439,7 @@ to make reporting depending on the current companies of the user.
view, and propose field mapping. For each field, you can decide to
create an index and set if it will be displayed on the pivot graph as
a column, a row or a measure.
-
+
Click on the button ‘Create SQL elements’. (this step could take a
while, if view is materialized)
@@ -451,7 +452,7 @@ the frequency of the refresh.
the size of view (and the indexes is displayed)
-
+
Before applying the final step, you will need to add a specific
Parent Menu to use when creating the UI Menu for the report. By
@@ -473,7 +474,7 @@ and search view.
-
+
- You can switch to ‘Graph’ or ‘tree’ views as any report.
@@ -483,7 +484,7 @@ and search view.
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.
+feedback.
Do not contact contributors directly about support or help with technical issues.
+
+
Other credits
+
The migration of this module from 17.0 to 18.0 was financially supported
+by Camptocamp.
+
Maintainers
This module is maintained by the OCA.
-

+
+
+
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:

-
This module is part of the OCA/reporting-engine project on GitHub.
+
This module is part of the OCA/reporting-engine project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/bi_sql_editor/tests/test_bi_sql_view.py b/bi_sql_editor/tests/test_bi_sql_view.py
index d7999ebfa..a85f30003 100644
--- a/bi_sql_editor/tests/test_bi_sql_view.py
+++ b/bi_sql_editor/tests/test_bi_sql_view.py
@@ -73,7 +73,7 @@ class TestBiSqlViewEditor(SingleTransactionCase):
[("name", "=", self.view.name)]
)
self.assertEqual(
- len(bi), 1, "Bi Manager should have access to bi %s" % self.view.name
+ len(bi), 1, f"Bi Manager should have access to bi {self.view.name}"
)
def test_unlink(self):
@@ -90,6 +90,7 @@ class TestBiSqlViewEditor(SingleTransactionCase):
self.assertEqual(copy_view.state, "ui_valid")
with self.assertRaises(UserError):
copy_view.unlink()
+
copy_view.button_set_draft()
self.assertNotEqual(
copy_view.cron_id,
diff --git a/bi_sql_editor/views/view_bi_sql_view.xml b/bi_sql_editor/views/view_bi_sql_view.xml
index 4590e19a1..3c2fa79c2 100644
--- a/bi_sql_editor/views/view_bi_sql_view.xml
+++ b/bi_sql_editor/views/view_bi_sql_view.xml
@@ -5,7 +5,6 @@ Copyright (C) 2017 - Today: GRAP (http://www.grap.coop)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
-
bi.sql.view
-
+
@@ -90,7 +89,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-
+
-
+
@@ -160,7 +161,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
readonly="state == 'ui_valid'"
/>
-
+
@@ -185,16 +186,12 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -246,7 +243,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
SQL Views
ir.actions.act_window
bi.sql.view
- tree,form
+ list,form
-