From 11562a3c2e5fc70b5d1442654dfacfd60925ebe6 Mon Sep 17 00:00:00 2001
From: George Katsikas <giorgakis.katsikas@gmail.com>
Date: Fri, 27 Sep 2024 09:07:16 +0200
Subject: [PATCH] type and prevent exceptions in `workdays_between`

---
 scipost_django/common/utils/text.py           |  5 ++-
 .../commands/send_refereeing_reminders.py     | 31 ++++++++++---------
 scipost_django/submissions/views/__init__.py  |  9 ++++--
 3 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/scipost_django/common/utils/text.py b/scipost_django/common/utils/text.py
index fd3106948..13d3295aa 100644
--- a/scipost_django/common/utils/text.py
+++ b/scipost_django/common/utils/text.py
@@ -134,7 +134,10 @@ def hslColorWheel(N=10, index=0, saturation=50, lightness=50):
     return "hsl(%s, %s%%, %s%%)" % (str(hue), str(saturation), str(lightness))
 
 
-def workdays_between(date_from, date_until):
+date_or_time = datetime.datetime | datetime.date
+
+
+def workdays_between(date_from: date_or_time, date_until: date_or_time):
     """Return number of complete workdays.
 
     Given two datetime parameters, this function returns the
diff --git a/scipost_django/submissions/management/commands/send_refereeing_reminders.py b/scipost_django/submissions/management/commands/send_refereeing_reminders.py
index 557d00675..dd9302a39 100644
--- a/scipost_django/submissions/management/commands/send_refereeing_reminders.py
+++ b/scipost_django/submissions/management/commands/send_refereeing_reminders.py
@@ -20,6 +20,7 @@ class Command(BaseCommand):
     help = "Sends all email reminders needed for Submissions undergoing refereeing"
 
     def handle(self, *args, **options):
+        submission: Submission
         for submission in Submission.objects.open_for_reporting():
 
             invitations_w_auto_reminders = (
@@ -34,8 +35,11 @@ class Command(BaseCommand):
                     if invitation.to_registered_referee
                     else "unregistered"
                 )
-                workdays_since_last_reminder = workdays_between(
-                    invitation.date_last_reminded, timezone.now()
+
+                workdays_since_last_reminder = (
+                    workdays_between(invitation.date_last_reminded, timezone.now())
+                    if invitation.date_last_reminded
+                    else 0
                 )
 
                 # Send the appropriate reminder email based on the number of days since the last reminder
@@ -65,15 +69,14 @@ class Command(BaseCommand):
                     mail.send_mail()
 
             # Send automatic reminder that the deadline is approaching (less than one week left)
-            workdays_until_deadline = workdays_between(
-                timezone.now(), submission.reporting_deadline
-            )
-            if (
-                submission.reporting_deadline is not None
-                and workdays_until_deadline == 5
-            ):
-                for invitation in invitations_w_auto_reminders.in_process():
-                    mail_sender = DirectMailUtil(
-                        "referees/remind_referee_deadline_1week", invitation=invitation
-                    )
-                    mail_sender.send_mail()
+            if submission.reporting_deadline is not None:
+                workdays_until_deadline = workdays_between(
+                    timezone.now(), submission.reporting_deadline
+                )
+                if workdays_until_deadline == 5:
+                    for invitation in invitations_w_auto_reminders.in_process():
+                        mail_sender = DirectMailUtil(
+                            "referees/remind_referee_deadline_1week",
+                            invitation=invitation,
+                        )
+                        mail_sender.send_mail()
diff --git a/scipost_django/submissions/views/__init__.py b/scipost_django/submissions/views/__init__.py
index d15da9d64..4873fc90e 100644
--- a/scipost_django/submissions/views/__init__.py
+++ b/scipost_django/submissions/views/__init__.py
@@ -22,7 +22,7 @@ from django.contrib.auth.mixins import (
 from django.contrib.messages.views import SuccessMessageMixin
 from django.core.exceptions import PermissionDenied
 from django.db import transaction, IntegrityError
-from django.db.models import Q, Count, Sum
+from django.db.models import Q, QuerySet
 from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect
 from django.shortcuts import get_object_or_404, get_list_or_404, render, redirect
 from django.template import Template, Context
@@ -3615,7 +3615,7 @@ def submissions_versus_fellows(submissions):
     return sorted(stats, key=lambda tup: tup["ratio"], reverse=True)
 
 
-def submissions_processing_timescales(submissions, phase):
+def submissions_processing_timescales(submissions: QuerySet[Submission], phase):
     """
     Generate a tuple containing information about timescales on submissions.
 
@@ -3639,7 +3639,10 @@ def submissions_processing_timescales(submissions, phase):
                 for sub in submissions_in_spec.all():
                     if phase == "assignment":
                         waiting_days = workdays_between(sub.submission_date, now)
-                    elif phase == "original_submission_to_acceptance":
+                    elif (
+                        phase == "original_submission_to_acceptance"
+                        and sub.acceptance_date
+                    ):
                         waiting_days = workdays_between(
                             sub.original_submission_date, sub.acceptance_date
                         )
-- 
GitLab