diff --git a/addons/gamification/__manifest__.py b/addons/gamification/__manifest__.py index 0270a25a56b..314dcf070a2 100644 --- a/addons/gamification/__manifest__.py +++ b/addons/gamification/__manifest__.py @@ -33,9 +33,11 @@ Both goals and badges are flexibles and can be adapted to a large range of modul 'data/gamification_karma_rank_data.xml', 'views/gamification.xml', 'views/gamification_karma_rank_views.xml', + 'views/gamification_karma_tracking_views.xml', 'views/mail_templates.xml' ], 'demo': [ - 'data/gamification_karma_rank_demo.xml' + 'data/gamification_karma_rank_demo.xml', + 'data/gamification_karma_tracking_demo.xml', ], } diff --git a/addons/gamification/data/cron.xml b/addons/gamification/data/cron.xml index 0ed59d39e11..4e59205647b 100644 --- a/addons/gamification/data/cron.xml +++ b/addons/gamification/data/cron.xml @@ -1,3 +1,4 @@ + @@ -10,5 +11,17 @@ -1 + + + Gamification: Karma tracking consolidation + + code + model._consolidate_last_month() + + 1 + months + -1 + + diff --git a/addons/gamification/data/gamification_karma_rank_demo.xml b/addons/gamification/data/gamification_karma_rank_demo.xml index 839e8750047..848e7fd68d0 100644 --- a/addons/gamification/data/gamification_karma_rank_demo.xml +++ b/addons/gamification/data/gamification_karma_rank_demo.xml @@ -1,13 +1,5 @@ - - - 20 - - - 10 - - @@ -44,5 +36,4 @@ - diff --git a/addons/gamification/data/gamification_karma_tracking_demo.xml b/addons/gamification/data/gamification_karma_tracking_demo.xml new file mode 100644 index 00000000000..01f4d8ac929 --- /dev/null +++ b/addons/gamification/data/gamification_karma_tracking_demo.xml @@ -0,0 +1,83 @@ + + + + + + + 0 + 1000 + + + + + 1000 + 1500 + + + + + 1500 + 2000 + + + + + 2000 + 2050 + + + + 2500 + + + + + + 0 + 5 + + + + + 5 + 10 + + + + + 10 + 20 + + + + + 20 + 25 + + + + 30 + + + + + + 0 + 2000 + + + + + 2000 + 2250 + + + + + 2250 + 2500 + + + + + diff --git a/addons/gamification/models/__init__.py b/addons/gamification/models/__init__.py index 926a5af2a07..659fcff70a1 100644 --- a/addons/gamification/models/__init__.py +++ b/addons/gamification/models/__init__.py @@ -5,4 +5,5 @@ from . import goal from . import challenge from . import badge from . import gamification_karma_rank +from . import gamification_karma_tracking from . import res_users diff --git a/addons/gamification/models/gamification_karma_tracking.py b/addons/gamification/models/gamification_karma_tracking.py new file mode 100644 index 00000000000..f7b184ad24d --- /dev/null +++ b/addons/gamification/models/gamification_karma_tracking.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import calendar + +from dateutil.relativedelta import relativedelta + +from odoo import api, fields, models + + +class KarmaTracking(models.Model): + _name = 'gamification.karma.tracking' + _description = 'Track Karma Changes' + _rec_name = 'user_id' + _order = 'tracking_date DESC' + + user_id = fields.Many2one('res.users', 'User', index=True, readonly=True, required=True, ondelete='cascade') + old_value = fields.Integer('Old Karma Value', required=True, readonly=True) + new_value = fields.Integer('New Karma Value', required=True, readonly=True) + consolidated = fields.Boolean('Consolidated') + tracking_date = fields.Date(default=fields.Date.context_today) + + @api.model + def _consolidate_last_month(self): + """ Consolidate last month. Used by a cron to cleanup tracking records. """ + previous_month_start = fields.Date.today() + relativedelta(months=-1, day=1) + return self._process_consolidate(previous_month_start) + + def _process_consolidate(self, from_date): + """ Consolidate trackings into a single record for a given month, starting + at a from_date (included). End date is set to last day of current month + using a smart calendar.monthrange construction. """ + end_date = from_date + relativedelta(day=calendar.monthrange(from_date.year, from_date.month)[1]) + select_query = """ +SELECT user_id, +( + SELECT old_value from gamification_karma_tracking old_tracking + WHERE old_tracking.user_id = gamification_karma_tracking.user_id + AND tracking_date::timestamp BETWEEN %(from_date)s AND %(to_date)s + AND consolidated IS NOT TRUE + ORDER BY tracking_date ASC LIMIT 1 +), ( + SELECT new_value from gamification_karma_tracking new_tracking + WHERE new_tracking.user_id = gamification_karma_tracking.user_id + AND tracking_date::timestamp BETWEEN %(from_date)s AND %(to_date)s + AND consolidated IS NOT TRUE + ORDER BY tracking_date DESC LIMIT 1 +) +FROM gamification_karma_tracking +WHERE tracking_date::timestamp BETWEEN %(from_date)s AND %(to_date)s +AND consolidated IS NOT TRUE +GROUP BY user_id """ + self.env.cr.execute(select_query, { + 'from_date': from_date, + 'to_date': end_date, + }) + results = self.env.cr.dictfetchall() + if results: + for result in results: + result['consolidated'] = True + result['tracking_date'] = fields.Date.to_string(from_date) + self.create(results) + + self.search([ + ('tracking_date', '>=', from_date), + ('tracking_date', '<=', end_date), + ('consolidated', '!=', True)] + ).unlink() + return True diff --git a/addons/gamification/models/res_users.py b/addons/gamification/models/res_users.py index 3e8b6d8e1cd..3dc95de74a1 100644 --- a/addons/gamification/models/res_users.py +++ b/addons/gamification/models/res_users.py @@ -3,16 +3,12 @@ from odoo import api, fields, models -import logging - -_logger = logging.getLogger(__name__) - class Users(models.Model): _inherit = 'res.users' - karma = fields.Integer('Karma', default=0) + karma_tracking_ids = fields.One2many('gamification.karma.tracking', 'user_id', string='Karma Changes', groups="base.group_system") badge_ids = fields.One2many('gamification.badge.user', 'user_id', string='Badges', copy=False) gold_badge = fields.Integer('Gold badges count', compute="_get_user_badge_level") silver_badge = fields.Integer('Silver badges count', compute="_get_user_badge_level") @@ -46,11 +42,28 @@ class Users(models.Model): @api.model_create_multi def create(self, values_list): res = super(Users, self).create(values_list) + + karma_trackings = [] + for user in res: + if user.karma: + karma_trackings.append({'user_id': user.id, 'old_value': 0, 'new_value': user.karma}) + if karma_trackings: + self.env['gamification.karma.tracking'].sudo().create(karma_trackings) + res._recompute_rank() return res def write(self, vals): + karma_trackings = [] + if 'karma' in vals: + for user in self: + if user.karma != vals['karma']: + karma_trackings.append({'user_id': user.id, 'old_value': user.karma, 'new_value': vals['karma']}) + result = super(Users, self).write(vals) + + if karma_trackings: + self.env['gamification.karma.tracking'].sudo().create(karma_trackings) if 'karma' in vals: self._recompute_rank() return result @@ -60,6 +73,68 @@ class Users(models.Model): user.karma += karma return True + def _get_tracking_karma_gain_position(self, user_domain, from_date=None, to_date=None): + """ Get absolute position in term of gained karma for users. First a ranking + of all users is done given a user_domain; then the position of each user + belonging to the current record set is extracted. + + Example: in website profile, search users with name containing Norbert. Their + positions should not be 1 to 4 (assuming 4 results), but their actual position + in the karma gain ranking (with example user_domain being karma > 1, + website published True). + + :param user_domain: general domain (i.e. active, karma > 1, website, ...) + to compute the absolute position of the current record set + :param from_date: compute karma gained after this date (included) or from + beginning of time; + :param to_date: compute karma gained before this date (included) or until + end of time; + + :return list: [{ + 'user_id': user_id (belonging to current record set), + 'karma_gain_total': integer, karma gained in the given timeframe, + 'karma_position': integer, ranking position + }, {..}] ordered by karma_position desc + """ + if not self: + return [] + + where_query = self.env['res.users']._where_calc(user_domain) + user_from_clause, user_where_clause, where_clause_params = where_query.get_sql() + + params = [] + if from_date: + date_from_condition = 'AND tracking.tracking_date::timestamp >= timestamp %s' + params.append(from_date) + if to_date: + date_to_condition = 'AND tracking.tracking_date::timestamp <= timestamp %s' + params.append(to_date) + params.append(tuple(self.ids)) + + query = """ +SELECT final.user_id, final.karma_gain_total, final.karma_position +FROM ( + SELECT intermediate.user_id, intermediate.karma_gain_total, row_number() OVER (ORDER BY intermediate.karma_gain_total DESC) AS karma_position + FROM ( + SELECT "res_users".id as user_id, COALESCE(SUM("tracking".new_value - "tracking".old_value), 0) as karma_gain_total + FROM %(user_from_clause)s + LEFT JOIN "gamification_karma_tracking" as "tracking" + ON "res_users".id = "tracking".user_id AND "res_users"."active" = TRUE + WHERE %(user_where_clause)s %(date_from_condition)s %(date_to_condition)s + GROUP BY "res_users".id + ORDER BY karma_gain_total DESC + ) intermediate +) final +WHERE final.user_id IN %%s""" % { + 'user_from_clause': user_from_clause, + 'user_where_clause': user_where_clause or (not from_date and not to_date and 'TRUE') or '', + 'date_from_condition': date_from_condition if from_date else '', + 'date_to_condition': date_to_condition if to_date else '' + } + + self.env.cr.execute(query, tuple(where_clause_params + params)) + return self.env.cr.dictfetchall() + def _rank_changed(self): """ Method that can be called on a batch of users with the same new rank @@ -68,7 +143,7 @@ class Users(models.Model): if template: for u in self: if u.rank_id.karma_min > 0: - template.send_mail(u.id, force_send=len(self) == 1, notif_layout='mail.mail_notification_light') + template.send_mail(u.id, force_send=False, notif_layout='mail.mail_notification_light') def _recompute_rank(self): """ @@ -161,7 +236,6 @@ class Users(models.Model): 'next_rank_id': lower_rank.id, }) - def _get_next_rank(self): """ For fresh users with 0 karma that don't have a rank_id and next_rank_id yet this method returns the first karma rank (by karma ascending). This acts as a diff --git a/addons/gamification/security/ir.model.access.csv b/addons/gamification/security/ir.model.access.csv index 41f36a87a5f..728360ab386 100644 --- a/addons/gamification/security/ir.model.access.csv +++ b/addons/gamification/security/ir.model.access.csv @@ -27,4 +27,6 @@ badge_user_portal,"Badge-user Portal",gamification.model_gamification_badge_user badge_user_public,"Badge-user Public",gamification.model_gamification_badge_user,base.group_public,1,0,0,0 gamification_karma_rank_access_all,gamification.karma.rank.access.all,gamification.model_gamification_karma_rank,,1,0,0,0 -gamification_karma_rank_access_user_manager,gamification.karma.rank.access.user.manager,gamification.model_gamification_karma_rank,base.group_erp_manager,1,1,1,1 +gamification_karma_rank_access_user_manager,gamification.karma.rank.access.user.manager,gamification.model_gamification_karma_rank,base.group_system,1,1,1,1 +gamification_karma_tracking_access_all,gamification.karma.tracking.access.all,gamification.model_gamification_karma_tracking,,0,0,0,0 +gamification_karma_tracking_access_user_manager,gamification.karma.tracking.access.user.manager,gamification.model_gamification_karma_tracking,base.group_system,1,1,1,1 diff --git a/addons/gamification/tests/__init__.py b/addons/gamification/tests/__init__.py index a6a599bf6c8..963887eb670 100644 --- a/addons/gamification/tests/__init__.py +++ b/addons/gamification/tests/__init__.py @@ -3,3 +3,4 @@ from . import test_challenge from . import test_recompute_rank +from . import test_karma_tracking diff --git a/addons/gamification/tests/test_karma_tracking.py b/addons/gamification/tests/test_karma_tracking.py new file mode 100644 index 00000000000..145b745b436 --- /dev/null +++ b/addons/gamification/tests/test_karma_tracking.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from datetime import date +from dateutil.relativedelta import relativedelta +from unittest.mock import patch + +from odoo import exceptions, fields +from odoo.tests import common + + +class TestKarmaTrackingCommon(common.SavepointCase): + + @classmethod + def setUpClass(cls): + super(TestKarmaTrackingCommon, cls).setUpClass() + cls.test_user = cls.env['res.users'].with_context(no_reset_password=True, mail_create_nosubscribe=True).create({ + 'name': 'Test User', + 'login': 'test', + 'email': 'test@example.com', + 'karma': 0, + 'groups_id': [(4, cls.env.ref('base.group_user').id)] + }) + cls.test_user_2 = cls.env['res.users'].with_context(no_reset_password=True, mail_create_nosubscribe=True).create({ + 'name': 'Test User 2', + 'login': 'test2', + 'email': 'test2@example.com', + 'karma': 0, + 'groups_id': [(4, cls.env.ref('base.group_user').id)] + }) + cls.env['gamification.karma.tracking'].search([]).unlink() + + cls.test_date = fields.Date.today() + relativedelta(month=4, day=1) + + @classmethod + def _create_trackings(cls, user, karma, steps, date, days_delta=1): + old_value = user.karma + for step in range(steps): + new_value = old_value + karma + cls.env['gamification.karma.tracking'].create([{ + 'user_id': user.id, + 'old_value': old_value, + 'new_value': new_value, + 'consolidated': False, + 'tracking_date': fields.Date.to_string(date) + }]) + old_value = new_value + date = date + relativedelta(days=days_delta) + + def test_computation_gain(self): + self._create_trackings(self.test_user, 20, 2, self.test_date, days_delta=30) + self._create_trackings(self.test_user_2, 10, 20, self.test_date, days_delta=2) + + results = (self.test_user | self.test_user_2)._get_tracking_karma_gain_position([]) + self.assertEqual(results[0]['user_id'], self.test_user_2.id) + self.assertEqual(results[0]['karma_gain_total'], 200) + self.assertEqual(results[0]['karma_position'], 1) + self.assertEqual(results[1]['user_id'], self.test_user.id) + self.assertEqual(results[1]['karma_gain_total'], 40) + self.assertEqual(results[1]['karma_position'], 2) + + results = (self.test_user | self.test_user_2)._get_tracking_karma_gain_position([], to_date=self.test_date + relativedelta(day=2)) + self.assertEqual(results[0]['user_id'], self.test_user.id) + self.assertEqual(results[0]['karma_gain_total'], 20) + self.assertEqual(results[0]['karma_position'], 1) + self.assertEqual(results[1]['user_id'], self.test_user_2.id) + self.assertEqual(results[1]['karma_gain_total'], 10) + self.assertEqual(results[1]['karma_position'], 2) + + results = (self.test_user | self.test_user_2)._get_tracking_karma_gain_position([], from_date=self.test_date + relativedelta(months=1, day=1)) + self.assertEqual(results[0]['user_id'], self.test_user_2.id) + self.assertEqual(results[0]['karma_gain_total'], 50) + self.assertEqual(results[0]['karma_position'], 1) + self.assertEqual(results[1]['user_id'], self.test_user.id) + self.assertEqual(results[1]['karma_gain_total'], 20) + self.assertEqual(results[1]['karma_position'], 2) + + results = self.env['res.users']._get_tracking_karma_gain_position([]) + self.assertEqual(len(results), 0) + + def test_consolidation_cron(self): + self.patcher = patch('odoo.addons.gamification.models.gamification_karma_tracking.fields.Date', wraps=fields.Date) + self.mock_datetime = self.patcher.start() + self.mock_datetime.today.return_value = date(self.test_date.year, self.test_date.month + 1, self.test_date.day) + + self._create_trackings(self.test_user, 20, 2, self.test_date, days_delta=30) + self._create_trackings(self.test_user_2, 10, 20, self.test_date, days_delta=2) + self.env['gamification.karma.tracking']._consolidate_last_month() + consolidated = self.env['gamification.karma.tracking'].search([ + ('user_id', 'in', (self.test_user | self.test_user_2).ids), + ('consolidated', '=', True), + ('tracking_date', '=', self.test_date) + ]) + self.assertEqual(len(consolidated), 2) + unconsolidated = self.env['gamification.karma.tracking'].search([ + ('user_id', 'in', (self.test_user | self.test_user_2).ids), + ('consolidated', '=', False), + ]) + self.assertEqual(len(unconsolidated), 6) # 5 for test user 2, 1 for test user + + self.patcher.stop() + + def test_consolidation_monthly(self): + Tracking = self.env['gamification.karma.tracking'] + base_test_user_karma = self.test_user.karma + base_test_user_2_karma = self.test_user_2.karma + self._create_trackings(self.test_user, 20, 2, self.test_date, days_delta=30) + self._create_trackings(self.test_user_2, 10, 20, self.test_date, days_delta=2) + + Tracking._process_consolidate(self.test_date) + consolidated = Tracking.search([ + ('user_id', '=', self.test_user_2.id), + ('consolidated', '=', True), + ('tracking_date', '=', self.test_date) + ]) + self.assertEqual(len(consolidated), 1) + self.assertEqual(consolidated.old_value, base_test_user_2_karma) # 15 2-days span, from 1 to 29 included = 15 steps -> 150 karma + self.assertEqual(consolidated.new_value, base_test_user_2_karma + 150) # 15 2-days span, from 1 to 29 included = 15 steps -> 150 karma + + remaining = Tracking.search([ + ('user_id', '=', self.test_user_2.id), + ('consolidated', '=', False) + ]) + self.assertEqual(len(remaining), 5) # 15 steps consolidated, remaining 5 + self.assertEqual(remaining[0].tracking_date, self.test_date + relativedelta(months=1, day=9)) # ordering: last first + self.assertEqual(remaining[-1].tracking_date, self.test_date + relativedelta(months=1, day=1)) + + Tracking._process_consolidate(self.test_date + relativedelta(months=1)) + consolidated = Tracking.search([ + ('user_id', '=', self.test_user_2.id), + ('consolidated', '=', True), + ]) + self.assertEqual(len(consolidated), 2) + self.assertEqual(consolidated[0].new_value, base_test_user_2_karma + 200) # 5 remaining 2-days span, from 1 to 9 included = 5 steps -> 50 karma + self.assertEqual(consolidated[0].old_value, base_test_user_2_karma + 150) # coming from previous iteration + self.assertEqual(consolidated[0].tracking_date, self.test_date + relativedelta(months=1)) # tracking set at beginning of month + self.assertEqual(consolidated[-1].new_value, base_test_user_2_karma + 150) # previously created one still present + self.assertEqual(consolidated[-1].old_value, base_test_user_2_karma) # previously created one still present + + remaining = Tracking.search([ + ('user_id', '=', self.test_user_2.id), + ('consolidated', '=', False) + ]) + self.assertFalse(remaining) + + # current user not-in-details tests + current_user_trackings = Tracking.search([ + ('user_id', '=', self.test_user.id), + ]) + self.assertEqual(len(current_user_trackings), 2) + self.assertEqual(current_user_trackings[0].new_value, base_test_user_karma + 40) + self.assertEqual(current_user_trackings[-1].old_value, base_test_user_karma) + + def test_user_as_erp_manager(self): + self.test_user.write({'groups_id': [ + (4, self.env.ref('base.group_partner_manager').id), + (4, self.env.ref('base.group_erp_manager').id) + ]}) + user = self.env['res.users'].with_user(self.test_user).create({ + 'name': 'Test Ostérone', 'karma': '32', + 'login': 'dummy', 'email': 'dummy@example.com', + }) + with self.assertRaises(exceptions.AccessError): + user.read(['karma_tracking_ids']) + + user.write({'karma': 60}) + user.add_karma(10) + self.assertEqual(user.karma, 70) + trackings = self.env['gamification.karma.tracking'].sudo().search([('user_id', '=', user.id)]) + self.assertEqual(len(trackings), 3) # create + write + add_karma + + def test_user_tracking(self): + self.test_user.write({'groups_id': [ + (4, self.env.ref('base.group_partner_manager').id), + (4, self.env.ref('base.group_system').id) + ]}) + user = self.env['res.users'].with_user(self.test_user).create({ + 'name': 'Test Ostérone', 'karma': '32', + 'login': 'dummy', 'email': 'dummy@example.com', + }) + self.assertEqual(user.karma, 32) + self.assertEqual(len(user.karma_tracking_ids), 1) + self.assertEqual(user.karma_tracking_ids.old_value, 0) + self.assertEqual(user.karma_tracking_ids.new_value, 32) + + user.write({'karma': 60}) + user.add_karma(10) + self.assertEqual(user.karma, 70) + self.assertEqual(len(user.karma_tracking_ids), 3) + self.assertEqual(user.karma_tracking_ids[2].old_value, 60) + self.assertEqual(user.karma_tracking_ids[2].new_value, 70) + self.assertEqual(user.karma_tracking_ids[1].old_value, 32) + self.assertEqual(user.karma_tracking_ids[1].new_value, 60) + self.assertEqual(user.karma_tracking_ids[0].old_value, 0) + self.assertEqual(user.karma_tracking_ids[0].new_value, 32) diff --git a/addons/gamification/views/gamification_karma_tracking_views.xml b/addons/gamification/views/gamification_karma_tracking_views.xml new file mode 100644 index 00000000000..998d0ff91ec --- /dev/null +++ b/addons/gamification/views/gamification_karma_tracking_views.xml @@ -0,0 +1,63 @@ + + + + gamification.karma.tracking.view.search + gamification.karma.tracking + + + + + + + + + + + + + + gamification.karma.tracking.view.tree + gamification.karma.tracking + + + + + + + + + + + + + gamification.karma.tracking.view.form + gamification.karma.tracking + +
+ + + + + + + + + +
+
+
+ + + Trackings + gamification.karma.tracking + tree,form + + + +
+
diff --git a/addons/website_profile/controllers/main.py b/addons/website_profile/controllers/main.py index eef5d1d4dc8..703fc250f96 100644 --- a/addons/website_profile/controllers/main.py +++ b/addons/website_profile/controllers/main.py @@ -8,7 +8,10 @@ import werkzeug.urls import werkzeug.wrappers import math -from odoo import http, modules, tools +from dateutil.relativedelta import relativedelta +from operator import itemgetter + +from odoo import fields, http, modules, tools from odoo.http import request from odoo.osv import expression @@ -205,12 +208,13 @@ class WebsiteProfile(http.Controller): @http.route(['/profile/users', '/profile/users/page/'], type='http', auth="public", website=True, sitemap=True) - def view_all_users_page(self, page=1, **searches): + def view_all_users_page(self, page=1, **kwargs): User = request.env['res.users'] dom = [('karma', '>', 1), ('website_published', '=', True)] # Searches - search_term = searches.get('search') + search_term = kwargs.get('search') + group_by = kwargs.get('group_by', False) if search_term: dom = expression.AND([['|', ('name', 'ilike', search_term), ('company_id.name', 'ilike', search_term)], dom]) @@ -225,12 +229,24 @@ class WebsiteProfile(http.Controller): user_values = self._prepare_all_users_values(users) # Get karma position for users (only website_published) - position_domain = [('karma', '>', 1), ('website_published', '=', True)] - position_map = self._get_users_karma_position(position_domain, users.ids) - for user in user_values: - user['position'] = position_map.get(user['id'], 0) + if group_by: + position_domain = [('karma', '>', 1), ('website_published', '=', True)] + position_map = self._get_user_tracking_karma_gain_position(position_domain, users.ids, group_by) + max_position = max([user_data['karma_position'] for user_data in position_map.values()], default=1) + for user in user_values: + user_data = position_map.get(user['id'], dict()) + user['position'] = user_data.get('karma_position', max_position + 1) + user['karma_gain'] = user_data.get('karma_gain_total', 0) + user_values.sort(key=itemgetter('position')) + else: + position_domain = [('karma', '>', 1), ('website_published', '=', True)] + position_map = self._get_users_karma_position(position_domain, users.ids) + for user in user_values: + user['position'] = position_map.get(user['id'], 0) + user['karma_gain'] = False values = { + 'group_by': group_by or 'all', 'top3_users': user_values[:3] if not search_term and page == 1 else None, 'users': user_values[3:] if not search_term and page == 1 else user_values, 'pager': pager @@ -244,8 +260,7 @@ class WebsiteProfile(http.Controller): if not user_ids: return {} - Users = request.env['res.users'] - where_query = Users._where_calc(domain) + where_query = request.env['res.users']._where_calc(domain) from_clause, where_clause, where_clause_params = where_query.get_sql() # we search on every user in the DB to get the real positioning (not the one inside the subset) @@ -264,6 +279,19 @@ class WebsiteProfile(http.Controller): return {item['id']: item['karma_position'] for item in request.env.cr.dictfetchall()} + def _get_user_tracking_karma_gain_position(self, domain, user_ids, group_by): + """ Helper method computing boundaries to give to _get_tracking_karma_gain_position. + See that method for more details. """ + to_date = fields.Date.today() + if group_by == 'week': + from_date = to_date - relativedelta(weeks=1) + elif group_by == 'month': + from_date = to_date - relativedelta(months=1) + else: + from_date = None + results = request.env['res.users'].browse(user_ids)._get_tracking_karma_gain_position(domain, from_date=from_date, to_date=to_date) + return dict((item['user_id'], dict(item)) for item in results) + # User and validation # -------------------------------------------------- diff --git a/addons/website_profile/views/website_profile.xml b/addons/website_profile/views/website_profile.xml index 629119b98d0..9a8dacb8e2a 100644 --- a/addons/website_profile/views/website_profile.xml +++ b/addons/website_profile/views/website_profile.xml @@ -481,7 +481,15 @@
-

All Users

+

All Users

+
+ Rank by : +
+ + + +
+
@@ -519,6 +527,9 @@

Unpublished +
+ + XP +