Merged in feature/VBV-567-reminder-email (pull request #226)
Send reminders only to related experts Approved-by: Daniel Egger
This commit is contained in:
commit
9a52d7e34f
|
|
@ -19,6 +19,7 @@ DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER = [
|
||||||
# ids for cypress test data
|
# ids for cypress test data
|
||||||
ADMIN_USER_ID = "872efd96-3bd7-4a1e-a239-2d72cad9f604"
|
ADMIN_USER_ID = "872efd96-3bd7-4a1e-a239-2d72cad9f604"
|
||||||
TEST_TRAINER1_USER_ID = "b9e71f59-c44f-4290-b93a-9b3151e9a2fc"
|
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_STUDENT1_USER_ID = "65c73ad0-6d53-43a9-a4a4-64143f27b03a"
|
||||||
TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900"
|
TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900"
|
||||||
TEST_STUDENT3_USER_ID = "bcf94dba-53bc-474b-a22d-e4af39aa042b"
|
TEST_STUDENT3_USER_ID = "bcf94dba-53bc-474b-a22d-e4af39aa042b"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from vbv_lernwelt.core.constants import (
|
||||||
TEST_STUDENT2_USER_ID,
|
TEST_STUDENT2_USER_ID,
|
||||||
TEST_STUDENT3_USER_ID,
|
TEST_STUDENT3_USER_ID,
|
||||||
TEST_TRAINER1_USER_ID,
|
TEST_TRAINER1_USER_ID,
|
||||||
|
TEST_TRAINER2_USER_ID,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.core.models import User
|
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",
|
last_name="Trainer1",
|
||||||
avatar_url="/static/avatars/uk1.patrizia.huggel.jpg",
|
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(
|
_create_student_user(
|
||||||
id=TEST_STUDENT1_USER_ID,
|
id=TEST_STUDENT1_USER_ID,
|
||||||
email="test-student1@example.com",
|
email="test-student1@example.com",
|
||||||
|
|
|
||||||
|
|
@ -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"))
|
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")
|
student1 = User.objects.get(email="test-student1@example.com")
|
||||||
_csu = CourseSessionUser.objects.create(
|
_csu = CourseSessionUser.objects.create(
|
||||||
course_session=cs_bern,
|
course_session=cs_bern,
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,23 @@ from django.test import TestCase
|
||||||
from vbv_lernwelt.core.constants import TEST_STUDENT1_USER_ID
|
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.create_default_users import create_default_users
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.creators.test_course import create_test_course
|
from vbv_lernwelt.course.creators.test_course import (
|
||||||
from vbv_lernwelt.course.models import CourseCompletion, CourseSession
|
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.services import mark_course_completion
|
||||||
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
from vbv_lernwelt.course_session.services.attendance import (
|
from vbv_lernwelt.course_session.services.attendance import (
|
||||||
AttendanceUserStatus,
|
AttendanceUserStatus,
|
||||||
update_attendance_list,
|
update_attendance_list,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.learnpath.models import Circle, LearningPath
|
||||||
|
from vbv_lernwelt.notify.email.reminders.attendance import get_recipients
|
||||||
|
|
||||||
|
|
||||||
class AttendanceServicesTestCase(TestCase):
|
class AttendanceServicesTestCase(TestCase):
|
||||||
|
|
@ -88,3 +97,36 @@ class AttendanceServicesTestCase(TestCase):
|
||||||
self.assertEqual(cc.user, student)
|
self.assertEqual(cc.user, student)
|
||||||
self.assertEqual(cc.completion_status, "FAIL")
|
self.assertEqual(cc.completion_status, "FAIL")
|
||||||
self.assertEqual(cc.page_id, self.attendance_course.learning_content.id)
|
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)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class EdoniqUserExportTestCase(TestCase):
|
||||||
users = fetch_course_session_users(
|
users = fetch_course_session_users(
|
||||||
[COURSE_TEST_ID], role=CourseSessionUser.Role.EXPERT, excluded_domains=[]
|
[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):
|
def test_remove_eiger_versicherungen(self):
|
||||||
user1 = User.objects.get(email="test-student1@example.com")
|
user1 = User.objects.get(email="test-student1@example.com")
|
||||||
|
|
@ -55,7 +55,7 @@ class EdoniqUserExportTestCase(TestCase):
|
||||||
|
|
||||||
def test_export_students_and_trainers(self):
|
def test_export_students_and_trainers(self):
|
||||||
users = fetch_course_session_all_users([COURSE_TEST_ID], excluded_domains=[])
|
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):
|
def test_deduplicates_users(self):
|
||||||
trainer1 = User.objects.get(email="test-trainer1@example.com")
|
trainer1 = User.objects.get(email="test-trainer1@example.com")
|
||||||
|
|
@ -67,7 +67,7 @@ class EdoniqUserExportTestCase(TestCase):
|
||||||
user=trainer1,
|
user=trainer1,
|
||||||
)
|
)
|
||||||
users = fetch_course_session_all_users([COURSE_TEST_ID], excluded_domains=[])
|
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):
|
def test_response_csv(self):
|
||||||
users = fetch_course_session_users([COURSE_TEST_ID], excluded_domains=[])
|
users = fetch_course_session_users([COURSE_TEST_ID], excluded_domains=[])
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ from collections import Counter
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
|
from django.db.models import QuerySet
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSessionUser
|
||||||
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
|
from vbv_lernwelt.learnpath.models import Circle
|
||||||
from vbv_lernwelt.notify.services import NotificationService
|
from vbv_lernwelt.notify.services import NotificationService
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
@ -32,7 +34,7 @@ def send_attendance_reminder_notifications():
|
||||||
)
|
)
|
||||||
for attendance_course in attendance_courses:
|
for attendance_course in attendance_courses:
|
||||||
cs_id = attendance_course.course_session.id
|
cs_id = attendance_course.course_session.id
|
||||||
csu = CourseSessionUser.objects.filter(course_session_id=cs_id)
|
csu = get_recipients(attendance_course)
|
||||||
logger.info(
|
logger.info(
|
||||||
"Sending attendance course reminder notification",
|
"Sending attendance course reminder notification",
|
||||||
start_time=start.isoformat(),
|
start_time=start.isoformat(),
|
||||||
|
|
@ -52,3 +54,18 @@ def send_attendance_reminder_notifications():
|
||||||
label="attendance_course_reminder_notification_job",
|
label="attendance_course_reminder_notification_job",
|
||||||
)
|
)
|
||||||
return dict(results_counter)
|
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)
|
||||||
|
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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue