Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: move student join request emails #2294

Merged
merged 10 commits into from
May 2, 2024
33 changes: 0 additions & 33 deletions cfl_common/common/email_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,6 @@ def kickedEmail(request, schoolName):
}


def studentJoinRequestSentEmail(request, schoolName, accessCode):
return {
"subject": f"School or club join request sent",
"message": (
f"Your request to join the school or club '{schoolName}' in class "
f"{accessCode} has been sent to that class's teacher, who will either "
f"accept or deny your request."
),
}


def studentJoinRequestNotifyEmail(request, username, email, accessCode):
return {
"subject": f"School or club join request",
"message": (
f"There is a request waiting from student with username '{username}' and "
f"email {email} to join your class {accessCode}. "
f"Please log in to your dashboard to review the request."
),
}


def studentJoinRequestRejectedEmail(request, schoolName, accessCode):
return {
"subject": f"School or club join request rejected",
"message": (
f"Your request to join the school or club '{schoolName}' in class "
f"{accessCode} has been rejected. Speak to your teacher if you think this "
f"is an error."
),
}


def inviteTeacherEmail(request, schoolName, token, account_exists):
url = f"{request.build_absolute_uri(reverse('invited_teacher', kwargs={'token': token}))} "

Expand Down
3 changes: 3 additions & 0 deletions cfl_common/common/mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"email_change_notification": 1551600,
"email_change_verification": 1551594,
"reset_password": 1557153,
"student_join_request_notification": 1569486,
"student_join_request_rejected": 1569470,
"student_join_request_sent": 1569477,
"verify_new_user": 1551577,
"verify_new_user_first_reminder": 1557170,
"verify_new_user_second_reminder": 1557173,
Expand Down
77 changes: 25 additions & 52 deletions portal/views/student/play.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from common import email_messages
from common.helpers.emails import NOTIFICATION_EMAIL, send_email
from common.mail import campaign_ids, send_dotdigital_email
from common.models import Student
from common.permissions import (
logged_in_as_independent_student,
Expand All @@ -22,9 +23,7 @@
from portal.forms.play import StudentJoinOrganisationForm


class SchoolStudentDashboard(
LoginRequiredNoErrorMixin, UserPassesTestMixin, TemplateView
):
class SchoolStudentDashboard(LoginRequiredNoErrorMixin, UserPassesTestMixin, TemplateView):
template_name = "portal/play/student_dashboard.html"
login_url = reverse_lazy("student_login_access_code")

Expand All @@ -50,16 +49,10 @@ def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
custom_levels = student.new_user.shared.filter(owner=teacher)

if custom_levels:
custom_levels_data = _compute_rapid_router_scores(
student, custom_levels
)
custom_levels_data = _compute_rapid_router_scores(student, custom_levels)

context_data["total_custom_score"] = custom_levels_data[
"total_score"
]
context_data["total_custom_available_score"] = custom_levels_data[
"total_available_score"
]
context_data["total_custom_score"] = custom_levels_data["total_score"]
context_data["total_custom_available_score"] = custom_levels_data["total_available_score"]

# Get Kurono game info if the class has a game linked to it
aimmo_game = klass.active_game
Expand All @@ -72,9 +65,7 @@ def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
return context_data


class IndependentStudentDashboard(
LoginRequiredNoErrorMixin, UserPassesTestMixin, TemplateView, FormView
):
class IndependentStudentDashboard(LoginRequiredNoErrorMixin, UserPassesTestMixin, TemplateView, FormView):
template_name = "portal/play/independent_student_dashboard.html"
login_url = reverse_lazy("independent_student_login")

Expand All @@ -91,9 +82,7 @@ def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
)


def _compute_rapid_router_scores(
student: Student, levels: List[Level] or QuerySet
) -> Dict[str, int]:
def _compute_rapid_router_scores(student: Student, levels: List[Level] or QuerySet) -> Dict[str, int]:
"""
Finds Rapid Router progress and score data for a specific student and a specific
set of levels. This is used to show quick score data to the student on their
Expand All @@ -112,20 +101,17 @@ def _compute_rapid_router_scores(
num_completed = num_top_scores = total_available_score = 0
total_score = 0.0
# Get a QuerySet of best attempts for each level
best_attempts = Attempt.objects.filter(
level__in=levels, student=student, is_best_attempt=True
).select_related("level")
best_attempts = Attempt.objects.filter(level__in=levels, student=student, is_best_attempt=True).select_related(
"level"
)

for level in levels:
total_available_score += _get_max_score_for_level(level)

# For each level, compare best attempt's score with level's max score and
# increment variables as needed
if best_attempts:
attempts_dict = {
best_attempt.level.id: best_attempt
for best_attempt in best_attempts
}
attempts_dict = {best_attempt.level.id: best_attempt for best_attempt in best_attempts}
for level in levels:
attempt = attempts_dict.get(level.id)

Expand Down Expand Up @@ -155,12 +141,7 @@ def _get_max_score_for_level(level: Level) -> int:
"""
return (
10
if level.id > 12
and (
level.disable_route_score
or level.disable_algorithm_score
or not level.episode
)
if level.id > 12 and (level.disable_route_score or level.disable_algorithm_score or not level.episode)
else 20
)

Expand Down Expand Up @@ -207,31 +188,23 @@ def process_join_organisation_form(request_form, request, student):
student.pending_class_request = request_form.klass
student.save()

email_message = email_messages.studentJoinRequestSentEmail(
request,
request_form.klass.teacher.school.name,
request_form.klass.access_code,
)
send_email(
NOTIFICATION_EMAIL,
send_dotdigital_email(
campaign_ids["student_join_request_sent"],
[student.new_user.email],
email_message["subject"],
email_message["message"],
email_message["subject"],
personalization_values={
"SCHOOL_CLUB_NAME": request_form.klass.teacher.school.name,
"ACCESS_CODE": request_form.klass.access_code,
},
)

email_message = email_messages.studentJoinRequestNotifyEmail(
request,
student.new_user.username,
student.new_user.email,
student.pending_class_request.access_code,
)
send_email(
NOTIFICATION_EMAIL,
send_dotdigital_email(
campaign_ids["student_join_request_notification"],
[student.pending_class_request.teacher.new_user.email],
email_message["subject"],
email_message["message"],
email_message["subject"],
personalization_values={
"USERNAME": student.new_user.username,
"EMAIL": student.new_user.email,
"ACCESS_CODE": student.pending_class_request.access_code,
},
)

messages.success(
Expand Down
14 changes: 6 additions & 8 deletions portal/views/teacher/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,15 +537,13 @@ def teacher_reject_student_request(request, pk):

check_student_request_can_be_handled(request, student)

emailMessage = email_messages.studentJoinRequestRejectedEmail(
request, student.pending_class_request.teacher.school.name, student.pending_class_request.access_code
)
send_email(
NOTIFICATION_EMAIL,
send_dotdigital_email(
campaign_ids["student_join_request_rejected"],
[student.new_user.email],
emailMessage["subject"],
emailMessage["message"],
emailMessage["subject"],
personalization_values={
"SCHOOL_CLUB_NAME": student.pending_class_request.teacher.school.name,
"ACCESS_CODE": student.pending_class_request.access_code,
},
)

student.pending_class_request = None
Expand Down
Loading