# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import math from dateutil.relativedelta import relativedelta from odoo import fields from odoo.addons.website_slides.tests import common from odoo.exceptions import UserError from odoo.tests import HttpCase, tagged from odoo.tests.common import users from odoo.tools import mute_logger, float_compare @tagged('functional') class TestChannelStatistics(common.SlidesCase): @mute_logger('odoo.models') def test_channel_new_content(self): (self.slide | self.slide_2).write({'date_published': fields.Datetime.now() + relativedelta(days=-6)}) self.slide_3.write({'date_published': fields.Datetime.now() + relativedelta(days=-8)}) self.assertTrue(all(slide.is_new_slide for slide in (self.slide | self.slide_2))) self.assertFalse(self.slide_3.is_new_slide) channel_aspublisher = self.channel.with_user(self.user_officer) self.assertTrue(channel_aspublisher.partner_has_new_content) (self.slide | self.slide_2).with_user(self.user_officer).action_mark_completed() self.assertFalse(channel_aspublisher.partner_has_new_content) channel_aspublisher._action_add_members(self.user_portal.partner_id) channel_asportal = self.channel.with_user(self.user_portal) self.assertTrue(channel_asportal.partner_has_new_content) (self.slide | self.slide_2).write({'date_published': fields.Datetime.now() + relativedelta(days=-8)}) channel_asportal.invalidate_recordset(['partner_has_new_content']) self.assertFalse(channel_asportal.partner_has_new_content) @mute_logger('odoo.models') def test_channel_statistics(self): channel_publisher = self.channel.with_user(self.user_officer) # slide category computation self.assertEqual(channel_publisher.total_slides, len(channel_publisher.slide_content_ids)) self.assertEqual(channel_publisher.nbr_infographic, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'infographic'))) self.assertEqual(channel_publisher.nbr_document, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'document'))) self.assertEqual(channel_publisher.nbr_video, len(channel_publisher.slide_content_ids.filtered(lambda s: s.slide_category == 'video'))) # slide statistics computation self.assertEqual(float_compare(channel_publisher.total_time, sum(s.completion_time for s in channel_publisher.slide_content_ids), 3), 0) # members computation self.assertEqual(channel_publisher.members_all_count, 1) channel_publisher._action_add_members(self.user_officer.partner_id) self.assertEqual(channel_publisher.members_all_count, 1) channel_publisher._action_add_members(self.user_emp.partner_id) channel_publisher.invalidate_recordset(['partner_ids']) self.assertEqual(channel_publisher.members_all_count, 2) self.assertEqual(channel_publisher.partner_ids, self.user_officer.partner_id | self.user_emp.partner_id) @mute_logger('odoo.models') def test_channel_user_statistics(self): channel_publisher = self.channel.with_user(self.user_officer) channel_publisher.write({ 'enroll': 'invite', }) channel_publisher._action_add_members(self.user_emp.partner_id) channel_emp = self.channel.with_user(self.user_emp) members = self.env['slide.channel.partner'].search([('channel_id', '=', self.channel.id)]) member_emp = members.filtered(lambda m: m.partner_id == self.user_emp.partner_id) member_publisher = members.filtered(lambda m: m.partner_id == self.user_officer.partner_id) slides_emp = (self.slide | self.slide_2).with_user(self.user_emp) slides_emp.action_set_viewed() self.assertEqual(member_emp.completion, 0) self.assertEqual(channel_emp.completion, 0) slides_emp.action_mark_completed() channel_emp.invalidate_recordset() self.assertEqual( channel_emp.completion, math.ceil(100.0 * len(slides_emp) / len(channel_publisher.slide_content_ids))) self.assertFalse(channel_emp.completed) self.slide_3.with_user(self.user_emp)._action_mark_completed() self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertTrue(channel_emp.completed) # The following tests should not update the completion for users that has already completed the course self.slide_3.is_published = False self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertTrue(channel_emp.completed) self.slide_3.is_published = True self.slide_3.active = False self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertTrue(channel_emp.completed) # Should update completion when slide is marked as completed self.assertEqual(member_publisher.completion, 0) self.assertEqual(channel_publisher.completion, 0) self.slide.with_user(self.user_officer).action_mark_completed() self.assertEqual(member_publisher.completion, 50) self.assertEqual(channel_publisher.completion, 50) # Should update completion when slide is (un)archived self.slide_3.active = True self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertEqual(member_publisher.completion, 33) self.assertEqual(channel_publisher.completion, 33) # Should update completion when a new published slide is created self.slide_4 = self.slide_3.copy({'is_published': True}) self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertEqual(member_publisher.completion, 25) self.assertEqual(channel_publisher.completion, 25) # Should update completion when slide is (un)published self.slide_4.is_published = False self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertEqual(member_publisher.completion, 33) self.assertEqual(channel_publisher.completion, 33) self.slide_4.is_published = True self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertEqual(member_publisher.completion, 25) self.assertEqual(channel_publisher.completion, 25) # Should update completion when a slide is unlinked self.slide_4.with_user(self.user_manager).unlink() self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertEqual(member_publisher.completion, 33) self.assertEqual(channel_publisher.completion, 33) # Should update completion when slide is marked as uncompleted slide_emp = self.slide.with_user(self.user_emp) slide_emp.action_mark_uncompleted() self.assertEqual(member_emp.completion, 100) self.assertEqual(channel_emp.completion, 100) self.assertTrue(channel_emp.completed) self.assertFalse(slide_emp.user_membership_id.completed) self.slide.invalidate_model(['user_has_completed']) slide_publisher = self.slide.with_user(self.user_officer) slide_publisher.action_mark_uncompleted() self.assertEqual(member_publisher.completion, 0) self.assertEqual(channel_publisher.completion, 0) self.assertFalse(channel_publisher.completed) self.assertFalse(slide_emp.user_membership_id.completed) @mute_logger('odoo.models') def test_channel_user_statistics_complete_check_member(self): slides = (self.slide | self.slide_2) slides.write({'is_preview': True}) slides.flush_model() slides_emp = slides.with_user(self.user_emp) slides_emp.read(['name']) with self.assertRaises(UserError): slides_emp.action_mark_completed() @mute_logger('odoo.models') def test_channel_user_statistics_view_check_member(self): slides = (self.slide | self.slide_2) slides.write({'is_preview': True}) slides.flush_model() slides_emp = slides.with_user(self.user_emp) slides_emp.read(['name']) with self.assertRaises(UserError): slides_emp.action_set_viewed() @tagged('functional') class TestSlideStatistics(common.SlidesCase): def test_slide_user_statistics(self): channel_publisher = self.channel.with_user(self.user_officer) channel_publisher._action_add_members(self.user_emp.partner_id) channel_publisher.invalidate_recordset(['partner_ids']) slide_emp = self.slide.with_user(self.user_emp) self.assertEqual(slide_emp.likes, 0) self.assertEqual(slide_emp.dislikes, 0) self.assertEqual(slide_emp.user_vote, 0) slide_emp.action_like() self.assertEqual(slide_emp.likes, 1) self.assertEqual(slide_emp.dislikes, 0) self.assertEqual(slide_emp.user_vote, 1) slide_emp.action_dislike() self.assertEqual(slide_emp.likes, 0) self.assertEqual(slide_emp.dislikes, 1) self.assertEqual(slide_emp.user_vote, -1) slide_emp.action_dislike() self.assertEqual(slide_emp.likes, 0) self.assertEqual(slide_emp.dislikes, 0) self.assertEqual(slide_emp.user_vote, 0) def test_slide_statistics_views(self): channel_publisher = self.channel.with_user(self.user_officer) channel_publisher._action_add_members(self.user_emp.partner_id) self.assertEqual(self.slide.slide_views, 0) self.assertEqual(self.slide.public_views, 0) self.slide.write({'public_views': 4}) self.assertEqual(self.slide.slide_views, 0) self.assertEqual(self.slide.public_views, 4) self.assertEqual(self.slide.total_views, 4) slide_emp = self.slide.with_user(self.user_emp) slide_emp.action_set_viewed() self.assertEqual(slide_emp.slide_views, 1) self.assertEqual(slide_emp.public_views, 4) self.assertEqual(slide_emp.total_views, 5) @users('user_officer') def test_slide_statistics_categories(self): category = self.category.with_user(self.env.user) self.assertEqual( category.nbr_document, len(category.channel_id.slide_ids.filtered(lambda s: s.category_id == category and s.slide_category == 'document'))) self.assertEqual(self.channel.total_slides, 3, 'The channel should contain 3 slides') self.assertEqual(category.total_slides, 2, 'The first category should contain 2 slides') self.assertEqual(category.completion_time, 4.5, 'The first category should be 4.5 hours long') other_category = self.env['slide.slide'].with_user(self.user_officer).create({ 'name': 'Other Category', 'channel_id': self.channel.id, 'is_category': True, 'is_published': True, 'sequence': 5, }) self.assertEqual(other_category.total_slides, 0, 'The other category should not contain any slide yet') # move one of the slide to the other category self.slide_3.write({'sequence': 6}) self.assertEqual(category.total_slides, 1, 'The first category should contain 1 slide') self.assertEqual(other_category.total_slides, 1, 'The other category should contain 1 slide') self.assertEqual(self.channel.total_slides, 3, 'The channel should still contain 3 slides') @tagged('functional') class TestHttpSlideStatistics(HttpCase, common.SlidesCase): @classmethod def setUpClass(cls): super(TestHttpSlideStatistics, cls).setUpClass() cls.slide.is_preview = True def test_slide_statistics_views(self): self.assertEqual(self.slide.public_views, 0) self.assertEqual(self.slide.total_views, 0) # Open the slide a first time. Must increase the views by 1 self.url_open(f'/slides/slide/{self.slide.id}') self.assertEqual(self.slide.public_views, 1) self.assertEqual(self.slide.total_views, 1) # Open the slide a second time. # As it's the same session, it must not increase the views anymore self.url_open(f'/slides/slide/{self.slide.id}') self.assertEqual(self.slide.public_views, 1) self.assertEqual(self.slide.total_views, 1)