diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py
index 3f26e16414f..96d85673011 100644
--- a/addons/website_slides/models/slide_channel.py
+++ b/addons/website_slides/models/slide_channel.py
@@ -34,6 +34,7 @@ class ChannelUsersRelation(models.Model):
channel_visibility = fields.Selection(related='channel_id.visibility')
channel_enroll = fields.Selection(related='channel_id.enroll')
channel_website_id = fields.Many2one('website', string='Website', related='channel_id.website_id')
+ next_slide_id = fields.Many2one('slide.slide', string='Next Lesson', compute='_compute_next_slide_id')
_sql_constraints = [
('channel_partner_uniq',
@@ -46,6 +47,39 @@ class ChannelUsersRelation(models.Model):
)
]
+ def _compute_next_slide_id(self):
+ self.env['slide.channel.partner'].flush_model()
+ self.env['slide.slide'].flush_model()
+ self.env['slide.slide.partner'].flush_model()
+ query = """
+ SELECT DISTINCT ON (SCP.id)
+ SCP.id AS id,
+ SS.id AS slide_id
+ FROM slide_channel_partner SCP
+ JOIN slide_slide SS
+ ON SS.channel_id = SCP.channel_id
+ AND SS.is_published = TRUE
+ AND SS.active = TRUE
+ AND SS.is_category = FALSE
+ AND NOT EXISTS (
+ SELECT 1
+ FROM slide_slide_partner
+ WHERE slide_id = SS.id
+ AND partner_id = SCP.partner_id
+ AND completed = TRUE
+ )
+ WHERE SCP.id IN %s
+ ORDER BY SCP.id, SS.sequence, SS.id
+ """
+ self.env.cr.execute(query, [tuple(self.ids)])
+ next_slide_per_membership = {
+ line['id']: line['slide_id']
+ for line in self.env.cr.dictfetchall()
+ }
+
+ for membership in self:
+ membership.next_slide_id = next_slide_per_membership.get(membership.id, False)
+
def _recompute_completion(self):
read_group_res = self.env['slide.slide.partner'].sudo()._read_group(
['&', '&', ('channel_id', 'in', self.mapped('channel_id').ids),
diff --git a/addons/website_slides/tests/test_slide_channel.py b/addons/website_slides/tests/test_slide_channel.py
index 8fe333653cb..b140354920a 100644
--- a/addons/website_slides/tests/test_slide_channel.py
+++ b/addons/website_slides/tests/test_slide_channel.py
@@ -53,6 +53,73 @@ class TestSlidesManagement(slides_common.SlidesCase):
else:
self.assertTrue(slide.is_published, "All slides should be unpublished when a channel is archived, except categories")
+ @users('user_manager')
+ def test_channel_partner_next_slide(self):
+ """ Test the mechanic of the 'next_slide' field for memberships.
+ Next slide should be equal to the next slide in order (sequence, id) based on completion. """
+
+ channel = self.env['slide.channel'].create({
+ 'name': 'Channel1',
+ 'channel_type': 'documentation',
+ 'enroll': 'public',
+ 'visibility': 'public',
+ 'is_published': True,
+ })
+
+ category_1, category_2 = self.env['slide.slide'].create([{
+ 'name': 'Category %s' % i,
+ 'channel_id': channel.id,
+ 'is_category': True,
+ 'is_published': True,
+ } for i in [1, 2]])
+
+ # create 2 slides within the first category
+ slide_1, slide_2 = self.env['slide.slide'].create([{
+ 'name': 'slide %s' % i,
+ 'channel_id': channel.id,
+ 'category_id': category_1.id,
+ 'slide_category': 'document',
+ 'is_published': True,
+ } for i in [1, 2]])
+
+ # create 2 slides within the second category
+ slide_3, slide_4 = self.env['slide.slide'].create([{
+ 'name': 'slide %s' % i,
+ 'channel_id': channel.id,
+ 'category_id': category_2.id,
+ 'slide_category': 'document',
+ 'is_published': True,
+ } for i in [3, 4]])
+
+ self.assertEqual(channel.slide_content_ids, slide_1 | slide_2 | slide_3 | slide_4)
+ # test the behavior on both employees and portal users
+ users = self.user_emp | self.user_portal
+ channel.sudo()._action_add_members(users.partner_id)
+ memberships = self.env['slide.channel.partner'].sudo().search([('partner_id', 'in', users.partner_id.ids)])
+
+ for membership in memberships:
+ for slide in channel.slide_content_ids:
+ self.assertEqual(
+ membership.next_slide_id,
+ slide,
+ 'Expected %(expected_slide)s but got %(actual_slide)s' % {
+ 'expected_slide': slide.name,
+ 'actual_slide': membership.next_slide_id.name,
+ }
+ )
+
+ self.env['slide.slide.partner'].create({
+ 'slide_id': slide.id,
+ 'channel_id': channel.id,
+ 'partner_id': membership.partner_id.id,
+ 'completed': True
+ })
+
+ membership.invalidate_recordset(fnames=['next_slide_id'])
+
+ # we have gone through all the content, next slide should be False
+ self.assertFalse(membership.next_slide_id)
+
def test_mail_completed(self):
""" When the slide.channel is completed, an email is supposed to be sent to people that completed it. """
channel_2 = self.env['slide.channel'].create({
diff --git a/addons/website_slides/views/slide_channel_partner_views.xml b/addons/website_slides/views/slide_channel_partner_views.xml
index 6a91c424f67..ed53bf7af1a 100644
--- a/addons/website_slides/views/slide_channel_partner_views.xml
+++ b/addons/website_slides/views/slide_channel_partner_views.xml
@@ -31,6 +31,7 @@
+
+
@@ -190,8 +191,12 @@
-
+
+
+
+
+