-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added functionality to email certificate.
Unit test is pending
- Loading branch information
Showing
4 changed files
with
123 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
from .certificate import Certificate | ||
from .quiz import QuizService |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,50 @@ | ||
from training.errors import IncompleteQuizResponseError, QuizNotFoundError | ||
from training.repositories import QuizRepository, QuizCompletionRepository | ||
import logging | ||
from email.message import EmailMessage | ||
from smtplib import SMTP | ||
from string import Template | ||
|
||
from fastapi import HTTPException, status | ||
|
||
from training.config import settings | ||
from training.errors import IncompleteQuizResponseError, QuizNotFoundError, SendEmailError | ||
from training.repositories import QuizRepository, QuizCompletionRepository, UserRepository, CertificateRepository | ||
from training.schemas import Quiz, QuizSubmission, QuizGrade, QuizCompletionCreate | ||
from sqlalchemy.orm import Session | ||
|
||
from training.services import Certificate | ||
|
||
CERTIFICATE_EMAIL_TEMPLATE = Template(''' | ||
<p>Hello $name,</p> | ||
<p> | ||
Congratulations! | ||
</p> | ||
<p>You've successfully passed the quiz for the $course_name.</p> | ||
<p>Your certificate is attached below.</p> | ||
<p> | ||
If you have any questions or need further assistance, | ||
email us at [email protected]. | ||
</p> | ||
<p>Thank you.</p> | ||
''') | ||
|
||
|
||
class QuizService(): | ||
def __init__(self, db: Session): | ||
self.quiz_repo = QuizRepository(db) | ||
self.quiz_completion_repo = QuizCompletionRepository(db) | ||
self.user_repo = UserRepository(db) | ||
self.certificate_repo = CertificateRepository(db) | ||
self.certificate_service = Certificate() | ||
|
||
def grade(self, quiz_id: int, user_id: int, submission: QuizSubmission) -> QuizGrade: | ||
""" | ||
Grades quizzes submitted by user. Sends congratulation email if user passes the quiz. | ||
:param quiz_id: Quiz ID | ||
:param user_id: User ID | ||
:param submission: Quiz submission object | ||
:return: QuizGrade model which includes quiz results | ||
""" | ||
db_quiz = self.quiz_repo.find_by_id(quiz_id) | ||
if db_quiz is None: | ||
raise QuizNotFoundError | ||
|
@@ -72,4 +107,52 @@ def grade(self, quiz_id: int, user_id: int, submission: QuizSubmission) -> QuizG | |
|
||
grade.quiz_completion_id = result.id | ||
|
||
if passed: | ||
# Send email with quizz completion attached | ||
try: | ||
user = self.user_repo.find_by_id(user_id) | ||
db_user_certificate = self.certificate_repo.get_certificate_by_id(result.id) | ||
pdf_bytes = self.certificate_service.generate_pdf( | ||
db_user_certificate.quiz_name, | ||
db_user_certificate.user_name, | ||
db_user_certificate.agency, | ||
db_user_certificate.completion_date | ||
) | ||
self.emailCertificate(user.name, quiz.name, user.email, pdf_bytes) | ||
logging.info(f"Sent confirmation email to {user.email} for passing training quiz") | ||
except Exception as e: | ||
logging.error("Error sending quiz confirmation mail", e) | ||
raise HTTPException( | ||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | ||
detail="Server Error" | ||
) | ||
|
||
return grade | ||
|
||
def emailCertificate(self, user_name: str, course_name: str, to_email: str, certificate: bytes) -> None: | ||
""" | ||
Sends congratulatory email to user with certificate attached. | ||
:param user_name: User's Name | ||
:param course_name: Name of course user completed | ||
:param to_email: User's email | ||
:param certificate: Certificate PDF file | ||
:return: N/A | ||
""" | ||
body = CERTIFICATE_EMAIL_TEMPLATE.substitute({"name": user_name, "course_name": course_name}) | ||
message = EmailMessage() | ||
message.set_content(body, subtype="html") | ||
message["Subject"] = "Certificate - " + course_name | ||
message["From"] = f"{settings.EMAIL_FROM_NAME} <{settings.EMAIL_FROM}>" | ||
message["To"] = to_email | ||
message.add_attachment(certificate, maintype="application", subtype="pdf", filename="SmartPayTraining.pdf") | ||
|
||
with SMTP(settings.SMTP_SERVER, port=settings.SMTP_PORT) as smtp: | ||
smtp.starttls() | ||
if settings.SMTP_USER and settings.SMTP_PASSWORD: | ||
smtp.login(user=settings.SMTP_USER, password=settings.SMTP_PASSWORD) | ||
try: | ||
smtp.send_message(message) | ||
except Exception as e: | ||
raise SendEmailError from e | ||
finally: | ||
smtp.quit() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters