[IMP] website_slides: add next lesson field to membership

Before this commit,
There is no way to see the next lesson of attendee.

After this commit,
User/Manager can see the next lesson from backend.
Also added 'is_published' field into course's tree view.
Added search for responsible, tag and content, also added 'Archived' filter.

Task-2199207

closes odoo/odoo#79119

Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
This commit is contained in:
Nikunj Ladava
2023-04-12 18:58:23 +02:00
committed by Aurélien Warnon
parent 3607efc9f9
commit 4f2e06d0ca
4 changed files with 108 additions and 1 deletions
@@ -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),
@@ -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({
@@ -31,6 +31,7 @@
<field name="create_date" string="Enrolled On"/>
<field name="write_date" string="Last Action On"/>
<field name="completion" string="Progress" widget="progressbar"/>
<field name="next_slide_id"/>
<field name="channel_type" optional="hide"/>
<field name="channel_visibility" optional="hide"/>
<field name="channel_enroll" widget="badge"
@@ -162,6 +162,7 @@
<field name="channel_type" string="Course Type"/>
<field name="visibility"/>
<field name="enroll" widget="badge" decoration-success="enroll == 'public'" decoration-info="enroll == 'invite'" decoration-warning="enroll == 'payment'" optional="hide"/>
<field name="is_published" string="Published"/>
<field name="active" invisible="1"/>
</tree>
</field>
@@ -190,8 +191,12 @@
<field name="arch" type="xml">
<search string="Courses">
<field name="name" string="Course"/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<field name="user_id" string="Responsible"/>
<field name="tag_ids" string="Tags"/>
<field name="slide_ids" string="Contents"/>
<filter string="Published" name="filter_published" domain="[('is_published', '=', True)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
</search>
</field>
</record>