From 052ddfba8dc7abf896b985f2412d574401290fef Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Tue, 31 Oct 2023 08:14:19 +0100 Subject: [PATCH 1/2] Send reminders only to related experts --- .../course_session/tests/test_attendance.py | 46 ++++++++++++++++++- .../notify/email/reminders/attendance.py | 17 ++++++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/server/vbv_lernwelt/course_session/tests/test_attendance.py b/server/vbv_lernwelt/course_session/tests/test_attendance.py index 347d1795..b9782167 100644 --- a/server/vbv_lernwelt/course_session/tests/test_attendance.py +++ b/server/vbv_lernwelt/course_session/tests/test_attendance.py @@ -3,14 +3,23 @@ from django.test import TestCase from vbv_lernwelt.core.constants import TEST_STUDENT1_USER_ID from vbv_lernwelt.core.create_default_users import create_default_users from vbv_lernwelt.core.models import User -from vbv_lernwelt.course.creators.test_course import create_test_course -from vbv_lernwelt.course.models import CourseCompletion, CourseSession +from vbv_lernwelt.course.creators.test_course import ( + create_test_course, + create_test_uk_circle_fahrzeug, +) +from vbv_lernwelt.course.models import ( + CourseCompletion, + CourseSession, + CourseSessionUser, +) from vbv_lernwelt.course.services import mark_course_completion from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse from vbv_lernwelt.course_session.services.attendance import ( AttendanceUserStatus, update_attendance_list, ) +from vbv_lernwelt.learnpath.models import Circle, LearningPath +from vbv_lernwelt.notify.email.reminders.attendance import get_recipients class AttendanceServicesTestCase(TestCase): @@ -88,3 +97,36 @@ class AttendanceServicesTestCase(TestCase): self.assertEqual(cc.user, student) self.assertEqual(cc.completion_status, "FAIL") self.assertEqual(cc.page_id, self.attendance_course.learning_content.id) + + +class AttendanceReminderTestCase(TestCase): + def setUp(self): + create_default_users() + create_test_course(include_vv=False, with_sessions=True) + self.course_session = CourseSession.objects.get(title="Test Bern 2022 a") + self.attendance_course = ( + self.course_session.coursesessionattendancecourse_set.first() + ) + self.trainer = User.objects.get(username="test-trainer1@example.com") + self.other_circle_title = "Something different" + lp = LearningPath.objects.get(title="Test Lernpfad") + create_test_uk_circle_fahrzeug(lp, title=self.other_circle_title) + csu = CourseSessionUser.objects.get(user=self.trainer) + fahrzeug = Circle.objects.get(title="Fahrzeug") + csu.expert.add(fahrzeug) + + def test_reminderOnlySendsToMembersAndRelevantExperts(self): + # promote user to expert, but in another circle + csu = CourseSessionUser.objects.get(user__email="test-student3@example.com") + other_circle = Circle.objects.get(title=self.other_circle_title) + csu.role = CourseSessionUser.Role.EXPERT + csu.save() + csu.expert.add(other_circle) + + expected_csu = { + "test-student1@example.com", + "test-student2@example.com", + "test-trainer1@example.com", + } + csus = get_recipients(self.attendance_course) + self.assertEqual(set([u.user.email for u in csus]), expected_csu) diff --git a/server/vbv_lernwelt/notify/email/reminders/attendance.py b/server/vbv_lernwelt/notify/email/reminders/attendance.py index aa97081d..e76f3ba5 100644 --- a/server/vbv_lernwelt/notify/email/reminders/attendance.py +++ b/server/vbv_lernwelt/notify/email/reminders/attendance.py @@ -2,10 +2,12 @@ from collections import Counter from datetime import timedelta import structlog +from django.db.models import QuerySet from django.utils import timezone from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse +from vbv_lernwelt.learnpath.models import Circle from vbv_lernwelt.notify.services import NotificationService logger = structlog.get_logger(__name__) @@ -32,7 +34,7 @@ def send_attendance_reminder_notifications(): ) for attendance_course in attendance_courses: cs_id = attendance_course.course_session.id - csu = CourseSessionUser.objects.filter(course_session_id=cs_id) + csu = get_recipients(attendance_course) logger.info( "Sending attendance course reminder notification", start_time=start.isoformat(), @@ -52,3 +54,16 @@ def send_attendance_reminder_notifications(): label="attendance_course_reminder_notification_job", ) return dict(results_counter) + + +def get_recipients( + attendance_course: CourseSessionAttendanceCourse, +) -> QuerySet["CourseSessionUser"]: + cs_id = attendance_course.course_session.id + circle_page = attendance_course.learning_content.get_parent_circle() + circle = Circle.objects.get(page_ptr=circle_page.id) + experts = circle.expert.all() + members = CourseSessionUser.objects.filter( + course_session_id=cs_id, role=CourseSessionUser.Role.MEMBER + ) + return members | experts From c1e73f58e61088bb5dba1a288f1d127d47956202 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Thu, 2 Nov 2023 16:52:02 +0100 Subject: [PATCH 2/2] `get_recipients` should only fetch experts for the course session --- server/vbv_lernwelt/core/constants.py | 1 + server/vbv_lernwelt/core/create_default_users.py | 8 ++++++++ server/vbv_lernwelt/course/creators/test_course.py | 8 ++++++++ .../vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py | 6 +++--- server/vbv_lernwelt/notify/email/reminders/attendance.py | 4 +++- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/server/vbv_lernwelt/core/constants.py b/server/vbv_lernwelt/core/constants.py index 4ec9713b..137f3dc0 100644 --- a/server/vbv_lernwelt/core/constants.py +++ b/server/vbv_lernwelt/core/constants.py @@ -19,6 +19,7 @@ DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER = [ # ids for cypress test data ADMIN_USER_ID = "872efd96-3bd7-4a1e-a239-2d72cad9f604" TEST_TRAINER1_USER_ID = "b9e71f59-c44f-4290-b93a-9b3151e9a2fc" +TEST_TRAINER2_USER_ID = "299941ae-1e4b-4f45-8180-876c3ad340b4" TEST_STUDENT1_USER_ID = "65c73ad0-6d53-43a9-a4a4-64143f27b03a" TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900" TEST_STUDENT3_USER_ID = "bcf94dba-53bc-474b-a22d-e4af39aa042b" diff --git a/server/vbv_lernwelt/core/create_default_users.py b/server/vbv_lernwelt/core/create_default_users.py index a3fe30d7..a3cbc6c8 100644 --- a/server/vbv_lernwelt/core/create_default_users.py +++ b/server/vbv_lernwelt/core/create_default_users.py @@ -11,6 +11,7 @@ from vbv_lernwelt.core.constants import ( TEST_STUDENT2_USER_ID, TEST_STUDENT3_USER_ID, TEST_TRAINER1_USER_ID, + TEST_TRAINER2_USER_ID, ) from vbv_lernwelt.core.models import User @@ -271,6 +272,13 @@ def create_default_users(user_model=User, group_model=Group, default_password=No last_name="Trainer1", avatar_url="/static/avatars/uk1.patrizia.huggel.jpg", ) + _create_student_user( + id=TEST_TRAINER2_USER_ID, + email="test-trainer2@example.com", + first_name="Test", + last_name="Trainer2", + avatar_url="/static/avatars/uk1.christian.koller.jpg", + ) _create_student_user( id=TEST_STUDENT1_USER_ID, email="test-student1@example.com", diff --git a/server/vbv_lernwelt/course/creators/test_course.py b/server/vbv_lernwelt/course/creators/test_course.py index 040e6c58..da40d742 100644 --- a/server/vbv_lernwelt/course/creators/test_course.py +++ b/server/vbv_lernwelt/course/creators/test_course.py @@ -199,6 +199,14 @@ def create_test_course(include_uk=True, include_vv=True, with_sessions=False): ) csu.expert.add(Circle.objects.get(slug="test-lehrgang-lp-circle-fahrzeug")) + trainer2 = User.objects.get(email="test-trainer2@example.com") + csu = CourseSessionUser.objects.create( + course_session=cs_zurich, + user=trainer2, + role=CourseSessionUser.Role.EXPERT, + ) + csu.expert.add(Circle.objects.get(slug="test-lehrgang-lp-circle-fahrzeug")) + student1 = User.objects.get(email="test-student1@example.com") _csu = CourseSessionUser.objects.create( course_session=cs_bern, diff --git a/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py b/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py index dc93b150..20c6d684 100644 --- a/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py +++ b/server/vbv_lernwelt/edoniq_test/tests/test_edoniq_export.py @@ -42,7 +42,7 @@ class EdoniqUserExportTestCase(TestCase): users = fetch_course_session_users( [COURSE_TEST_ID], role=CourseSessionUser.Role.EXPERT, excluded_domains=[] ) - self.assertEqual(len(users), 1) + self.assertEqual(len(users), 2) def test_remove_eiger_versicherungen(self): user1 = User.objects.get(email="test-student1@example.com") @@ -55,7 +55,7 @@ class EdoniqUserExportTestCase(TestCase): def test_export_students_and_trainers(self): users = fetch_course_session_all_users([COURSE_TEST_ID], excluded_domains=[]) - self.assertEqual(len(users), 4) + self.assertEqual(len(users), 5) def test_deduplicates_users(self): trainer1 = User.objects.get(email="test-trainer1@example.com") @@ -67,7 +67,7 @@ class EdoniqUserExportTestCase(TestCase): user=trainer1, ) users = fetch_course_session_all_users([COURSE_TEST_ID], excluded_domains=[]) - self.assertEqual(len(users), 4) + self.assertEqual(len(users), 5) def test_response_csv(self): users = fetch_course_session_users([COURSE_TEST_ID], excluded_domains=[]) diff --git a/server/vbv_lernwelt/notify/email/reminders/attendance.py b/server/vbv_lernwelt/notify/email/reminders/attendance.py index e76f3ba5..e768335d 100644 --- a/server/vbv_lernwelt/notify/email/reminders/attendance.py +++ b/server/vbv_lernwelt/notify/email/reminders/attendance.py @@ -62,8 +62,10 @@ def get_recipients( cs_id = attendance_course.course_session.id circle_page = attendance_course.learning_content.get_parent_circle() circle = Circle.objects.get(page_ptr=circle_page.id) - experts = circle.expert.all() members = CourseSessionUser.objects.filter( course_session_id=cs_id, role=CourseSessionUser.Role.MEMBER ) + experts = CourseSessionUser.objects.filter( + course_session_id=cs_id, role=CourseSessionUser.Role.EXPERT, expert=circle + ) return members | experts