From d86dcafea6d6a4a36783c989df6ae44098587eab Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Fri, 7 Dec 2018 14:26:44 +0100 Subject: [PATCH] [FIX] project, rating: project percentage satisfaction compute performance This is basically a backport of revision 47479401cb3f685788d76abe01d3d2bc21ff11e3 to gain the performance on the project percentage satisaction computation but without introducing the new parent mixin, which would not be a stable change. --- addons/project/models/project.py | 13 ++++++------- addons/rating/models/rating.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/addons/project/models/project.py b/addons/project/models/project.py index b3286c2afe312..ecde1a1fa18bf 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -253,19 +253,18 @@ def _compute_access_warning(self): project.access_warning = _( "The project cannot be shared with the recipient(s) because the privacy of the project is too restricted. Set the privacy to 'Visible by following customers' in order to make it accessible by the recipient(s).") - @api.depends('percentage_satisfaction_task') + @api.depends('tasks.rating_ids.rating', 'tasks.rating_ids.parent_res_id') def _compute_percentage_satisfaction_project(self): - domain = [('create_date', '>=', fields.Datetime.to_string(fields.datetime.now() - timedelta(days=30)))] + res = self.env['project.task']._compute_parent_rating_percentage_satisfaction(self, rating_satisfaction_days=30) for project in self: - activity = project.tasks.rating_get_grades(domain) - project.percentage_satisfaction_project = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 + project.percentage_satisfaction_project = res[project.id] #TODO JEM: Only one field can be kept since project only contains task - @api.depends('tasks.rating_ids.rating') + @api.depends('tasks.rating_ids.rating', 'tasks.rating_ids.parent_res_id') def _compute_percentage_satisfaction_task(self): + res = self.env['project.task']._compute_parent_rating_percentage_satisfaction(self) for project in self: - activity = project.tasks.rating_get_grades() - project.percentage_satisfaction_task = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 + project.percentage_satisfaction_task = res[project.id] @api.depends('rating_status', 'rating_status_period') def _compute_rating_request_deadline(self): diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py index 5c81e0032e879..20daf0c5ee7ba 100644 --- a/addons/rating/models/rating.py +++ b/addons/rating/models/rating.py @@ -3,6 +3,8 @@ import base64 import uuid +from datetime import timedelta + from odoo import api, fields, models, tools, _ from odoo.modules.module import get_resource_path @@ -352,3 +354,31 @@ def rating_get_stats(self, domain=None): for rate in data['repartition']: result['percent'][rate] = (data['repartition'][rate] * 100) / data['total'] if data['total'] > 0 else 0 return result + + @api.model + def _compute_parent_rating_percentage_satisfaction(self, parent_records, rating_satisfaction_days=None): + # build domain and fetch data + domain = [('parent_res_model', '=', parent_records._name), ('parent_res_id', 'in', parent_records.ids), ('rating', '>=', 1), ('consumed', '=', True)] + if rating_satisfaction_days: + domain += [('create_date', '>=', fields.Datetime.to_string(fields.datetime.now() - timedelta(days=rating_satisfaction_days)))] + data = self.env['rating.rating'].read_group(domain, ['parent_res_id', 'rating'], ['parent_res_id', 'rating'], lazy=False) + + # get repartition of grades per parent id + default_grades = {'great': 0, 'okay': 0, 'bad': 0} + grades_per_parent = dict((parent_id, dict(default_grades)) for parent_id in parent_records.ids) # map: {parent_id: {'great': 0, 'bad': 0, 'ok': 0}} + for item in data: + parent_id = item['parent_res_id'] + rating = item['rating'] + if rating >= RATING_LIMIT_SATISFIED: + grades_per_parent[parent_id]['great'] += item['__count'] + elif rating > RATING_LIMIT_OK: + grades_per_parent[parent_id]['okay'] += item['__count'] + else: + grades_per_parent[parent_id]['bad'] += item['__count'] + + # compute percentage per parent + res = {} + for record in parent_records: + repartition = grades_per_parent.get(record.id) + res[record.id] = repartition['great'] * 100 / sum(repartition.values()) if sum(repartition.values()) else -1 + return res