From c414ea4a875ef7c428389943758bcfd1d62c0908 Mon Sep 17 00:00:00 2001 From: Richard deMeester Date: Thu, 28 Nov 2019 12:11:36 +1100 Subject: [PATCH] [12.0][ENH] sql view - allow group operator Replaces #345 Adds the possibility, for float and integer columns, to apply a group operator (average, min, max). --- bi_sql_editor_aggregate/__init__.py | 3 ++ bi_sql_editor_aggregate/__manifest__.py | 20 +++++++++ bi_sql_editor_aggregate/description/icon.png | Bin 0 -> 11127 bytes bi_sql_editor_aggregate/models/__init__.py | 5 +++ bi_sql_editor_aggregate/models/bi_sql_view.py | 38 ++++++++++++++++++ .../models/bi_sql_view_field.py | 25 ++++++++++++ bi_sql_editor_aggregate/models/ir_model.py | 14 +++++++ .../views/view_bi_sql_view.xml | 19 +++++++++ 8 files changed, 124 insertions(+) create mode 100644 bi_sql_editor_aggregate/__init__.py create mode 100644 bi_sql_editor_aggregate/__manifest__.py create mode 100644 bi_sql_editor_aggregate/description/icon.png create mode 100644 bi_sql_editor_aggregate/models/__init__.py create mode 100644 bi_sql_editor_aggregate/models/bi_sql_view.py create mode 100644 bi_sql_editor_aggregate/models/bi_sql_view_field.py create mode 100644 bi_sql_editor_aggregate/models/ir_model.py create mode 100644 bi_sql_editor_aggregate/views/view_bi_sql_view.xml diff --git a/bi_sql_editor_aggregate/__init__.py b/bi_sql_editor_aggregate/__init__.py new file mode 100644 index 00000000..83e553ac --- /dev/null +++ b/bi_sql_editor_aggregate/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/bi_sql_editor_aggregate/__manifest__.py b/bi_sql_editor_aggregate/__manifest__.py new file mode 100644 index 00000000..ac3766f0 --- /dev/null +++ b/bi_sql_editor_aggregate/__manifest__.py @@ -0,0 +1,20 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + 'name': 'BI SQL Editor Aggregate', + 'summary': 'BI SQL Editor Aggregation', + 'version': '12.0.1.0.0', + 'license': 'AGPL-3', + 'category': 'Reporting', + 'author': 'Richard deMeester,Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/reporting-engine', + 'depends': [ + 'bi_sql_editor', + ], + 'data': [ + 'views/view_bi_sql_view.xml', + ], + 'demo': [ + ], + 'installable': True, +} diff --git a/bi_sql_editor_aggregate/description/icon.png b/bi_sql_editor_aggregate/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c72ba5caa1302634ebeeb1689bb6df735f8bb5c8 GIT binary patch literal 11127 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 literal 0 HcmV?d00001 diff --git a/bi_sql_editor_aggregate/models/__init__.py b/bi_sql_editor_aggregate/models/__init__.py new file mode 100644 index 00000000..ef99aabc --- /dev/null +++ b/bi_sql_editor_aggregate/models/__init__.py @@ -0,0 +1,5 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import bi_sql_view +from . import bi_sql_view_field +from . import ir_model diff --git a/bi_sql_editor_aggregate/models/bi_sql_view.py b/bi_sql_editor_aggregate/models/bi_sql_view.py new file mode 100644 index 00000000..ceab2a34 --- /dev/null +++ b/bi_sql_editor_aggregate/models/bi_sql_view.py @@ -0,0 +1,38 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, tools + + +class BiSQLView(models.Model): + _inherit = 'bi.sql.view' + + def check_manual_fields(self, model): + # check the fields we need are defined on self, to stop it going + # early on install / startup - particularly problematic during upgrade + if 'group_operator' in tools.table_columns( + self.env.cr, 'bi_sql_view_field') and\ + model._name.startswith(self._model_prefix): + # 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. + self.env.cr.execute( + """ +SELECT + f.name, + f.ttype, + f.group_operator +FROM + bi_sql_view v + LEFT JOIN bi_sql_view_field f ON f.bi_sql_view_id = v.id +WHERE + v.model_name = %s +; + """, (model._name,) + ) + sql_fields = self.env.cr.fetchall() + + for sql_field in sql_fields: + if sql_field[0] in model._fields and\ + sql_field[1] in ('integer', 'float') and\ + sql_field[2]: + model._fields[sql_field[0]].group_operator = sql_field[2] diff --git a/bi_sql_editor_aggregate/models/bi_sql_view_field.py b/bi_sql_editor_aggregate/models/bi_sql_view_field.py new file mode 100644 index 00000000..00efc454 --- /dev/null +++ b/bi_sql_editor_aggregate/models/bi_sql_view_field.py @@ -0,0 +1,25 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models + + +class BiSQLViewField(models.Model): + _inherit = 'bi.sql.view.field' + + _GROUP_OPERATOR_SELECTION = [ + ('sum', 'Sum'), + ('avg', 'Average'), + ('min', 'Minimum'), + ('max', 'Maximum'), + ] + + _GRAPH_TYPE_SELECTION = [ + ('col', 'Column'), + ('row', 'Row'), + ('measure', 'Measure'), + ] + + group_operator = fields.Selection( + string='Group Operator', selection=_GROUP_OPERATOR_SELECTION, + help="By default, Odoo will sum the values when grouping. If you wish" + " to alter the behaviour, choose an alternate Group Operator") diff --git a/bi_sql_editor_aggregate/models/ir_model.py b/bi_sql_editor_aggregate/models/ir_model.py new file mode 100644 index 00000000..6ec21d50 --- /dev/null +++ b/bi_sql_editor_aggregate/models/ir_model.py @@ -0,0 +1,14 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + + +class IrModelFields(models.Model): + _inherit = 'ir.model.fields' + + def _add_manual_fields(self, model): + super()._add_manual_fields(model) + if 'bi.sql.view' in self.env: + Sql = self.env['bi.sql.view'] + if hasattr(Sql, 'check_manual_fields'): + Sql.check_manual_fields(model) diff --git a/bi_sql_editor_aggregate/views/view_bi_sql_view.xml b/bi_sql_editor_aggregate/views/view_bi_sql_view.xml new file mode 100644 index 00000000..f81f62dc --- /dev/null +++ b/bi_sql_editor_aggregate/views/view_bi_sql_view.xml @@ -0,0 +1,19 @@ + + + + + + + bi.sql.view + + + + + + + + +