[FIX] website_slides: completly leave a channel

When leaving a channel, remove the earned karma in addition of the
slides.
This way, the user goes back in the same state as before completing
the course.
Add a message to clarify to the user the impact of leaving a course.
Add a test to answer questions

opw-2199066

closes odoo/odoo#47166

X-original-commit: a5e66d681ccd760c0af7bd0b179b5e42c76577ba
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
This commit is contained in:
Martin Trigaux
2020-03-09 09:10:29 +00:00
parent 2406a23259
commit a14fd21c60
5 changed files with 86 additions and 5 deletions
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server saas~13.2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-02-13 08:34+0000\n"
"PO-Revision-Date: 2020-02-13 08:34+0000\n"
"POT-Creation-Date: 2020-02-28 13:21+0000\n"
"PO-Revision-Date: 2020-02-28 13:21+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -702,6 +702,13 @@ msgstr ""
msgid "All Courses"
msgstr ""
#. module: website_slides
#. openerp-web
#: code:addons/website_slides/static/src/xml/website_slides_unsubscribe.xml:0
#, python-format
msgid "All completed classes and earned karma will be lost."
msgstr ""
#. module: website_slides
#: model:ir.model.fields,help:website_slides.field_slide_channel__partner_ids
msgid "All members of the channel."
+46 -1
View File
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import uuid
from collections import defaultdict
from dateutil.relativedelta import relativedelta
@@ -501,12 +502,56 @@ class Channel(models.Model):
for channel in self:
channel._action_add_members(channel.mapped('enroll_group_ids.users.partner_id'))
def _get_earned_karma(self, partner_ids):
""" Compute the number of karma earned by partners on a channel
Warning: this count will not be accurate if the configuration has been
modified after the completion of a course!
"""
total_karma = defaultdict(int)
slide_completed = self.env['slide.slide.partner'].sudo().search([
('partner_id', 'in', partner_ids),
('channel_id', 'in', self.ids),
('completed', '=', True),
('quiz_attempts_count', '>', 0)
])
for partner_slide in slide_completed:
slide = partner_slide.slide_id
if not slide.question_ids:
continue
gains = [slide.quiz_first_attempt_reward,
slide.quiz_second_attempt_reward,
slide.quiz_third_attempt_reward,
slide.quiz_fourth_attempt_reward]
attempts = min(partner_slide.quiz_attempts_count - 1, 3)
total_karma[partner_slide.partner_id.id] += gains[attempts]
channel_completed = self.env['slide.channel.partner'].sudo().search([
('partner_id', 'in', partner_ids),
('channel_id', 'in', self.ids),
('completed', '=', True)
])
for partner_channel in channel_completed:
channel = partner_channel.channel_id
total_karma[partner_channel.partner_id.id] += channel.karma_gen_channel_finish
return total_karma
def _remove_membership(self, partner_ids):
""" Unlink (!!!) the relationships between the passed partner_ids
and the channels and their slides (done in the unlink of slide.channel.partner model). """
and the channels and their slides (done in the unlink of slide.channel.partner model).
Remove earned karma when completed quizz """
if not partner_ids:
raise ValueError("Do not use this method with an empty partner_id recordset")
earned_karma = self._get_earned_karma(partner_ids)
users = self.env['res.users'].sudo().search([
('partner_id', 'in', list(earned_karma)),
])
for user in users:
if earned_karma[user.partner_id.id]:
user.add_karma(-1 * earned_karma[user.partner_id.id])
removed_channel_partner_domain = []
for channel in self:
removed_channel_partner_domain = expression.OR([
@@ -22,6 +22,7 @@
<t t-name="slides.course.unsubscribe.modal.leave">
<p>Do you really want to leave the course?</p>
<p>All completed classes and earned karma will be lost.</p>
</t>
</templates>
+15
View File
@@ -82,4 +82,19 @@ class SlidesCase(common.SavepointCase):
'is_published': True,
'completion_time': 1.5,
'sequence': 4,
'quiz_first_attempt_reward': 42,
})
cls.question_1 = cls.env['slide.question'].with_user(cls.user_officer).create({
'question': 'How long should be cooked a human?',
'slide_id': cls.slide_3.id,
})
cls.answer_1 = cls.env['slide.answer'].with_user(cls.user_officer).create({
'question_id': cls.question_1.id,
'text_value': "25' at 180°C",
'is_correct': True,
})
cls.answer_2 = cls.env['slide.answer'].with_user(cls.user_officer).create({
'question_id': cls.question_1.id,
'text_value': "Raw",
'is_correct': False,
})
+15 -2
View File
@@ -54,9 +54,16 @@ class TestKarmaGain(common.SlidesCase):
# Finish the Course
self.slide.with_user(user).action_set_completed()
self.assertFalse(self.channel.with_user(user).completed)
(self.slide_2 | self.slide_3).with_user(user).action_set_completed()
self.assertTrue(self.channel.with_user(user).completed)
self.slide_2.with_user(user).action_set_completed()
# answer a quizz question
self.slide_3.with_user(user).action_set_viewed(quiz_attempts_inc=True)
self.slide_3.with_user(user)._action_set_quiz_done()
self.slide_3.with_user(user).action_set_completed()
computed_karma += self.slide_3.quiz_first_attempt_reward
computed_karma += self.channel.karma_gen_channel_finish
self.assertTrue(self.channel.with_user(user).completed)
self.assertEqual(user.karma, computed_karma)
# Begin then finish the second Course
@@ -85,6 +92,12 @@ class TestKarmaGain(common.SlidesCase):
slide_user.action_dislike() # dislike again something already disliked should not remove karma again
self.assertEqual(user.karma, computed_karma)
# Leave the finished course
self.channel._remove_membership(user.partner_id.ids)
computed_karma -= self.channel.karma_gen_channel_finish
computed_karma -= self.slide_3.quiz_first_attempt_reward
self.assertEqual(user.karma, computed_karma)
@mute_logger('odoo.models')
@users('user_emp', 'user_portal', 'user_officer')
def test_karma_gain_multiple_course(self):