SciPost Code Repository

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


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


class FellowshipNomination(models.Model):

    college = models.ForeignKey(
        'colleges.College',
        on_delete=models.PROTECT,
        related_name='nominations'
    )

    profile = models.ForeignKey(
        'profiles.Profile',
        on_delete=models.CASCADE,
        related_name='fellowship_nominations'
    )

    nominated_by = models.ForeignKey(
        'scipost.Contributor',
        on_delete=models.CASCADE,
        related_name='fellowship_nominations_initiated'
    )

    nominated_on = models.DateTimeField(default=timezone.now)

    nominator_comments = models.TextField(
        help_text=('You can use plain text, Markdown or reStructuredText; see our '
                   '<a href="/markup/help/" target="_blank">markup help</a> pages.'),
        blank=True
    )

    fellowship = models.OneToOneField(
        'colleges.Fellowship',
        on_delete=models.CASCADE,
        related_name='nomination',
        blank=True, null=True
    )

    class Meta:
        ordering = [
            'profile',
            'college',
        ]
        verbose_name_plural = 'Fellowship Nominations'

    def __str__(self):
        return (f'{self.profile} to {self.college} '
                f'on {self.nominated_on.strftime("%Y-%m-%d")}')


class FellowshipNominationEvent(models.Model):

    nomination = models.ForeignKey(
        'colleges.FellowshipNomination',
        on_delete=models.CASCADE,
        related_name='events'
    )

    description = models.TextField()

    on = models.DateTimeField(default=timezone.now)

    class Meta:
        ordering = [
            '-on'
            ]
        verbose_name_plural = 'Fellowhip Nomination Events'

    def __str__(self):
        return f'Event for {nomination}'


class FellowshipNominationVotingRound(models.Model):

    nomination = models.ForeignKey(
        'colleges.FellowshipNomination',
        on_delete=models.CASCADE,
        related_name='voting_rounds'
    )

    eligible_to_vote = models.ManyToManyField(
        'colleges.Fellowship',
        related_name='voting_rounds_eligible_to_vote_in',
        blank=True
    )

    voting_opens = models.DateTimeField()

    voting_deadline = models.DateTimeField()

    class Meta:
        ordering = [
            'nomination__profile__last_name'
        ]
        verbose_name_plural = 'Fellowship Nomination Voting Rounds'

    def __str__(self):
        return (f'Voting round ({voting_opens.strftime("%Y-%m-%d")} -'
                f' {voting_deadline.strftime("%Y-%m-%d")}) for {nomination}')


class FellowshipNominationVote(models.Model):

    VOTE_AGREE = 'agree'
    VOTE_ABSTAIN = 'abstain'
    VOTE_DISAGREE = 'disagree'
    VOTE_CHOICES = (
        (VOTE_AGREE, 'Agree'),
        (VOTE_ABSTAIN, 'Abstain'),
        (VOTE_DISAGREE, 'Disagree')
    )

    voting_round = models.ForeignKey(
        'colleges.FellowshipNominationVotingRound',
        on_delete=models.CASCADE,
        related_name='votes'
    )

    fellow = models.ForeignKey(
        'colleges.Fellowship',
        on_delete=models.CASCADE,
        related_name='fellowship_nomination_votes'
    )

    vote = models.CharField(
        max_length=16,
        choices=VOTE_CHOICES
    )

    on = models.DateTimeField(blank=True, null=True)

    comments = models.TextField(
        help_text=('You can use plain text, Markdown or reStructuredText; see our '
                   '<a href="/markup/help/" target="_blank">markup help</a> pages.'),
        blank=True
    )

    class Meta:
        ordering = ['voting_round',]
        verbose_name_plural = 'Fellowship Nomination Votes'


class FellowshipNominationDecision(models.Model):

    nomination = models.OneToOneField(
        'colleges.FellowshipNomination',
        on_delete=models.CASCADE,
        related_name='decision'
    )

    OUTCOME_ELECTED = 'elected'
    OUTCOME_NOT_ELECTED = 'notelected'
    OUTCOME_CHOICES = (
        (OUTCOME_ELECTED, 'Elected'),
        (OUTCOME_NOT_ELECTED, 'Not elected')
    )
    outcome = models.CharField(
        max_length=16,
        choices=OUTCOME_CHOICES
    )

    fixed_on = models.DateTimeField(default=timezone.now)

    comments = models.TextField(
        help_text=('You can use plain text, Markdown or reStructuredText; see our '
                   '<a href="/markup/help/" target="_blank">markup help</a> pages.'),
        blank=True
    )

    class Meta:
        ordering = ['nomination',]
        verbose_name_plural = 'Fellowship Nomination Decisions'

    def __str__(self):
        return f'Decision for {nomination}: {self.get_outcome_display()}'

    @property
    def elected(self):
        return self.outcome == self.OUTCOME_ELECTED


class FellowshipInvitation(models.Model):

    nomination = models.OneToOneField(
        'colleges.FellowshipNomination',
        on_delete=models.CASCADE,
        related_name='invitation'
    )

    invited_on = models.DateTimeField(blank=True, null=True)

    RESPONSE_NOT_YET_INVITED = 'notyetinvited'
    RESPONSE_INVITED = 'invited'
    RESPONSE_REINVITED = 'reinvited'
    RESPONSE_MULTIPLY_REINVITED = 'multireinvited'
    RESPONSE_UNRESPONSIVE = 'unresponsive'
    RESPONSE_ACCEPTED = 'accepted'
    RESPONSE_POSTPONED = 'postponed'
    RESPONSE_DECLINED = 'declined'
    RESPONSE_CHOICES = (
        (RESPONSE_NOT_YET_INVITED, 'Not yet invited'),
        (RESPONSE_INVITED, 'Invited'),
        (RESPONSE_REINVITED, 'Reinvited'),
        (RESPONSE_MULTIPLY_REINVITED, 'Multiply reinvited'),
        (RESPONSE_UNRESPONSIVE, 'Unresponsive'),
        (RESPONSE_ACCEPTED, 'Accepted, for immediate start'),
        (RESPONSE_POSTPONED, 'Accepted, but start date postponed'),
        (RESPONSE_DECLINED, 'Declined')
    )
    response = models.CharField(
        max_length=16,
        choices=RESPONSE_CHOICES,
        blank=True
    )

    postpone_start_to = models.DateField(blank=True)

    comments = models.TextField(
        help_text=('You can use plain text, Markdown or reStructuredText; see our '
                   '<a href="/markup/help/" target="_blank">markup help</a> pages.'),
        blank=True
    )

    class Meta:
        ordering = ['nomination',]
        verbose_name_plural = 'Fellowship Invitations'

    def __str__(self):
        return f'Invitation for {nomination}'

    @property
    def declined(self):
        return self.response == self.RESPONSE_DECLINED