SciPost Code Repository

Skip to content
Snippets Groups Projects
assignment.py 4.95 KiB
Newer Older
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


from django.db import models
from django.urls import reverse
from django.utils import timezone

from mails.utils import DirectMailUtil

from ..behaviors import SubmissionRelatedObjectMixin
from ..managers import EditorialAssignmentQuerySet


class EditorialAssignment(SubmissionRelatedObjectMixin, models.Model):
    """
    Consideration of a Fellow to become Editor-in-Charge of a Submission.
    """

    REFUSE_OUTSIDE_EXPERTISE = "OFE"
    REFUSE_TOO_BUSY = "BUS"
    REFUSE_ON_VACATION = "VAC"
    REFUSE_COI_COAUTHOR = "COI"
    REFUSE_COI_COLLEAGUE = "CCC"
    REFUSE_COI_COMPETITOR = "CCM"
    REFUSE_COI_OTHER = "COT"
    REFUSE_NOT_IMPARTIAL = "NIR"
    REFUSE_NOT_INTERESTED = "NIE"
    REFUSE_DESK_REJECT = "DNP"
    REFUSAL_REASONS = (
        (REFUSE_OUTSIDE_EXPERTISE, "Outside of my field of expertise"),
        (REFUSE_TOO_BUSY, "Too busy"),
        (REFUSE_ON_VACATION, "Away on vacation"),
        (REFUSE_COI_COAUTHOR, "Conflict of interest: coauthor in last 5 years"),
        (REFUSE_COI_COLLEAGUE, "Conflict of interest: close colleague"),
        (REFUSE_COI_COMPETITOR, "Conflict of interest: close competitor"),
        (REFUSE_COI_OTHER, "Conflict of interest: other"),
        (REFUSE_NOT_IMPARTIAL, "Cannot give an impartial assessment"),
        (REFUSE_NOT_INTERESTED, "Not interested enough"),
        (
            REFUSE_DESK_REJECT,
            "SciPost should desk reject this paper",
        ),
    )

    STATUS_PREASSIGNED = "preassigned"
    STATUS_INVITED = "invited"
    STATUS_ACCEPTED = "accepted"
    STATUS_ACCEPT_IF_NOBODY_ELSE = "accifnobodyelse"
    STATUS_ACCEPT_IF_TRANSFERRED = "acciftransferred"
    STATUS_PERHAPS_LATER = "askagainlater"
    STATUS_DECLINED = "declined"
    STATUS_COMPLETED = "completed"
    STATUS_DEPRECATED = "deprecated"
    STATUS_REPLACED = "replaced"
    ASSIGNMENT_STATUSES = (
        (STATUS_PREASSIGNED, "Preassigned"),
        (STATUS_INVITED, "Invited"),
        (STATUS_ACCEPTED, "Accepted"),
        (STATUS_ACCEPT_IF_NOBODY_ELSE, "Accept (if nobody else does)"),
        (
            STATUS_ACCEPT_IF_TRANSFERRED,
            "Accept (if transferred to non-flagship journal)",
        ),
        (STATUS_PERHAPS_LATER, "Perhaps; ask again later"),
        (STATUS_DECLINED, "Declined"),
        (STATUS_COMPLETED, "Completed"),
        (STATUS_DEPRECATED, "Deprecated"),
        (STATUS_REPLACED, "Replaced"),
    )

    submission = models.ForeignKey(
        "submissions.Submission",
        on_delete=models.CASCADE,
    )
    to = models.ForeignKey("scipost.Contributor", on_delete=models.CASCADE)
        max_length=16, choices=ASSIGNMENT_STATUSES, default=STATUS_PREASSIGNED
    )
    refusal_reason = models.CharField(
        max_length=3, choices=REFUSAL_REASONS, blank=True, null=True
    invitation_order = models.PositiveSmallIntegerField(default=0)

    date_created = models.DateTimeField(default=timezone.now)
    date_invited = models.DateTimeField(blank=True, null=True)
    date_answered = models.DateTimeField(blank=True, null=True)

    objects = EditorialAssignmentQuerySet.as_manager()

    class Meta:
        default_related_name = "editorial_assignments"
        ordering = ["-date_created"]
Jean-Sébastien Caux's avatar
Jean-Sébastien Caux committed
        """Summarize the EditorialAssignment's basic information."""
        return (
            self.to.user.first_name
            + " "
            + self.to.user.last_name
            + " to become EIC of "
            + self.submission.title[:30]
            + " by "
            + self.submission.author_list[:30]
            + ", requested on "
            + self.date_created.strftime("%Y-%m-%d")
        )

    def get_absolute_url(self):
        """Return the url of the assignment's processing page."""
        return reverse("submissions:pool:assignment_request", args=(self.id,))
        return self.status == self.STATUS_PREASSIGNED
        return self.status == self.STATUS_INVITED
        return self.status == self.STATUS_REPLACED
        return self.status == self.STATUS_ACCEPTED
        return self.status == self.STATUS_DEPRECATED
        return self.status == self.STATUS_COMPLETED

    def send_invitation(self):
        """Send invitation and update status."""
        if self.status != self.STATUS_PREASSIGNED:
            # Only send if status is appropriate to prevent double sending
            return False

        # Send mail
        mail_sender = DirectMailUtil(
            mail_code="eic/assignment_request", assignment=self
        )
        EditorialAssignment.objects.filter(id=self.id).update(
            date_invited=timezone.now(), status=self.STATUS_INVITED