import datetime from django.db import models from django.db.models import BooleanField, CharField, DateField, IntegerField, Q from markdownx.models import MarkdownxField from solo.models import SingletonModel class SiteConfiguration(SingletonModel): homepageText = MarkdownxField("Texte de la page d'accueil (Markdown)") writearticleText = MarkdownxField("Texte de la page « écrire » (Markdown)") email = CharField( "Adresse de contact du BOcal", max_length=128, help_text="Attention au spam…" ) specialPublisDescr = MarkdownxField( "Texte de la page des " "publications spéciales (Markdown)" ) def __str__(self): return "Configuration du site" class Meta: # pyright: ignore verbose_name = "Configuration du site" class Publication(models.Model): num = CharField("Numéro du BOcal", max_length=128) url = CharField("Adresse sur le site", max_length=512) # ^ This is not a URLField because we need internal URLS, eg `/static/blah` date = DateField("Publication") unknown_date = BooleanField( "Date inconnue", help_text=( "La date de publication du BOcal " "est inconnue parce qu'il est " "trop vieux. La date indiquée ne " "servira qu'à le ranger dans une " "année et à ordonner les BOcals." ), default=False, ) is_special = BooleanField( "Numéro spécial", help_text="Numéro du BOcal non-numéroté", default=False ) in_year_view_anyway = BooleanField( "Aussi dans l'année", help_text=( "Si le numéro est spécial, l'afficher quand même dans la " "page de l'année correspondante." ), default=False, ) descr = CharField("Description (optionnelle)", max_length=512, blank=True) custom_name = CharField( "Nom customisé", help_text="Vide pour laisser le numéro seulement", max_length=128, blank=True, ) class NoPublicationYear(Exception): def __str__(self): return "No matching publication year." @property def numericPublicationYear(self): startYear = self.date.year if self.date.month < 8: return startYear - 1 return startYear def publicationYear(self): """Fetch corresponding publication year Raise `NoPublicationYear` if there is no such entry""" startYear = self.numericPublicationYear try: return PublicationYear.objects.get(startYear=startYear) except PublicationYear.DoesNotExist: raise self.NoPublicationYear def createPubYear(self): """Creates the corresponding publication year if needed.""" if ( PublicationYear.objects.filter( startYear=self.numericPublicationYear ).count() ) == 0: pubYear = PublicationYear(startYear=self.numericPublicationYear, descr="") pubYear.save() return True return False def __str__(self): if self.custom_name: return self.custom_name elif self.is_special: return self.num return "BOcal n°{}".format(self.num) @staticmethod def latest(): return Publication.objects.order_by("-date")[0] class Meta: ordering = ["date"] class PublicationYear(models.Model): startYear = IntegerField( "Année de début", help_text="Année scolaire à partir du 15/08", primary_key=True ) descr = MarkdownxField("Accroche de l'année (Markdown)") def __str__(self): return "{}-{}".format(self.startYear, self.startYear + 1) def beg(self): """First day of this publication year (incl.)""" return datetime.date(self.startYear, 8, 15) def end(self): """Last day of this publication year (excl.)""" return datetime.date(self.startYear + 1, 8, 15) def inYear(self, date): return self.beg() <= date < self.end() def publis(self): """List of publications from this year""" return Publication.objects.filter( Q(is_special=False) | Q(in_year_view_anyway=True), date__gte=self.beg(), date__lt=self.end(), ) @property def url(self): return "/{}/".format(self) @property def prettyName(self): return "{} – {}".format(self.startYear, self.startYear + 1) class Meta: ordering = ["-startYear"]