[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:
committed by
Aurélien Warnon
parent
3607efc9f9
commit
4f2e06d0ca
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user