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 ed61cd4..86a09b4 100644 Binary files a/test.pdf and b/test.pdf differ