__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
from django.db import models
from django.db.models import Q
from django.utils import timezone
from .constants import POTENTIAL_FELLOWSHIP_ELECTION_VOTE_ONGOING
[docs]class FellowQuerySet(models.QuerySet):
[docs] def guests(self):
from .models import Fellowship
return self.filter(status=Fellowship.STATUS_GUEST)
[docs] def regular(self):
from .models import Fellowship
return self.filter(status=Fellowship.STATUS_REGULAR)
[docs] def senior(self):
from .models import Fellowship
return self.filter(status=Fellowship.STATUS_SENIOR)
[docs] def regular_or_senior(self):
from .models import Fellowship
return self.filter(
Q(status=Fellowship.STATUS_REGULAR) | Q(status=Fellowship.STATUS_SENIOR)
)
[docs] def active(self):
today = timezone.now().date()
return self.filter(
Q(start_date__lte=today, until_date__isnull=True)
| Q(start_date__isnull=True, until_date__gte=today)
| Q(start_date__lte=today, until_date__gte=today)
| Q(start_date__isnull=True, until_date__isnull=True)
).ordered()
[docs] def active_in_year(self, year):
"""
Filter for Fellows which were active during a certain calendar year.
"""
return self.filter(start_date__year__lte=year, until_date__year__gte=year)
[docs] def specialties_overlap(self, specialties_slug_list):
"""
Returns all Fellows whose specialties overlap with those specified in the slug list.
This method is also separately implemented for Contributor and Profile objects.
"""
return self.filter(
contributor__profile__specialties__slug__in=specialties_slug_list
)
[docs] def ordered(self):
"""Return ordered queryset explicitly, since this may have big effect on performance."""
return self.order_by("contributor__user__last_name")
[docs] def return_active_for_submission(self, submission):
"""
This method returns a *list* of Fellowships that passed the 'author-check' for
a specific submission.
"""
try:
qs = self.exclude(contributor__in=submission.authors.all()).active()
false_claims = submission.authors_false_claims.all()
author_list = submission.author_list.lower()
fellowships = []
for fellowship in qs:
if (
fellowship.contributor.user.last_name.lower() in author_list
and fellowship.contributor not in false_claims
):
continue
fellowships.append(fellowship)
return fellowships
except AttributeError:
return []
[docs]class PotentialFellowshipQuerySet(models.QuerySet):
[docs] def vote_needed(self, contributor):
college_id_list = [
f.college.id for f in contributor.fellowships.senior().active()
]
return (
self.filter(
college__pk__in=college_id_list,
status=POTENTIAL_FELLOWSHIP_ELECTION_VOTE_ONGOING,
)
.distinct()
.order_by("profile__last_name")
)
[docs] def to_vote_on(self, contributor):
return self.vote_needed(contributor).exclude(
Q(in_agreement__in=[contributor])
| Q(in_abstain__in=[contributor])
| Q(in_disagreement__in=[contributor])
)
[docs] def voted_on(self, contributor):
return self.vote_needed(contributor).filter(
Q(in_agreement__in=[contributor])
| Q(in_abstain__in=[contributor])
| Q(in_disagreement__in=[contributor])
)
[docs]class FellowshipNominationQuerySet(models.QuerySet):
[docs] def needing_handling(self):
return self.exclude(
decision__isnull=False
).exclude(
voting_rounds__isnull=False
)
[docs]class FellowshipNominationVotingRoundQuerySet(models.QuerySet):
[docs] def ongoing(self):
now = timezone.now()
return self.filter(voting_opens__lte=now, voting_deadline__gte=now)
[docs] def closed(self):
now = timezone.now()
return self.filter(voting_deadline__lte=now)
[docs]class FellowshipNominationVoteQuerySet(models.QuerySet):
[docs] def agree(self):
return self.filter(vote=self.model.VOTE_AGREE)
[docs] def abstain(self):
return self.filter(vote=self.model.VOTE_ABSTAIN)
[docs] def disagree(self):
return self.filter(vote=self.model.VOTE_DISAGREE)