SciPost Code Repository

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


from django.core.validators import validate_unicode_slug
from django.db import models
from django.urls import reverse


def cost_default_value():
    return {"default": 400}


class AffiliateJournal(models.Model):
    """
    A Journal which piggybacks on SciPost's services.
    """

    publisher = models.ForeignKey(
        "affiliates.AffiliatePublisher",
        on_delete=models.CASCADE,
        related_name="journals",
    name = models.CharField(max_length=256)
    short_name = models.CharField(max_length=256, default="")

    slug = models.SlugField(
        max_length=128,
        validators=[
            validate_unicode_slug,
        ],
        unique=True,
    homepage = models.URLField(max_length=256, blank=True)

    # Cost per publication information
    cost_info = models.JSONField(default=cost_default_value)

    class Meta:
        ordering = ["publisher", "name"]
        permissions = (("manage_journal_content", "Manage Journal content"),)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("affiliates:journal_detail", kwargs={"slug": self.slug})

    def cost_per_publication(self, year):
        try:
            return int(self.cost_info[str(year)])
        except KeyError:
            return int(self.cost_info["default"])

    @property
    def balance_info(self):
        return self.get_balance_info()

    def get_balance_info(self, organization=None):
        """
        For each publishing year, provide financial info.
        """
        publications = self.publications.all()
        subsidies = self.affiliatejournalyearsubsidy_set.all()
        if organization:
            publications = publications.filter(
                pubfractions__organization=organization
            )
            subsidies = subsidies.filter(organization=organization)
        if not publications:
            return {}
        maxyear = publications.first().publication_date.year
        minyear = publications.last().publication_date.year
        years = range(maxyear, minyear - 1, -1)
        balance_info = {}
        for year in years:
            nr_publications = publications.filter(
                publication_date__year=year).count()
            subsidy_tally = subsidies.filter(
                year=year
            ).aggregate(models.Sum("amount"))["amount__sum"]
            if not subsidy_tally:
                subsidy_tally = 0
            balance_info[year] = {
                "nr_publications": nr_publications,
                "unit_cost": self.cost_per_publication(year),
                "expenditure": nr_publications * self.cost_per_publication(year),
                "subsidies": subsidy_tally,
                "balance": (subsidy_tally -
                            nr_publications * self.cost_per_publication(year)),
            }
            if organization:
                from ..models import AffiliatePubFraction
                sum_pubfracs = AffiliatePubFraction.objects.filter(
                    publication__journal=self,
                    organization=organization,
                    publication__publication_date__year=year,
                ).aggregate(models.Sum("fraction"))["fraction__sum"]
                if not sum_pubfracs:
                    sum_pubfracs = 0
                balance_info[year]["pubfractions"] = sum_pubfracs
                balance_info[year][
                    "expenditure"
                ] = int(sum_pubfracs * self.cost_per_publication(year))
                balance_info[year][
                    "balance"
                ] = int(subsidy_tally - sum_pubfracs * self.cost_per_publication(year))