diff --git a/addons/gamification/data/goal_base.xml b/addons/gamification/data/goal_base.xml index b517bb50713..af96a4806cf 100644 --- a/addons/gamification/data/goal_base.xml +++ b/addons/gamification/data/goal_base.xml @@ -297,7 +297,7 @@ Thank you, never inprogress - other + other @@ -307,7 +307,7 @@ Thank you, never inprogress - other + other diff --git a/addons/gamification/models/badge.py b/addons/gamification/models/badge.py index bd270113a52..7bfdd074644 100644 --- a/addons/gamification/models/badge.py +++ b/addons/gamification/models/badge.py @@ -107,8 +107,8 @@ class GamificationBadge(models.Model): 'gamification.badge.user', 'badge_id', string='Owners', help='The list of instances of this badge granted to users') - stat_count = fields.Integer("Total", compute='_get_owners_info', help="The number of time this badge has been received.") - stat_count_distinct = fields.Integer("Number of users", compute='_get_owners_info', help="The number of time this badge has been received by unique users.") + granted_count = fields.Integer("Total", compute='_get_owners_info', help="The number of time this badge has been received.") + granted_users_count = fields.Integer("Number of users", compute='_get_owners_info', help="The number of time this badge has been received by unique users.") unique_owner_ids = fields.Many2many( 'res.users', string="Unique Owners", compute='_get_owners_info', help="The list of unique users having received this badge.") @@ -139,8 +139,8 @@ class GamificationBadge(models.Model): the total number of users this badge was granted to """ self.env.cr.execute(""" - SELECT badge_id, count(user_id) as stat_count, - count(distinct(user_id)) as stat_count_distinct, + SELECT badge_id, count(user_id) as granted_count, + count(distinct(user_id)) as granted_users_count, array_agg(distinct(user_id)) as unique_owner_ids FROM gamification_badge_user WHERE badge_id in %s @@ -148,14 +148,14 @@ class GamificationBadge(models.Model): """, [tuple(self.ids)]) defaults = { - 'stat_count': 0, - 'stat_count_distinct': 0, + 'granted_count': 0, + 'granted_users_count': 0, 'unique_owner_ids': [], } mapping = { badge_id: { - 'stat_count': count, - 'stat_count_distinct': distinct_count, + 'granted_count': count, + 'granted_users_count': distinct_count, 'unique_owner_ids': owner_ids, } for (badge_id, count, distinct_count, owner_ids) in self.env.cr._obj diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py index 72103f89205..ad932dddc31 100644 --- a/addons/gamification/models/challenge.py +++ b/addons/gamification/models/challenge.py @@ -123,7 +123,7 @@ class Challenge(models.Model): last_report_date = fields.Date("Last Report Date", default=fields.Date.today) next_report_date = fields.Date("Next Report Date", compute='_get_next_report_date', store=True) - category = fields.Selection([ + challenge_category = fields.Selection([ ('hr', 'Human Resources / Engagement'), ('other', 'Settings / Gamification Tools'), ], string="Appears in", required=True, default='hr', diff --git a/addons/gamification/views/badge.xml b/addons/gamification/views/badge.xml index 5dc93d1f921..80d9130181a 100644 --- a/addons/gamification/views/badge.xml +++ b/addons/gamification/views/badge.xml @@ -35,7 +35,7 @@ - + @@ -91,11 +91,11 @@ - + - + - + @@ -117,7 +117,7 @@ - + @@ -141,7 +141,7 @@
Can not grant
- granted, + granted, this month
diff --git a/addons/gamification/views/challenge.xml b/addons/gamification/views/challenge.xml index bbc11afe910..6b8ccc9c25b 100644 --- a/addons/gamification/views/challenge.xml +++ b/addons/gamification/views/challenge.xml @@ -123,7 +123,7 @@
- + @@ -218,7 +218,7 @@ + domain="[('challenge_category', '=', 'hr')]"/> diff --git a/addons/hr_gamification/models/hr_employee.py b/addons/hr_gamification/models/hr_employee.py index d36edd79d49..441c104c635 100644 --- a/addons/hr_gamification/models/hr_employee.py +++ b/addons/hr_gamification/models/hr_employee.py @@ -18,12 +18,12 @@ class HrEmployeeBase(models.AbstractModel): 'gamification.badge.user', 'employee_id', help="Badges directly linked to the employee") - @api.depends('user_id.goal_ids.challenge_id.category') + @api.depends('user_id.goal_ids.challenge_id.challenge_category') def _compute_employee_goals(self): for employee in self: employee.goal_ids = self.env['gamification.goal'].search([ ('user_id', '=', employee.user_id.id), - ('challenge_id.category', '=', 'hr'), + ('challenge_id.challenge_category', '=', 'hr'), ]) @api.depends('direct_badge_ids', 'user_id.badge_ids.employee_id') diff --git a/addons/hr_gamification/views/gamification_views.xml b/addons/hr_gamification/views/gamification_views.xml index 6eddd1171ca..c2b378fa42d 100644 --- a/addons/hr_gamification/views/gamification_views.xml +++ b/addons/hr_gamification/views/gamification_views.xml @@ -7,7 +7,7 @@
-
@@ -19,7 +19,7 @@ Goals History tree,kanban {'search_default_group_by_user': True, 'search_default_group_by_definition': True} - [('challenge_id.category', '=', 'hr')] + [('challenge_id.challenge_category', '=', 'hr')]

Create a new goal @@ -35,7 +35,7 @@ Challenges gamification.challenge kanban,tree,form - [('category', '=', 'hr')] + [('challenge_category', '=', 'hr')] {'search_default_inprogress':True, 'default_inprogress':True}

diff --git a/addons/survey/data/survey_demo_certification.xml b/addons/survey/data/survey_demo_certification.xml index dedfdc7a2ed..f531ea7d89d 100644 --- a/addons/survey/data/survey_demo_certification.xml +++ b/addons/survey/data/survey_demo_certification.xml @@ -1,6 +1,13 @@ + + MyCompany Vendor + Congratulation, you are now official vendor of MyCompany + nobody + + + MyCompany Vendor Certification @@ -18,6 +25,8 @@ 2 <p>Test your vendor skills!</p> <p></p> + True + diff --git a/addons/survey/models/challenge.py b/addons/survey/models/challenge.py index e1677d46fc9..b4cd4626b91 100644 --- a/addons/survey/models/challenge.py +++ b/addons/survey/models/challenge.py @@ -7,4 +7,4 @@ from odoo import models, fields class Challenge(models.Model): _inherit = 'gamification.challenge' - category = fields.Selection(selection_add=[('certification', 'Certifications')]) + challenge_category = fields.Selection(selection_add=[('certification', 'Certifications')]) diff --git a/addons/survey/models/survey_survey.py b/addons/survey/models/survey_survey.py index 7a6a73491ed..92030be9cf8 100644 --- a/addons/survey/models/survey_survey.py +++ b/addons/survey/models/survey_survey.py @@ -705,6 +705,8 @@ class Survey(models.Model): # ------------------------------------------------------------ # GAMIFICATION / BADGES # ------------------------------------------------------------ + def _prepare_challenge_category(self): + return 'certification' def _create_certification_badge_trigger(self): self.ensure_one() @@ -725,7 +727,7 @@ class Survey(models.Model): 'reward_id': self.certification_badge_id.id, 'state': 'inprogress', 'period': 'once', - 'category': 'certification', + 'challenge_category': self._prepare_challenge_category(), 'reward_realtime': True, 'report_message_frequency': 'never', 'user_domain': [('karma', '>', 0)], diff --git a/addons/website_forum/data/badges_answer.xml b/addons/website_forum/data/badges_answer.xml index 88e0302f514..712a717c457 100644 --- a/addons/website_forum/data/badges_answer.xml +++ b/addons/website_forum/data/badges_answer.xml @@ -31,7 +31,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -66,7 +66,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -101,7 +101,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -136,7 +136,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -173,7 +173,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -208,7 +208,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -244,7 +244,7 @@ True [('karma', '>', 0)] inprogress - forum + forum diff --git a/addons/website_forum/data/badges_moderation.xml b/addons/website_forum/data/badges_moderation.xml index 9901875305d..65dae67a4a3 100644 --- a/addons/website_forum/data/badges_moderation.xml +++ b/addons/website_forum/data/badges_moderation.xml @@ -38,7 +38,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -74,7 +74,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -110,7 +110,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -145,7 +145,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -181,7 +181,7 @@ True [('karma', '>', 0)] inprogress - forum + forum diff --git a/addons/website_forum/data/badges_participation.xml b/addons/website_forum/data/badges_participation.xml index 88a6ac9b3f5..310f1fb2ab6 100644 --- a/addons/website_forum/data/badges_participation.xml +++ b/addons/website_forum/data/badges_participation.xml @@ -34,7 +34,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -70,7 +70,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -105,7 +105,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -129,7 +129,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -164,7 +164,7 @@ True [('karma', '>', 0)] inprogress - forum + forum diff --git a/addons/website_forum/data/badges_question.xml b/addons/website_forum/data/badges_question.xml index de95e53d12c..ecd45cb4ae3 100644 --- a/addons/website_forum/data/badges_question.xml +++ b/addons/website_forum/data/badges_question.xml @@ -31,7 +31,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -67,7 +67,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -102,7 +102,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -139,7 +139,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -174,7 +174,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -209,7 +209,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -246,7 +246,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -281,7 +281,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -316,7 +316,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -351,7 +351,7 @@ True [('karma', '>', 0)] inprogress - forum + forum @@ -387,7 +387,7 @@ True [('karma', '>', 0)] inprogress - forum + forum diff --git a/addons/website_forum/models/gamification.py b/addons/website_forum/models/gamification.py index 49544fae28f..902b5e0eab9 100644 --- a/addons/website_forum/models/gamification.py +++ b/addons/website_forum/models/gamification.py @@ -7,4 +7,4 @@ from odoo import models, fields class Challenge(models.Model): _inherit = 'gamification.challenge' - category = fields.Selection(selection_add=[('forum', 'Website / Forum')]) + challenge_category = fields.Selection(selection_add=[('forum', 'Website / Forum')]) diff --git a/addons/website_profile/controllers/main.py b/addons/website_profile/controllers/main.py index 2148f5b78a2..3d14024d1a0 100644 --- a/addons/website_profile/controllers/main.py +++ b/addons/website_profile/controllers/main.py @@ -168,11 +168,10 @@ class WebsiteProfile(http.Controller): """ domain = [('website_published', '=', True)] if 'badge_category' in kwargs: - domain = expression.AND([[('challenge_ids.category', '=', kwargs.get('badge_category'))], domain]) + domain = expression.AND([[('challenge_ids.challenge_category', '=', kwargs.get('badge_category'))], domain]) return domain - @http.route('/profile/ranks_badges', type='http', auth="public", website=True, sitemap=True) - def view_ranks_badges(self, **kwargs): + def _prepare_ranks_badges_values(self, **kwargs): ranks = [] if 'badge_category' not in kwargs: Rank = request.env['gamification.karma.rank'] @@ -180,7 +179,7 @@ class WebsiteProfile(http.Controller): Badge = request.env['gamification.badge'] badges = Badge.sudo().search(self._prepare_badges_domain(**kwargs)) - badges = sorted(badges, key=lambda b: b.stat_count_distinct, reverse=True) + badges = badges.sorted("granted_users_count", reverse=True) values = self._prepare_user_values(searches={'badges': True}) values.update({ @@ -188,6 +187,11 @@ class WebsiteProfile(http.Controller): 'badges': badges, 'user': request.env.user, }) + return values + + @http.route('/profile/ranks_badges', type='http', auth="public", website=True, sitemap=True) + def view_ranks_badges(self, **kwargs): + values = self._prepare_ranks_badges_values(**kwargs) return request.render("website_profile.rank_badge_main", values) # All Users Page diff --git a/addons/website_profile/static/src/scss/website_profile.scss b/addons/website_profile/static/src/scss/website_profile.scss index 07ac29b67fa..60a47bc7bc8 100644 --- a/addons/website_profile/static/src/scss/website_profile.scss +++ b/addons/website_profile/static/src/scss/website_profile.scss @@ -228,6 +228,10 @@ $owprofile-color-bg: mix($body-bg, #efeff4); } } +.wprofile_badge_img { + height: 2.5em; +} + // Other stuffs .country_flag { diff --git a/addons/website_profile/views/website_profile.xml b/addons/website_profile/views/website_profile.xml index 881bcb7f0da..50694cbcbfe 100644 --- a/addons/website_profile/views/website_profile.xml +++ b/addons/website_profile/views/website_profile.xml @@ -423,33 +423,40 @@ + + diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index c1a67026b70..d501ff21e2a 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -253,7 +253,7 @@ class WebsiteSlides(WebsiteProfile): challenges_done = None else: challenges = request.env['gamification.challenge'].sudo().search([ - ('category', '=', 'slides'), + ('challenge_category', '=', 'slides'), ('reward_id.is_published', '=', True) ], order='id asc', limit=5) challenges_done = request.env['gamification.badge.user'].sudo().search([ diff --git a/addons/website_slides/data/gamification_data.xml b/addons/website_slides/data/gamification_data.xml index 4cb9ce47af7..cefecaac089 100644 --- a/addons/website_slides/data/gamification_data.xml +++ b/addons/website_slides/data/gamification_data.xml @@ -27,7 +27,7 @@ Register to the platform - slides + slides once personal never @@ -69,7 +69,7 @@ Complete your profile - slides + slides once personal never @@ -109,7 +109,7 @@ Complete a course - slides + slides once personal never @@ -150,7 +150,7 @@ Get a certification - slides + slides once personal never @@ -190,7 +190,7 @@ Read 2000 XP - slides + slides once personal never diff --git a/addons/website_slides/models/gamification_challenge.py b/addons/website_slides/models/gamification_challenge.py index aa492e9b7cb..f1346f7ddab 100644 --- a/addons/website_slides/models/gamification_challenge.py +++ b/addons/website_slides/models/gamification_challenge.py @@ -7,4 +7,4 @@ from odoo import models, fields class Challenge(models.Model): _inherit = 'gamification.challenge' - category = fields.Selection(selection_add=[('slides', 'Website / Slides')]) + challenge_category = fields.Selection(selection_add=[('slides', 'Website / Slides')]) diff --git a/addons/website_slides_survey/controllers/slides.py b/addons/website_slides_survey/controllers/slides.py index 53d280d5b88..3c8f7bdc4ec 100644 --- a/addons/website_slides_survey/controllers/slides.py +++ b/addons/website_slides_survey/controllers/slides.py @@ -8,6 +8,7 @@ import werkzeug.exceptions from odoo import _ from odoo import http from odoo.http import request +from odoo.osv import expression from odoo.addons.website_slides.controllers.main import WebsiteSlides from collections import defaultdict @@ -74,3 +75,39 @@ class WebsiteSlides(WebsiteSlides): ] for user in users } return users_certificates + + # Badges & Ranks Page + # --------------------------------------------------- + def _prepare_ranks_badges_values(self, **kwargs): + """ Extract certification badges, to render them in ranks/badges page in another section. + Order them by number of granted users desc and show only badges linked to opened certifications.""" + values = super(WebsiteSlides, self)._prepare_ranks_badges_values(**kwargs) + + # 1. Getting all certification badges, sorted by granted user desc + domain = expression.AND([[('survey_id', '!=', False)], self._prepare_badges_domain(**kwargs)]) + certification_badges = request.env['gamification.badge'].sudo().search(domain) + # keep only the badge with challenge category = slides (the rest will be displayed under 'normal badges' section + certification_badges = certification_badges.filtered( + lambda b: 'slides' in b.challenge_ids.mapped('challenge_category')) + + if not certification_badges: + return values + + # 2. sort by granted users (done here, and not in search directly, because non stored field) + certification_badges = certification_badges.sorted("granted_users_count", reverse=True) + + # 3. Remove certification badge from badges and keep only certification badge linked to opened survey + badges = values['badges'] - certification_badges + certification_badges = certification_badges.filtered(lambda b: b.survey_id.state == 'open') + + # 4. Getting all course url for each badge + certification_slides = request.env['slide.slide'].sudo().search([('survey_id', 'in', certification_badges.mapped('survey_id').ids)]) + certification_badge_urls = {slide.survey_id.certification_badge_id.id: slide.channel_id.website_url for slide in certification_slides} + + # 5. Applying changes + values.update({ + 'badges': badges, + 'certification_badges': certification_badges, + 'certification_badge_urls': certification_badge_urls + }) + return values diff --git a/addons/website_slides_survey/models/slide_slide.py b/addons/website_slides_survey/models/slide_slide.py index 6bc157b1ac6..3b3ceadefa7 100644 --- a/addons/website_slides_survey/models/slide_slide.py +++ b/addons/website_slides_survey/models/slide_slide.py @@ -57,8 +57,34 @@ class Slide(models.Model): rec = super(Slide, self).create(values) if rec.survey_id: rec.slide_type = 'certification' + if 'survey_id' in values: + rec._ensure_challenge_category() return rec + def write(self, values): + old_surveys = self.mapped('survey_id') + result = super(Slide, self).write(values) + if 'survey_id' in values: + self._ensure_challenge_category(old_surveys=old_surveys - self.mapped('survey_id')) + return result + + def unlink(self): + old_surveys = self.mapped('survey_id') + result = super(Slide, self).unlink() + self._ensure_challenge_category(old_surveys=old_surveys, unlink=True) + return result + + def _ensure_challenge_category(self, old_surveys=None, unlink=False): + """ If a slide is linked to a survey that gives a badge, the challenge category of this badge must be + set to 'slides' in order to appear under the certification badge list on ranks_badges page. + If the survey is unlinked from the slide, the challenge category must be reset to 'certification'""" + if old_surveys: + old_certification_challenges = old_surveys.mapped('certification_badge_id').challenge_ids + old_certification_challenges.write({'challenge_category': 'certification'}) + if not unlink: + certification_challenges = self.mapped('survey_id').mapped('certification_badge_id').challenge_ids + certification_challenges.write({'challenge_category': 'slides'}) + def _generate_certification_url(self): """ get a map of certification url for certification slide from `self`. The url will come from the survey user input: 1/ existing and not done user_input for member of the course diff --git a/addons/website_slides_survey/models/survey_survey.py b/addons/website_slides_survey/models/survey_survey.py index dc8c91e1599..7f4e0c48bce 100644 --- a/addons/website_slides_survey/models/survey_survey.py +++ b/addons/website_slides_survey/models/survey_survey.py @@ -14,3 +14,7 @@ class Survey(models.Model): return True return super(Survey, self)._check_answer_creation(user, partner, email, test_entry=test_entry, check_attempts=check_attempts, invite_token=invite_token) + + def _prepare_challenge_category(self): + slide_survey = self.env['slide.slide'].search([('survey_id', '=', self.id)]) + return 'slides' if slide_survey else 'certification' diff --git a/addons/website_slides_survey/views/website_profile.xml b/addons/website_slides_survey/views/website_profile.xml index 386afb35c94..8a76d0867e3 100644 --- a/addons/website_slides_survey/views/website_profile.xml +++ b/addons/website_slides_survey/views/website_profile.xml @@ -16,7 +16,7 @@

-
+
@@ -62,4 +62,34 @@ + +