Source code for scipost.managers

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


from django.db import models
from django.db.models import Count, Q
from django.db.models.functions import Concat, Lower
from django.utils import timezone

from .constants import (
    NORMAL_CONTRIBUTOR,
    NEWLY_REGISTERED,
    DOUBLE_ACCOUNT,
    AUTHORSHIP_CLAIM_PENDING,
)


[docs]class ContributorQuerySet(models.QuerySet): """Custom defined filters for the Contributor model."""
[docs] def active(self): """Return all validated and vetted Contributors.""" return self.filter(user__is_active=True, status=NORMAL_CONTRIBUTOR)
[docs] def nonduplicates(self): """ Filter out duplicate Contributors. """ return self.exclude(duplicate_of__isnull=False)
[docs] def available(self): """Filter out the Contributors that have active unavailability periods.""" today = timezone.now().date() return self.exclude( unavailability_periods__start__lte=today, unavailability_periods__end__gte=today, )
[docs] def awaiting_validation(self): """Filter Contributors that have not been validated by the user.""" return self.filter(user__is_active=False, status=NEWLY_REGISTERED)
[docs] def awaiting_vetting(self): """Filter Contributors that have not been vetted through.""" return self.filter(user__is_active=True, status=NEWLY_REGISTERED).exclude( status=DOUBLE_ACCOUNT )
[docs] def with_duplicate_names(self): """ Returns only potential duplicate Contributors (as identified by first and last names). Admins and superusers are explicitly excluded. """ contribs = ( self.exclude(status=DOUBLE_ACCOUNT) .exclude(user__is_superuser=True) .exclude(user__is_staff=True) .annotate(full_name=Concat("user__last_name", "user__first_name")) ) duplicates = ( contribs.values("full_name") .annotate(nr_count=Count("full_name")) .filter(nr_count__gt=1) .values_list("full_name", flat=True) ) return contribs.filter(full_name__in=duplicates).order_by( "user__last_name", "user__first_name", "-id" )
[docs] def with_duplicate_email(self): """ Return Contributors having duplicate emails. """ qs = ( self.exclude(status=DOUBLE_ACCOUNT) .exclude(user__is_superuser=True) .exclude(user__is_staff=True) .annotate(lower_email=Lower("user__email")) ) duplicates = ( qs.values("lower_email") .annotate(Count("id")) .filter(id__count__gt=1) .values_list("lower_email", flat=True) ) return qs.filter(lower_email__in=duplicates)
[docs] def specialties_overlap(self, specialties_slug_list): """ Returns all Contributors whose specialties overlap with those specified in the slug list. This method is also separately implemented for Profile and PotentialFellowship objects. """ return self.filter(profile__specialties__slug__in=specialties_slug_list)
[docs]class UnavailabilityPeriodManager(models.Manager):
[docs] def today(self): today = timezone.now().date() return self.filter(start__lte=today, end__gte=today)
[docs] def future(self): today = timezone.now().date() return self.filter(end__gte=today)
[docs]class AuthorshipClaimQuerySet(models.QuerySet):
[docs] def awaiting_vetting(self): return self.filter(status=AUTHORSHIP_CLAIM_PENDING)