Génération du pdf à partir de la base de données

This commit is contained in:
Valentin Moguérou 2024-04-15 03:02:49 +02:00
parent f716040bcd
commit b46a739430
5 changed files with 151 additions and 40 deletions

View File

@ -0,0 +1,21 @@
# Generated by Django 5.0.4 on 2024-04-15 00:12
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('colloscope', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='periode',
options={'ordering': ['debut']},
),
migrations.RemoveField(
model_name='appartenance',
name='periode',
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 5.0.4 on 2024-04-15 00:14
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('colloscope', '0002_alter_periode_options_remove_appartenance_periode'),
]
operations = [
migrations.RemoveField(
model_name='creneau',
name='classe',
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 5.0.4 on 2024-04-15 00:17
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('colloscope', '0003_remove_creneau_classe'),
]
operations = [
migrations.AddField(
model_name='matiere',
name='classe',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='colloscope.classe'),
preserve_default=False,
),
]

View File

@ -1,5 +1,17 @@
from math import ceil
from datetime import date, datetime, timedelta
from django.db import models from django.db import models
from django.db.models import F from django.db.models import F, Q
calendrier = {
"C" : [
( date(2023, 10, 21), date(2023, 11, 6) ),
( date(2023, 12, 23), date(2024, 1, 8) ),
( date(2024, 2, 10), date(2024, 2, 26) ),
( date(2024, 4, 6), date(2024, 4, 22) ),
]
}
class Lycee(models.Model): class Lycee(models.Model):
uai = models.CharField(max_length=10) uai = models.CharField(max_length=10)
@ -19,7 +31,40 @@ class Periode(models.Model):
debut = models.DateField() debut = models.DateField()
fin = models.DateField() fin = models.DateField()
class Meta:
ordering = ["debut"]
def no_semaine(self, jour):
zone = self.classe.lycee.vacances
vacances = calendrier[zone]
jour0 = self.classe.jour_zero
n = 1 + ((jour - jour0).days)//7
for debut, fin in vacances:
if jour > debut:
n -= 2
return n
def range_semaines(self):
return range(self.no_semaine(self.debut), self.no_semaine(self.fin)+1)
def date_debut_sem(self, n):
zone = self.classe.lycee.vacances
vacances = calendrier[zone]
jour0 = self.classe.jour_zero
jour = jour0 + (n-1) * timedelta(weeks=1)
for debut, _ in vacances:
if jour >= debut:
jour += 2*timedelta(weeks=1)
return jour
class Matiere(models.Model): class Matiere(models.Model):
classe = models.ForeignKey(Classe, on_delete=models.CASCADE)
libelle = models.CharField(max_length=100) libelle = models.CharField(max_length=100)
code = models.CharField(max_length=20) code = models.CharField(max_length=20)
@ -35,6 +80,9 @@ class Groupe(models.Model):
critere = models.ForeignKey(Critere, null=True, on_delete=models.CASCADE) critere = models.ForeignKey(Critere, null=True, on_delete=models.CASCADE)
libelle = models.CharField(max_length=100) libelle = models.CharField(max_length=100)
def membres(self):
return Etudiant.objects.filter(id__in=Appartenance.objects.filter(groupe=self))
class Etudiant(models.Model): class Etudiant(models.Model):
class Meta: class Meta:
ordering=["classe", "nom", "prenom"] ordering=["classe", "nom", "prenom"]
@ -46,19 +94,18 @@ class Etudiant(models.Model):
#lv2 = models.ForeignKey(Matiere, on_delete=models.CASCADE) #lv2 = models.ForeignKey(Matiere, on_delete=models.CASCADE)
def appartient(self, groupe, periode): def appartient(self, groupe, periode):
return Appartenance.objects.filter(periode=periode, etudiant=self, groupe=groupe).exists() return Appartenance.objects.filter(etudiant=self, groupe=groupe).exists()
def groupe_du_critere(self, periode, critere): def groupe_du_critere(self, periode, critere):
if isinstance(critere, str): if isinstance(critere, str):
critere = Critere.objects.get(periode=periode, libelle=critere) critere = Critere.objects.get(periode=periode, libelle=critere)
return Appartenance.objects.get(periode=periode, etudiant=self, groupe__critere=critere).groupe return Appartenance.objects.get(groupe__periode=periode, etudiant=self, groupe__critere=critere).groupe
def groupe_de_colle(self, periode): def groupe_de_colle(self, periode):
return self.groupe_du_critere(periode, "colle") return self.groupe_du_critere(periode, "colle")
class Appartenance(models.Model): class Appartenance(models.Model):
periode = models.ForeignKey(Periode, on_delete=models.CASCADE)
etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE) etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE)
groupe = models.ForeignKey(Groupe, on_delete=models.CASCADE) groupe = models.ForeignKey(Groupe, on_delete=models.CASCADE)
@ -67,12 +114,11 @@ class Colleur(models.Model):
nom = models.CharField(max_length=100) nom = models.CharField(max_length=100)
class Creneau(models.Model): class Creneau(models.Model):
classe = models.ForeignKey(Classe, on_delete=models.CASCADE) periode = models.ForeignKey(Periode, on_delete=models.CASCADE)
jour = models.IntegerField() jour = models.IntegerField()
heure = models.TimeField() heure = models.TimeField()
duree = models.DurationField() duree = models.DurationField()
salle = models.CharField(max_length=20) salle = models.CharField(max_length=20)
periode = models.ForeignKey(Periode, on_delete=models.CASCADE)
matiere = models.ForeignKey(Matiere, on_delete=models.CASCADE) matiere = models.ForeignKey(Matiere, on_delete=models.CASCADE)
colleur = models.ForeignKey(Colleur, on_delete=models.CASCADE) colleur = models.ForeignKey(Colleur, on_delete=models.CASCADE)
est_colle = models.BooleanField() est_colle = models.BooleanField()
@ -83,6 +129,21 @@ class Rotation(models.Model):
groupes = models.ManyToManyField(Groupe) groupes = models.ManyToManyField(Groupe)
semaine = models.IntegerField() semaine = models.IntegerField()
def effectif(self):
n_base = sum(len(groupe.membres()) for groupe in self.groupes.all())
n_plus = len(Amendement.objects.filter(est_positif=True, rotation=self))
n_moins = len(Amendement.objects.filter(est_positif=False, rotation=self))
return n_base + n_plus - n_moins
def est_pleine(self):
eff = self.effectif()
if eff>self.creneau.capacite:
raise models.IntegrityError
else:
return eff==self.creneau.capacite
class Amendement(models.Model): class Amendement(models.Model):
est_positif = models.BooleanField() est_positif = models.BooleanField()
rotation = models.ForeignKey(Rotation, on_delete=models.CASCADE) rotation = models.ForeignKey(Rotation, on_delete=models.CASCADE)

