Source code for journals.models.volume

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


from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Avg, F
from django.utils import timezone

from ..constants import ISSUES_AND_VOLUMES
from ..validators import doi_volume_validator


[docs]class Volume(models.Model): """ A Volume belongs to a specific Journal, and is a container for either (multiple) Issue(s) or Publication(s). """ in_journal = models.ForeignKey( "journals.Journal", limit_choices_to={"structure": ISSUES_AND_VOLUMES}, on_delete=models.CASCADE, ) number = models.PositiveSmallIntegerField() start_date = models.DateField(default=timezone.now) until_date = models.DateField(default=timezone.now) doi_label = models.CharField( max_length=200, unique=True, db_index=True, validators=[doi_volume_validator] ) class Meta: default_related_name = "volumes" ordering = ("-until_date",) unique_together = ("number", "in_journal") def __str__(self): return str(self.in_journal) + " Vol. " + str(self.number)
[docs] def clean(self): """Check if the Volume is assigned to a valid Journal.""" if not self.in_journal.has_volumes: raise ValidationError( { "in_journal": ValidationError( "This journal does not allow for the use of Volumes", code="invalid", ), } )
@property def doi_string(self): return "10.21468/" + self.doi_label
[docs] def is_current(self): today = timezone.now().date() return self.start_date <= today and self.until_date >= today
[docs] def nr_publications(self, tier=None): from journals.models import Publication publications = Publication.objects.filter(in_issue__in_volume=self) if tier: publications = publications.filter( accepted_submission__eicrecommendations__recommendation=tier ) return publications.count()
[docs] def avg_processing_duration(self): from journals.models import Publication duration = Publication.objects.filter(in_issue__in_volume=self).aggregate( avg=Avg(F("publication_date") - F("submission_date")) )["avg"] if duration: return duration.total_seconds() / 86400 return 0
[docs] def citation_rate(self, tier=None): """Returns the citation rate in units of nr citations per article per year.""" from journals.models import Publication publications = Publication.objects.filter(in_issue__in_volume=self) if tier: publications = publications.filter( accepted_submission__eicrecommendations__recommendation=tier ) ncites = 0 deltat = 1 # to avoid division by zero for pub in publications: if pub.citedby and pub.latest_citedby_update: ncites += len(pub.citedby) deltat += (pub.latest_citedby_update.date() - pub.publication_date).days return ncites * 365.25 / deltat