From 424db2fea63f60e537f9acc0d863e66adee673f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Mogu=C3=A9rou?= Date: Mon, 15 Apr 2024 19:02:01 +0200 Subject: [PATCH] changes --- colloscope/models.py | 40 ++++++-- colloscope/output-15_1.csv | 199 +++++++++++++++++++++++++++++++++++++ colloscope/pdfexport.py | 61 +++++------- test.pdf | Bin 4520 -> 4556 bytes 4 files changed, 259 insertions(+), 41 deletions(-) create mode 100644 colloscope/output-15_1.csv diff --git a/colloscope/models.py b/colloscope/models.py index 26b2d3a..1a5a1d2 100644 --- a/colloscope/models.py +++ b/colloscope/models.py @@ -93,7 +93,7 @@ class Etudiant(models.Model): #lv1 = models.ForeignKey(Matiere, on_delete=models.CASCADE) #lv2 = models.ForeignKey(Matiere, on_delete=models.CASCADE) - def appartient(self, groupe, periode): + def appartient(self, groupe): return Appartenance.objects.filter(etudiant=self, groupe=groupe).exists() def groupe_du_critere(self, periode, critere): @@ -129,6 +129,18 @@ class Rotation(models.Model): groupes = models.ManyToManyField(Groupe) semaine = models.IntegerField() + def groupe_initial(self): + return Etudiant.objects.filter(id__in=Appartenance.objects.filter(groupe__in=self.groupes.all())) + + def groupe_effectif(self): + amendements=Amendement.objects.filter(rotation=self) + + return Etudiant.objects.filter( + ( Q(id__in=Appartenance.objects.filter(groupe__in=self.groupes.all())) + | Q(id__in=amendements.filter(est_positif=True).values("etudiant_id")) ) + & ~Q(id__in=amendements.filter(est_positif=False).values("etudiant_id")) + ) + 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)) @@ -138,18 +150,34 @@ class Rotation(models.Model): def est_pleine(self): eff = self.effectif() + return eff>=self.creneau.capacite - if eff>self.creneau.capacite: - raise models.IntegrityError + def est_modifiee(self): + return Amendement.objects.filter(rotation=self).exists() + + def amender(self, etudiant, est_positif): + # check annulation + + if Amendement.objects.filter(rotation=self, etudiant=etudiant, est_positif=est_positif).exists(): + raise Exception("Duplication") + elif Amendement.objects.filter(rotation=self, etudiant=etudiant, est_positif=not est_positif).exists(): + Amendement.objects.get(rotation=self, etudiant=etudiant, est_positif=not est_positif).delete() + elif est_positif and any(etudiant.appartient(groupe) for groupe in self.groupes.all()): + raise Exception("Vous êtes déjà dans le groupe") + elif not est_positif and all(not etudiant.appartient(groupe) for groupe in self.groupes.all()): + raise Exception("Vous n'êtes pas dans le groupe") + elif est_positif and self.est_pleine(): + raise Exception("Capacité dépassée") else: - return eff==self.creneau.capacite - + # on ne peut pas s'ajouter si on est dans le groupe de base + amendement = Amendement(rotation=self, etudiant=etudiant, est_positif=est_positif) + amendement.save() + class Amendement(models.Model): est_positif = models.BooleanField() rotation = models.ForeignKey(Rotation, on_delete=models.CASCADE) etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE) - class Utilisateur(models.Model): username = models.CharField(max_length=100) password = models.CharField(max_length=300) diff --git a/colloscope/output-15_1.csv b/colloscope/output-15_1.csv new file mode 100644 index 0000000..e3b637c --- /dev/null +++ b/colloscope/output-15_1.csv @@ -0,0 +1,199 @@ +hour,day,month,year,length,group,colleur,matiere +12,5,2,2024,1,2,Chevalier,Physique +13,5,2,2024,1,13,Herbaut,Anglais +14,6,2,2024,1,6,Mullaert,Maths +14,6,2,2024,1,4,Chevalier,Physique +14,6,2,2024,1,15,Belaggoune,Anglais +17,6,2,2024,1,10,Colin,Physique +17,6,2,2024,1,14,Chevalier,Physique +18,6,2,2024,1,7,Rapin,Maths +13,7,2,2024,1,10,Carpintero,Maths +14,7,2,2024,1,5,Le_Gouriellec,Anglais +14,7,2,2024,1,12,Carpintero,Maths +14,7,2,2024,1,14,Boully,Maths +14,7,2,2024,1,15,Bouverot,Maths +14,7,2,2024,2,0,none,_ +14,7,2,2024,2,0,none,_ +14,7,2,2024,2,0,none,_ +15,7,2,2024,1,4,Bouverot,Maths +15,7,2,2024,1,7,Le_Gouriellec,Anglais +15,7,2,2024,1,11,Boully,Maths +16,7,2,2024,1,9,Mann,Anglais +16,7,2,2024,2,0,none,_ +16,7,2,2024,2,0,none,_ +16,7,2,2024,2,0,none,_ +17,7,2,2024,1,3,Mann,Anglais +17,7,2,2024,1,6,Poupy,Physique +18,7,2,2024,1,8,Poupy,Physique +14,8,2,2024,1,1,Belaggoune,Anglais +15,8,2,2024,1,11,Belaggoune,Anglais +18,8,2,2024,1,2,Rapin,Maths +18,8,2,2024,1,0,none,_ +16,9,2,2024,1,12,Chibani,Physique +17,9,2,2024,1,8,Oubaha,Maths +18,9,2,2024,1,3,Oubaha,Maths +12,12,2,2024,1,1,Chevalier,Physique +13,12,2,2024,1,14,Herbaut,Anglais +14,13,2,2024,1,1,Mullaert,Maths +14,13,2,2024,1,5,Chevalier,Physique +14,13,2,2024,1,0,none,_ +17,13,2,2024,1,7,Colin,Physique +17,13,2,2024,1,9,Chevalier,Physique +18,13,2,2024,1,4,Rapin,Maths +13,14,2,2024,1,7,Carpintero,Maths +14,14,2,2024,1,2,Le_Gouriellec,Anglais +14,14,2,2024,1,13,Carpintero,Maths +14,14,2,2024,1,3,Bouverot,Maths +14,14,2,2024,1,5,Boully,Maths +14,14,2,2024,2,0,none,_ +14,14,2,2024,2,0,none,_ +14,14,2,2024,2,0,none,_ +15,14,2,2024,1,4,Le_Gouriellec,Anglais +15,14,2,2024,1,9,Bouverot,Maths +15,14,2,2024,1,12,Boully,Maths +16,14,2,2024,1,6,Mann,Anglais +16,14,2,2024,2,0,none,_ +16,14,2,2024,2,0,none,_ +16,14,2,2024,2,0,none,_ +17,14,2,2024,1,8,Mann,Anglais +17,14,2,2024,1,11,Poupy,Physique +18,14,2,2024,1,13,Poupy,Physique +14,15,2,2024,1,10,Belaggoune,Anglais +15,15,2,2024,1,12,Belaggoune,Anglais +18,15,2,2024,1,0,none,_ +18,15,2,2024,1,8,Rapin,Maths +16,16,2,2024,1,3,Chibani,Physique +17,16,2,2024,1,11,Oubaha,Maths +18,16,2,2024,1,15,Oubaha,Maths +12,19,2,2024,1,2,Chevalier,Physique +13,19,2,2024,1,11,Herbaut,Anglais +14,20,2,2024,1,2,Mullaert,Maths +14,20,2,2024,1,10,Chevalier,Physique +14,20,2,2024,1,13,Belaggoune,Anglais +17,20,2,2024,1,12,Chevalier,Physique +17,20,2,2024,1,14,Colin,Physique +18,20,2,2024,1,1,Rapin,Maths +13,21,2,2024,1,8,Carpintero,Maths +14,21,2,2024,1,3,Le_Gouriellec,Anglais +14,21,2,2024,1,12,Carpintero,Maths +14,21,2,2024,1,14,Bouverot,Maths +14,21,2,2024,1,9,Boully,Maths +14,21,2,2024,2,0,none,_ +14,21,2,2024,2,0,none,_ +14,21,2,2024,2,0,none,_ +15,21,2,2024,1,1,Le_Gouriellec,Anglais +15,21,2,2024,1,13,Bouverot,Maths +15,21,2,2024,1,6,Boully,Maths +16,21,2,2024,1,5,Mann,Anglais +16,21,2,2024,2,0,none,_ +16,21,2,2024,2,0,none,_ +16,21,2,2024,2,0,none,_ +17,21,2,2024,1,4,Poupy,Physique +17,21,2,2024,1,7,Mann,Anglais +18,21,2,2024,1,8,Poupy,Physique +14,22,2,2024,1,9,Belaggoune,Anglais +15,22,2,2024,1,15,Belaggoune,Anglais +18,22,2,2024,1,5,Rapin,Maths +18,22,2,2024,1,0,none,_ +16,23,2,2024,1,6,Chibani,Physique +17,23,2,2024,1,4,Oubaha,Maths +18,23,2,2024,1,10,Oubaha,Maths +12,26,2,2024,1,9,Chevalier,Physique +13,26,2,2024,1,6,Herbaut,Anglais +14,27,2,2024,1,7,Chevalier,Physique +14,27,2,2024,1,14,Belaggoune,Anglais +14,27,2,2024,1,7,Mullaert,Maths +17,27,2,2024,1,11,Chevalier,Physique +17,27,2,2024,1,13,Colin,Physique +18,27,2,2024,1,3,Rapin,Maths +13,28,2,2024,1,10,Carpintero,Maths +14,28,2,2024,1,2,Le_Gouriellec,Anglais +14,28,2,2024,1,11,Carpintero,Maths +14,28,2,2024,1,13,Bouverot,Maths +14,28,2,2024,1,6,Boully,Maths +14,28,2,2024,2,0,none,_ +14,28,2,2024,2,0,none,_ +14,28,2,2024,2,0,none,_ +15,28,2,2024,1,4,Le_Gouriellec,Anglais +15,28,2,2024,1,5,Boully,Maths +15,28,2,2024,1,14,Bouverot,Maths +16,28,2,2024,1,8,Mann,Anglais +16,28,2,2024,2,0,none,_ +16,28,2,2024,2,0,none,_ +16,28,2,2024,2,0,none,_ +17,28,2,2024,1,1,Poupy,Physique +17,28,2,2024,1,10,Mann,Anglais +18,28,2,2024,1,3,Poupy,Physique +14,29,2,2024,1,12,Belaggoune,Anglais +15,29,2,2024,1,0,none,_ +18,29,2,2024,1,1,Rapin,Maths +18,29,2,2024,1,0,none,_ +16,1,3,2024,1,5,Chibani,Physique +17,1,3,2024,1,2,Oubaha,Maths +18,1,3,2024,1,9,Oubaha,Maths +12,4,3,2024,1,8,Chevalier,Physique +13,4,3,2024,1,3,Herbaut,Anglais +14,5,3,2024,1,5,Belaggoune,Anglais +14,5,3,2024,1,10,Mullaert,Maths +14,5,3,2024,1,10,Chevalier,Physique +17,5,3,2024,1,12,Colin,Physique +17,5,3,2024,1,14,Chevalier,Physique +18,5,3,2024,1,11,Rapin,Maths +13,6,3,2024,1,14,Carpintero,Maths +14,6,3,2024,1,12,Boully,Maths +14,6,3,2024,1,6,Bouverot,Maths +14,6,3,2024,1,7,Le_Gouriellec,Anglais +14,6,3,2024,1,8,Carpintero,Maths +14,6,3,2024,2,0,none,_ +14,6,3,2024,2,0,none,_ +14,6,3,2024,2,0,none,_ +15,6,3,2024,1,2,Boully,Maths +15,6,3,2024,1,9,Le_Gouriellec,Anglais +15,6,3,2024,1,15,Bouverot,Maths +16,6,3,2024,1,11,Mann,Anglais +16,6,3,2024,2,0,none,_ +16,6,3,2024,2,0,none,_ +16,6,3,2024,2,0,none,_ +17,6,3,2024,1,13,Mann,Anglais +17,6,3,2024,1,4,Poupy,Physique +18,6,3,2024,1,6,Poupy,Physique +14,7,3,2024,1,1,Belaggoune,Anglais +15,7,3,2024,1,15,Belaggoune,Anglais +18,7,3,2024,1,0,none,_ +18,7,3,2024,1,3,Rapin,Maths +16,8,3,2024,1,2,Chibani,Physique +17,8,3,2024,1,4,Oubaha,Maths +18,8,3,2024,1,7,Oubaha,Maths +12,11,3,2024,1,7,Chevalier,Physique +13,11,3,2024,1,2,Herbaut,Anglais +14,12,3,2024,1,1,Mullaert,Maths +14,12,3,2024,1,9,Chevalier,Physique +14,12,3,2024,1,4,Belaggoune,Anglais +17,12,3,2024,1,11,Colin,Physique +17,12,3,2024,1,13,Chevalier,Physique +18,12,3,2024,1,7,Rapin,Maths +13,13,3,2024,1,8,Carpintero,Maths +14,13,3,2024,1,6,Le_Gouriellec,Anglais +14,13,3,2024,1,9,Bouverot,Maths +14,13,3,2024,1,13,Carpintero,Maths +14,13,3,2024,1,5,Boully,Maths +14,13,3,2024,2,0,none,_ +14,13,3,2024,2,0,none,_ +14,13,3,2024,2,0,none,_ +15,13,3,2024,1,8,Le_Gouriellec,Anglais +15,13,3,2024,1,11,Bouverot,Maths +15,13,3,2024,1,12,Boully,Maths +16,13,3,2024,1,10,Mann,Anglais +16,13,3,2024,2,0,none,_ +16,13,3,2024,2,0,none,_ +16,13,3,2024,2,0,none,_ +17,13,3,2024,1,1,Poupy,Physique +17,13,3,2024,1,12,Mann,Anglais +18,13,3,2024,1,3,Poupy,Physique +14,14,3,2024,1,0,none,_ +15,14,3,2024,1,14,Belaggoune,Anglais +18,14,3,2024,1,15,Rapin,Maths +18,14,3,2024,1,0,none,_ +16,15,3,2024,1,5,Chibani,Physique +17,15,3,2024,1,3,Oubaha,Maths +18,15,3,2024,1,4,Oubaha,Maths diff --git a/colloscope/pdfexport.py b/colloscope/pdfexport.py index 3cf3134..7a1db25 100644 --- a/colloscope/pdfexport.py +++ b/colloscope/pdfexport.py @@ -1,6 +1,6 @@ from datetime import date, timedelta -from colloscope.models import Etudiant, Critere, Classe, Rotation, Periode, Creneau +from colloscope.models import * from fpdf import FPDF from fpdf.fonts import FontFace @@ -106,10 +106,10 @@ class PDF(FPDF): row.cell("??") # LV2 - def table_colloscope(self, periode): + def table_colloscope(self, periode, heading=True, est_colle=True): semaines = periode.range_semaines() lundis = [ periode.date_debut_sem(n) for n in semaines ] - creneaux = Creneau.objects.filter(periode=periode) + creneaux = Creneau.objects.filter(periode=periode, est_colle=est_colle) jours = ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"] with self.table( @@ -117,18 +117,20 @@ class PDF(FPDF): width=190, line_height=3, col_widths=(2, 1, 1, 3, 1, *(1,)*len(semaines)), - num_heading_rows=2) as table: + num_heading_rows=2 if heading else 0, + first_row_as_headings=heading) as table: - header = table.row() - for th in ("Matière", "Jour", "Heure", "Colleur", "Salle"): - header.cell(th, align="CENTER", rowspan=2) + if heading: + header = table.row() + for th in ("Matière", "Jour", "Heure", "Colleur", "Salle"): + header.cell(th, align="CENTER", rowspan=2) - for sem in semaines: - header.cell(str(sem), align="CENTER") + for sem in semaines: + header.cell(str(sem), align="CENTER") - header2 = table.row() - for lundi in lundis: - header2.cell(lundi.strftime("%d/%m/%y"), align="CENTER") + header2 = table.row() + for lundi in lundis: + header2.cell(lundi.strftime("%d/%m/%y"), align="CENTER") for i, c in enumerate(creneaux): @@ -147,29 +149,15 @@ class PDF(FPDF): for s in semaines: if Rotation.objects.filter(creneau=c, semaine=s).exists(): - rot = Rotation.objects.get(creneau=c, semaine=s) - groupes = rot.groupes - row.cell(", ".join(g.libelle for g in groupes.all()), align="CENTER") + r = Rotation.objects.get(creneau=c, semaine=s) + groupes = r.groupes + content = ", ".join(g.libelle for g in groupes.all()) + + with self.local_context(fill_color=(255, 100, 100) if r.est_modifiee() else None): + row.cell(content, align="CENTER") else: row.cell() - def table_travaux(self): - with self.table( - align="LEFT", - width=190, - line_height=3, - col_widths=(2, 1, 1, 4, *(1,)*len(semaines)), - first_row_as_headings=False) as table: - - row = table.row() - row.cell("TP Physique") - row.cell("lundi") - row.cell("8:30") - row.cell() - - for _ in range(len(semaines)): - row.cell("9 à 15", align="CENTER") - def generate(periode): classe = periode.classe @@ -189,13 +177,16 @@ def generate(periode): pdf.liste_eleves(periode) pdf.set_y(base_y) pdf.table_colloscope(periode) - #pdf.y += 3 - #pdf.table_travaux() + pdf.y += 3 + pdf.table_colloscope(periode, heading=False, est_colle=False) pdf.output("test.pdf") -if __name__ == "__main__": +def main(): classe = Classe.objects.get(id=1) periode = Periode.objects.get(classe=classe, libelle="Semestre 5/2") generate(periode) + +if __name__ == "__main__": + main() diff --git a/test.pdf b/test.pdf index ed61cd46651f737bb88e5d337268bab5a079ef93..86a09b4a4c3d0e911c1d6ddc1cfa1ae3819d5a40 100644 GIT binary patch delta 3689 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 delta 3647 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