View File

@ -1,29 +1,11 @@
from datetime import date, timedelta from datetime import date, timedelta
from colloscope.models import Etudiant, Critere, Classe from colloscope.models import Etudiant, Critere, Classe, Rotation, Periode, Creneau
from fpdf import FPDF from fpdf import FPDF
from fpdf.fonts import FontFace from fpdf.fonts import FontFace
from fpdf.enums import TableCellFillMode from fpdf.enums import TableCellFillMode
calendrier_zoneC = date(2023, 9, 18), [
( date(2023, 10, 21), date(2023, 11, 6) ),
( date(2023, 12, 23), date(2024, 1, 8) ),
( date(2024, 2, 10), date(2024, 2, 26) ),
( date(2024, 4, 6), date(2024, 4, 22) ),
]
def jour_of_sem(n, cal):
sem_1, vac = cal
jour = sem_1 + (n-1) * timedelta(weeks=1)
for (debut, fin) in vac:
if jour >= debut:
jour += 2*timedelta(weeks=1)
return jour
""" """
etudiants = [ etudiants = [
['Aboujaib', 'Alexandre', 4, 'A', '', ''], ['Aboujaib', 'Alexandre', 4, 'A', '', ''],
@ -124,7 +106,12 @@ class PDF(FPDF):
row.cell("??") # LV2 row.cell("??") # LV2
def table_colloscope(self, creneaux, semaines, rotations): def table_colloscope(self, periode):
semaines = periode.range_semaines()
lundis = [ periode.date_debut_sem(n) for n in semaines ]
creneaux = Creneau.objects.filter(periode=periode)
jours = ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"]
with self.table( with self.table(
align="LEFT", align="LEFT",
width=190, width=190,
@ -140,24 +127,29 @@ class PDF(FPDF):
header.cell(str(sem), align="CENTER") header.cell(str(sem), align="CENTER")
header2 = table.row() header2 = table.row()
for sem in semaines: for lundi in lundis:
header2.cell(jour_of_sem(sem, calendrier_zoneC).strftime("%d/%m/%y"), align="CENTER") header2.cell(lundi.strftime("%d/%m/%y"), align="CENTER")
for i, tr in enumerate(creneaux):
matiere, jour, heure, colleur, salle = tr for i, c in enumerate(creneaux):
matiere = c.matiere
jour = c.jour
heure = c.heure
colleur = c.colleur
salle = c.salle
row = table.row() row = table.row()
row.cell(matiere) row.cell(matiere.libelle)
row.cell(jour) row.cell(jours[jour])
row.cell(heure) row.cell(heure.strftime("%H:%M"))
row.cell(colleur) row.cell("{} {}".format("M." if colleur.civilite=="M" else "Mme", colleur.nom.upper()))
row.cell(salle) row.cell(salle)
for s in semaines: for s in semaines:
for rot in rotations: if Rotation.objects.filter(creneau=c, semaine=s).exists():
if rot[2] == i and rot[0] == s: rot = Rotation.objects.get(creneau=c, semaine=s)
row.cell(str(rot[1]), align="CENTER") groupes = rot.groupes
break row.cell(", ".join(g.libelle for g in groupes.all()), align="CENTER")
else: else:
row.cell() row.cell()
@ -195,8 +187,8 @@ def generate(periode):
base_y = pdf.t_margin + 10 base_y = pdf.t_margin + 10
pdf.set_y(base_y) pdf.set_y(base_y)
pdf.liste_eleves(periode) pdf.liste_eleves(periode)
#pdf.set_y(base_y) pdf.set_y(base_y)
#pdf.table_colloscope(creneaux, semaines, rotations) pdf.table_colloscope(periode)
#pdf.y += 3 #pdf.y += 3
#pdf.table_travaux() #pdf.table_travaux()