From f5d5a10659801e9637cd173d4306cd011ff2afb2 Mon Sep 17 00:00:00 2001 From: George Katsikas <giorgakis.katsikas@gmail.com> Date: Thu, 1 Aug 2024 13:28:36 +0200 Subject: [PATCH] refactor submission communications --- scipost_django/submissions/utils.py | 102 +++++++++++-------- scipost_django/submissions/views/__init__.py | 13 ++- 2 files changed, 71 insertions(+), 44 deletions(-) diff --git a/scipost_django/submissions/utils.py b/scipost_django/submissions/utils.py index 69a3d8a81..2a32fc9e7 100644 --- a/scipost_django/submissions/utils.py +++ b/scipost_django/submissions/utils.py @@ -3,8 +3,11 @@ __license__ = "AGPL v3" import datetime +import itertools import os +import re import subprocess +from typing import TYPE_CHECKING from django.core.mail import EmailMessage, EmailMultiAlternatives from django.template import Context, Template @@ -23,6 +26,11 @@ from common.utils import get_current_domain, BaseMailUtil domain = get_current_domain() +if TYPE_CHECKING: + from submissions.models.communication import EditorialCommunication + from scipost.models import Contributor + + class SubmissionUtils(BaseMailUtil): mail_sender = f"submissions@{domain}" mail_sender_title = "SciPost Editorial Admin" @@ -716,51 +724,60 @@ class SubmissionUtils(BaseMailUtil): recipient_email = [] bcc_emails = [] further_action_page = None - if cls.communication.comtype in ["AtoE", "RtoE", "StoE"]: - recipient_email.append( - cls.communication.submission.editor_in_charge.user.email - ) - recipient_greeting = ( - "Dear " - + cls.communication.submission.editor_in_charge.profile.get_title_display() - + " " - + cls.communication.submission.editor_in_charge.user.last_name - ) - further_action_page = ( - f"https://{domain}/submission/editorial_page/" - + cls.communication.submission.preprint.identifier_w_vn_nr - ) - if cls.communication.comtype == "RtoE": - bcc_emails.append(cls.communication.referee.user.email) - bcc_emails.append(f"submissions@{domain}") - elif cls.communication.comtype in ["EtoA"]: - recipient_email.append(cls.communication.submission.submitted_by.user.email) - recipient_greeting = ( - "Dear " - + cls.communication.submission.submitted_by.profile.get_title_display() - + " " - + cls.communication.submission.submitted_by.user.last_name - ) - bcc_emails.append(cls.communication.submission.editor_in_charge.user.email) - bcc_emails.append(f"submissions@{domain}") - elif cls.communication.comtype in ["EtoR"]: - recipient_email.append(cls.communication.referee.user.email) - recipient_greeting = ( - "Dear " - + cls.communication.referee.profile.get_title_display() - + " " - + cls.communication.referee.user.last_name + + PARTIES = ["E", "A", "R", "S"] + # Allow only comtype to and from E(ditor) + valid_comtypes = [ + f"{x}to{y}" + for x, y in itertools.product(PARTIES, repeat=2) + if "E" in [x, y] and x != y + ] + + communication: "EditorialCommunication | None" = getattr( + cls, "communication", None + ) + if communication is None: + raise ValueError("No communication attribute found. Please `.load()` it.") + + if communication.comtype not in valid_comtypes: + raise ValueError( + f"Invalid comtype {communication.comtype}. " + f"Valid comtypes are {valid_comtypes}." ) - bcc_emails.append(cls.communication.submission.editor_in_charge.user.email) + + recipients: dict[str, "Contributor | None"] = { + "E": communication.submission.editor_in_charge, + "A": communication.submission.submitted_by, + "R": communication.referee, + } + + author, recipient = re.match(r"(\w)to(\w)", communication.comtype).groups() + + # Use standard greeting for all communications except to Editorial Administrator + if recipient != "S": + recipient_contributor = recipients.get(recipient, None) + if recipient_contributor is None: + raise ValueError( + f"Recipient not found for comtype {communication.comtype}. Must be one of {recipients.keys()}" + ) + + recipient_email.append(recipient_contributor.user.email) + recipient_greeting = f"Dear {recipient_contributor.profile_title} {recipient_contributor.user.last_name}" + + # BCC all non-edadmin communications to the Editorial Administrator bcc_emails.append(f"submissions@{domain}") - elif cls.communication.comtype in ["EtoS"]: + else: + # Communication to Editorial Administrator doesn't have a specific recipient contributor recipient_email.append(f"submissions@{domain}") recipient_greeting = "Dear Editorial Administrators" - bcc_emails.append(cls.communication.submission.editor_in_charge.user.email) - further_action_page = ( - f"https://{domain}/submission/editorial_page/" - + cls.communication.submission.preprint.identifier_w_vn_nr - ) + + # BCC all editor-authored communications to the Editor-in-charge + if author == "E": + bcc_emails.append(communication.submission.editor_in_charge.user.email) + + # Further action page for Editor and Editorial Administrator + if recipient in ["E", "S"]: # EtoS and StoE + further_action_page = f"https://{domain}/submission/editorial_page/{communication.submission.preprint.identifier_w_vn_nr}" email_text = ( recipient_greeting @@ -784,8 +801,9 @@ class SubmissionUtils(BaseMailUtil): "\n\nWe thank you very much for your contribution." "\n\nSincerely," + "\n\nThe SciPost Team." ) + emailmessage = EmailMessage( - "SciPost: communication (" + cls.communication.get_comtype_display() + ")", + "SciPost: communication (" + communication.get_comtype_display() + ")", email_text, f"SciPost Editorial Admin <submissions@{domain}>", recipient_email, diff --git a/scipost_django/submissions/views/__init__.py b/scipost_django/submissions/views/__init__.py index f7d7fcad5..91f826228 100644 --- a/scipost_django/submissions/views/__init__.py +++ b/scipost_django/submissions/views/__init__.py @@ -34,6 +34,7 @@ from django.views.generic.edit import CreateView, UpdateView from django.views.generic.list import ListView from dal import autocomplete +import sentry_sdk from scipost.permissions import ( HTMXPermissionsDenied, @@ -2077,8 +2078,16 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): communication.referee = referee communication.save() - SubmissionUtils.load({"communication": communication}) - SubmissionUtils.send_communication_email() + try: + SubmissionUtils.load({"communication": communication}) + SubmissionUtils.send_communication_email() + except Exception as e: + messages.error( + request, + "Communication submitted, but an error occurred while sending the email: " + str(e), + ) + sentry_sdk.capture_exception(e) + return redirect(submission.get_absolute_url()) messages.success(request, "Communication submitted") if comtype in ["EtoA", "EtoR", "EtoS"]: -- GitLab