Files
odoo_source/addons/gamification/models/res_users.py
T
David Beguin d7cc1520f4 [IMP] website_profile, gamification, : add search bar in all users page
This commit adds the search bar in 'All users' page in order to filter on name or company name.
To be able to keep the position, a non stored computed field has been added on res_users
to get the position depending on the user's karma.

The podium (top 3 users) is now displayed only if there is no search applied and if the page = 1
because it has no sens anymore in other cases.

Special thanks to @jem-odoo who helped me finding smart solution for position computing.

Task ID : 1943788
PR #31321
2019-03-15 14:59:12 +00:00

121 lines
4.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class Users(models.Model):
_inherit = 'res.users'
karma = fields.Integer('Karma', default=0)
karma_position = fields.Integer('Karma position', compute="_compute_karma_position", store=False)
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")
bronze_badge = fields.Integer('Bronze badges count', compute="_get_user_badge_level")
rank_id = fields.Many2one('gamification.karma.rank', 'Rank', index=False)
next_rank_id = fields.Many2one('gamification.karma.rank', 'Next Rank', index=False)
@api.depends('karma')
def _compute_karma_position(self):
where_query = self._where_calc([])
self._apply_ir_rules(where_query, 'read')
from_clause, where_clause, where_clause_params = where_query.get_sql()
query = """
SELECT sub.id, sub.karma_position
FROM (
SELECT id, row_number() OVER (ORDER BY res_users.karma DESC) AS karma_position
FROM {from_clause}
WHERE {where_clause}
) sub
WHERE sub.id IN %s
""".format(from_clause=from_clause, where_clause=where_clause)
self.env.cr.execute(query, where_clause_params + [tuple(self.ids)])
position_map = {item['id']: item['karma_position'] for item in self.env.cr.dictfetchall()}
for user in self:
user.karma_position = position_map.get(user.id, 0)
@api.multi
@api.depends('badge_ids')
def _get_user_badge_level(self):
""" Return total badge per level of users
TDE CLEANME: shouldn't check type is forum ? """
for user in self:
user.gold_badge = 0
user.silver_badge = 0
user.bronze_badge = 0
self.env.cr.execute("""
SELECT bu.user_id, b.level, count(1)
FROM gamification_badge_user bu, gamification_badge b
WHERE bu.user_id IN %s
AND bu.badge_id = b.id
AND b.level IS NOT NULL
GROUP BY bu.user_id, b.level
ORDER BY bu.user_id;
""", [tuple(self.ids)])
for (user_id, level, count) in self.env.cr.fetchall():
# levels are gold, silver, bronze but fields have _badge postfix
self.browse(user_id)['{}_badge'.format(level)] = count
@api.model_create_multi
def create(self, values_list):
res = super(Users, self).create(values_list)
res._recompute_rank()
return res
@api.multi
def write(self, vals):
result = super(Users, self).write(vals)
if 'karma' in vals:
self._recompute_rank()
return result
@api.multi
def add_karma(self, karma):
for user in self:
user.karma += karma
return True
def _rank_changed(self):
if self.rank_id.karma_min > 0:
template = self.env.ref('gamification.mail_template_data_new_rank_reached', raise_if_not_found=False)
if template:
template.send_mail(self.id, force_send=True, notif_layout='mail.mail_notification_light')
def _recompute_rank(self):
"""
The caller should filter the users on karma > 0 before calling this method
to avoid looping on every single users
"""
ranks = [{'rank': rank, 'karma_min': rank.karma_min} for rank in
self.env['gamification.karma.rank'].search([], order="karma_min DESC")]
for user in self:
old_rank = user.rank_id
if user.karma == 0 and ranks:
user.write({'next_rank_id': ranks[-1]['rank'].id})
else:
for i in range(0, len(ranks)):
if user.karma >= ranks[i]['karma_min']:
user.write({
'rank_id': ranks[i]['rank'].id,
'next_rank_id': ranks[i - 1]['rank'].id if 0 < i else False
})
break
if old_rank != user.rank_id:
user._rank_changed()
def get_gamification_redirection_data(self):
"""
Hook for other modules to add redirect button(s) in new rank reached mail
Must return a list of dictionnary including url and label.
E.g. return [{'url': '/forum', label: 'Go to Forum'}]
"""
self.ensure_one()
return []