From 26b005c5c327450d0dcad99029bd549084f6844e Mon Sep 17 00:00:00 2001 From: EdgarRetes Date: Wed, 20 Nov 2024 13:56:43 -0600 Subject: [PATCH] [MIG] kpi: Migration to 17.0 --- kpi/__manifest__.py | 4 +- kpi/models/kpi.py | 14 +++---- kpi/models/kpi_category.py | 4 +- kpi/models/kpi_history.py | 6 +-- kpi/models/kpi_threshold.py | 14 +++---- kpi/models/kpi_threshold_range.py | 18 ++++----- kpi/static/description/icon.png | Bin 9455 -> 25466 bytes kpi/static/description/icon.svg | 1 + kpi/tests/test_kpi.py | 5 ++- kpi/views/kpi_category_views.xml | 2 +- kpi/views/kpi_history_views.xml | 14 +++---- kpi/views/kpi_threshold_range_views.xml | 32 ++++++---------- kpi/views/kpi_threshold_views.xml | 6 +-- kpi/views/kpi_views.xml | 49 ++++++++++++++---------- kpi/views/menu.xml | 6 ++- 15 files changed, 84 insertions(+), 91 deletions(-) create mode 100644 kpi/static/description/icon.svg diff --git a/kpi/__manifest__.py b/kpi/__manifest__.py index 3c629dd94..734689a72 100644 --- a/kpi/__manifest__.py +++ b/kpi/__manifest__.py @@ -3,12 +3,12 @@ { "name": "Key Performance Indicator", - "version": "13.0.1.0.1", + "version": "17.0.1.0.0", "author": "Savoir-faire Linux,Odoo Community Association (OCA)", "website": "https://github.com/OCA/reporting-engine", "license": "AGPL-3", "category": "Report", - "depends": ["base_external_dbsource"], + "depends": ["base_external_dbsource", "spreadsheet_dashboard"], "data": [ "security/kpi_security.xml", "security/ir.model.access.csv", diff --git a/kpi/models/kpi.py b/kpi/models/kpi.py index 6b1f9312f..b7ebb504a 100644 --- a/kpi/models/kpi.py +++ b/kpi/models/kpi.py @@ -16,9 +16,9 @@ _logger = logging.getLogger(__name__) def is_one_value(result): # check if sql query returns only one value - if type(result) is dict and "value" in result.dictfetchone(): + if isinstance(result, dict) and "value" in result.dictfetchone(): return True - elif type(result) is list and "value" in result[0]: + elif isinstance(result, list) and "value" in result[0]: return True else: return False @@ -54,8 +54,8 @@ class KPI(models.Model): _name = "kpi" _description = "Key Performance Indicator" - name = fields.Char("Name", required=True) - description = fields.Text("Description") + name = fields.Char(required=True) + description = fields.Text() category_id = fields.Many2one( "kpi.category", "Category", @@ -66,7 +66,7 @@ class KPI(models.Model): "Threshold", required=True, ) - periodicity = fields.Integer("Periodicity", default=1) + periodicity = fields.Integer(default=1) periodicity_uom = fields.Selection( [ @@ -83,14 +83,11 @@ class KPI(models.Model): next_execution_date = fields.Datetime( "Next execution date", - readonly=True, ) value = fields.Float( - string="Value", compute="_compute_display_last_kpi_value", ) color = fields.Text( - "Color", compute="_compute_display_last_kpi_value", ) last_execution = fields.Datetime( @@ -122,7 +119,6 @@ class KPI(models.Model): "History", ) active = fields.Boolean( - "Active", help=( "Only active KPIs will be updated by the scheduler based on" " the periodicity configuration." diff --git a/kpi/models/kpi_category.py b/kpi/models/kpi_category.py index 17c572792..6491006c1 100644 --- a/kpi/models/kpi_category.py +++ b/kpi/models/kpi_category.py @@ -9,5 +9,5 @@ class KPICategory(models.Model): _name = "kpi.category" _description = "KPI Category" - name = fields.Char("Name", size=50, required=True) - description = fields.Text("Description") + name = fields.Char(required=True) + description = fields.Text() diff --git a/kpi/models/kpi_history.py b/kpi/models/kpi_history.py index 344d0c09c..e222e0243 100644 --- a/kpi/models/kpi_history.py +++ b/kpi/models/kpi_history.py @@ -12,7 +12,6 @@ class KPIHistory(models.Model): _order = "date desc" name = fields.Char( - "Name", size=150, required=True, default=fields.Datetime.now(), @@ -21,11 +20,10 @@ class KPIHistory(models.Model): date = fields.Datetime( "Execution Date", required=True, - readonly=True, default=lambda r: fields.Datetime.now(), ) - value = fields.Float("Value", required=True, readonly=True) - color = fields.Text("Color", required=True, readonly=True, default="#FFFFFF") + value = fields.Float(required=True) + color = fields.Text(required=True, default="#FFFFFF") company_id = fields.Many2one( "res.company", "Company", default=lambda self: self.env.company ) diff --git a/kpi/models/kpi_threshold.py b/kpi/models/kpi_threshold.py index 51fbdf930..5c9d3f893 100644 --- a/kpi/models/kpi_threshold.py +++ b/kpi/models/kpi_threshold.py @@ -34,7 +34,7 @@ class KPIThreshold(models.Model): "Please make sure your ranges do not overlap." ) - name = fields.Char("Name", size=50, required=True) + name = fields.Char(required=True) range_ids = fields.Many2many( "kpi.threshold.range", "kpi_threshold_range_rel", @@ -43,7 +43,6 @@ class KPIThreshold(models.Model): "Ranges", ) valid = fields.Boolean( - string="Valid", required=True, compute="_compute_is_valid_threshold", default=True, @@ -63,10 +62,11 @@ class KPIThreshold(models.Model): range_obj1 = self.env["kpi.threshold.range"] range_obj2 = self.env["kpi.threshold.range"] if data.get("range_ids"): - for range1 in data["range_ids"][0][2]: - range_obj1 = range_obj1.browse(range1) - for range2 in data["range_ids"][0][2]: - range_obj2 = range_obj2.browse(range2) + for range1 in data["range_ids"]: + range_obj1 = range_obj1.browse(range1[1]) + for range2 in data["range_ids"]: + range_obj2 = range_obj2.browse(range2[1]) + if ( range_obj1.valid and range_obj2.valid @@ -79,7 +79,7 @@ class KPIThreshold(models.Model): ) range_obj2 = self.env["kpi.threshold.range"] range_obj1 = self.env["kpi.threshold.range"] - return super(KPIThreshold, self).create(data) + return super().create(data) def get_color(self, kpi_value): color = "#FFFFFF" diff --git a/kpi/models/kpi_threshold_range.py b/kpi/models/kpi_threshold_range.py index 434c4d489..4c669170b 100644 --- a/kpi/models/kpi_threshold_range.py +++ b/kpi/models/kpi_threshold_range.py @@ -9,9 +9,9 @@ from odoo.tools.safe_eval import safe_eval def is_one_value(result): # check if sql query returns only one value - if type(result) is dict and "value" in result.dictfetchone(): + if isinstance(result, dict) and "value" in result.dictfetchone(): return True - elif type(result) is list and "value" in result[0]: + elif isinstance(result, list) and "value" in result[0]: return True else: return False @@ -58,16 +58,14 @@ class KPIThresholdRange(models.Model): ("external", "SQL - External DB"), ] - name = fields.Char("Name", size=50, required=True) + name = fields.Char(required=True) valid = fields.Boolean( - string="Valid", required=True, compute="_compute_is_valid_range", default=True + required=True, compute="_compute_is_valid_range", default=True ) invalid_message = fields.Char( string="Message", size=100, compute="_compute_is_valid_range" ) - min_type = fields.Selection( - selection="_selection_value_type", string="Min Type", required=True - ) + min_type = fields.Selection(selection="_selection_value_type", required=True) min_value = fields.Float(string="Minimum Value", compute="_compute_min_value") min_fixed_value = fields.Float("Minimum Fixed Value") min_code = fields.Text("Minimum Computation Code") @@ -76,9 +74,7 @@ class KPIThresholdRange(models.Model): "base.external.dbsource", "External DB Source Minimum", ) - max_type = fields.Selection( - selection="_selection_value_type", string="Max Type", required=True - ) + max_type = fields.Selection(selection="_selection_value_type", required=True) max_value = fields.Float(string="Maximum Value", compute="_compute_max_value") max_fixed_value = fields.Float("Maximum Fixed Value") max_code = fields.Text("Maximum Computation Code") @@ -88,7 +84,7 @@ class KPIThresholdRange(models.Model): "External DB Source Maximum", ) - color = fields.Char(string="Color", help="Choose your color") + color = fields.Char(help="Choose your color") threshold_ids = fields.Many2many( "kpi.threshold", diff --git a/kpi/static/description/icon.png b/kpi/static/description/icon.png index 3a0328b516c4980e8e44cdb63fd945757ddd132d..9e53b1e966a75c172683ee7a329c1692224218f1 100644 GIT binary patch literal 25466 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I diff --git a/kpi/static/description/icon.svg b/kpi/static/description/icon.svg new file mode 100644 index 000000000..2d9daf9ba --- /dev/null +++ b/kpi/static/description/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kpi/tests/test_kpi.py b/kpi/tests/test_kpi.py index 96c63eb42..4953efe3b 100644 --- a/kpi/tests/test_kpi.py +++ b/kpi/tests/test_kpi.py @@ -4,8 +4,9 @@ from odoo.tests.common import TransactionCase class TestKPI(TransactionCase): - def setUp(self): - super(TestKPI, self).setUp() + @classmethod + def setUpClass(cls): + super().setUpClass() def test_invalid_threshold_range(self): range1 = self.env["kpi.threshold.range"].create( diff --git a/kpi/views/kpi_category_views.xml b/kpi/views/kpi_category_views.xml index 466c5b80a..c809068a0 100644 --- a/kpi/views/kpi_category_views.xml +++ b/kpi/views/kpi_category_views.xml @@ -7,7 +7,7 @@ kpi.category.tree kpi.category - + diff --git a/kpi/views/kpi_history_views.xml b/kpi/views/kpi_history_views.xml index c2abf7ebd..635368c4d 100644 --- a/kpi/views/kpi_history_views.xml +++ b/kpi/views/kpi_history_views.xml @@ -7,11 +7,11 @@ kpi.history.tree kpi.history - + - - - + + + @@ -25,9 +25,9 @@ - - - + + + diff --git a/kpi/views/kpi_threshold_range_views.xml b/kpi/views/kpi_threshold_range_views.xml index 1473a32df..0ad77474b 100644 --- a/kpi/views/kpi_threshold_range_views.xml +++ b/kpi/views/kpi_threshold_range_views.xml @@ -7,11 +7,11 @@ kpi.threshold.range.tree kpi.threshold.range - + - + @@ -39,23 +39,19 @@ - + @@ -63,25 +59,21 @@ - + @@ -89,13 +81,13 @@ diff --git a/kpi/views/kpi_threshold_views.xml b/kpi/views/kpi_threshold_views.xml index 280181ccf..c69ac6e42 100644 --- a/kpi/views/kpi_threshold_views.xml +++ b/kpi/views/kpi_threshold_views.xml @@ -7,7 +7,7 @@ kpi.threshold.tree kpi.threshold - + @@ -38,13 +38,13 @@ diff --git a/kpi/views/kpi_views.xml b/kpi/views/kpi_views.xml index 34d68da09..85cc9bc35 100644 --- a/kpi/views/kpi_views.xml +++ b/kpi/views/kpi_views.xml @@ -8,9 +8,9 @@ kpi - + - + @@ -24,8 +24,8 @@ - - + + @@ -41,7 +41,7 @@ t-attf-style="color:#{record.color.raw_value}" > - +
- + - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -152,7 +159,7 @@ - KPI Maintenance + KPI kpi tree,form diff --git a/kpi/views/menu.xml b/kpi/views/menu.xml index b951090e8..58e7b145d 100644 --- a/kpi/views/menu.xml +++ b/kpi/views/menu.xml @@ -2,19 +2,21 @@ + +