diff --git a/colloscope/: b/colloscope/: new file mode 100644 index 0000000..7324391 --- /dev/null +++ b/colloscope/: @@ -0,0 +1,204 @@ +from datetime import date, timedelta + +from colloscope.models import Etudiant, Critere + +from fpdf import FPDF +from fpdf.fonts import FontFace +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 = [ + ['Aboujaib', 'Alexandre', 4, 'A', '', ''], + ['Ajan', 'George', 4, 'A', '', ''], + ['Akrad', 'Lina', 1, 'SI', '', ''], + ['Aubert', 'Nicolas', 1, 'SI', '', ''], + ['Badr', 'Roman', 4, 'A', '', ''], + ['Bazire', 'Aurélien', 5, 'A', '', ''], + ['Boit', 'Arthur', 5, 'A', '', ''], + ['Boubker', 'Youssef', 5, 'A', '', ''], + ['Boudjema', 'Dylan', 1, 'SI', '', ''], + ['Chiriac', 'Mihnea', 6, 'A', '', ''], + ['Courier', 'Marine', 6, 'A', '', ''], + ['Daguin', 'Joseph', 6, 'A', '', ''], + ['Dauguen', 'Gabriel', 7, 'A', '', ''], + ['De Weer', 'Matthias', 7, 'A', '', ''], + ['Desbouis', 'Katell', 2, 'SI', '', ''], + ['Dupouy', 'Jérémie', 7, 'A', '', ''], + ['Hariri--Gautier-Picard', 'Grégoire', 8, 'A', '', ''], + ['Juricevic', 'Matteo', 8, 'A', '', ''], + ['Knanoua', 'Anas', 8, 'A', '', ''], + ['Lesenne', 'Pierrick', 9, 'A', '', ''], + ['Lin', 'Hao', 2, 'SI', '', ''], + ['Masbatin', 'Lucas', 2, 'SI', '', ''], + ['Mayuran', 'Mithushan', 9, 'A', '', ''], + ['Messahli', 'Yassine', 9, 'A', '', ''], + ['Moguérou', 'Valentin', 10, 'B', '', ''], + ['Mohellebi', 'Mathéo', 10, 'B', '', ''], + ['Mouisset--Ferrara', 'Maël', 10, 'B', '', ''], + ['Ottavi', 'Corentin', 11, 'B', '', ''], + ['Ponce', 'Alexian', 11, 'B', '', ''], + ['Pujol', 'Raphaël', 11, 'B', '', ''], + ['Pustetto', 'Mathis', 12, 'B', '', ''], + ['Radice', 'Roman', 12, 'B', '', ''], + ['Rat', 'Evelyn', 12, 'B', '', ''], + ['Rousse', 'Louis', 3, 'SI', '', ''], + ['Roux', 'Gaëtan', 3, 'SI', '', ''], + ['Rouyre--Cros', 'Célian', 3, 'SI', '', ''], + ['Sourbé', 'François-Gabriel', 13, 'B', '', ''], + ['Stourbe', 'Simon', 13, 'B', '', ''], + ['Thai', 'Dany', 13, 'B', '', ''], + ['Théodore', 'Jonathan', 14, 'B', '', ''], + ['Vandroux', 'Benoît', 14, 'B', '', ''], + ['Veyssière', 'Thibaud', 14, 'B', '', ''], + ['Vié', 'Adrien', 15, 'B', '', ''], + ['Ye', 'Luan', 15, 'B', '', ''], + ['Zarka', 'Amélie', 15, 'B', '', ''], +] +""" + +creneaux = [ + ["Mathématiques", "vendredi", "17:00", "M. OUBAHA", "C382"], + ["Anglais", "mercredi", "14:00", "Mme LE GOURIELLEC", "C393"], + ["Mathématiques", "mercredi", "15:00", "M. BOULLY", "R004"], + ["Physique", "mardi", "14:00", "Mme CHEVALIER", "R103"], + ["Mathématiques", "mardi", "18:00", "M. RAPIN", "V152"], + ["Anglais", "mardi", "14:00", "Mme BELAGGOUNE", "C4??"], + ["pas de colle", "", "", "", ""], + ["Physique", "mardi", "17:00", "M. COLIN", "C386"], + ["Mathématiques", "mercredi", "13:30", "M. BOUVEROT", "??"], + ["Anglais", "lundi", "13:00", "M. HERBAUT", "V052"], +] + +semaines = list(range(24, 34)) + +rotations = [ + # [semaine, groupe, creneau] + (24, 1, 1), + (24, 2, 2), + (24, 3, 3), + (27, 3, 3), + (28, 3, 3), + (31, 3, 3), +] + +class PDF(FPDF): + def liste_eleves(self, periode): + classe = periode.classe + etudiants = Etudiant.objects.filter(classe=classe) + + with self.table( + align="RIGHT", + col_widths=(4, 3, 1, 1, 1, 1), + width=80, + line_height=3) as table: + header = table.row() + for th in ("Nom", "Prénom", "Grp.", "TD", "LV1", "LV2"): + header.cell(th) + + for etu in etudiants: + row = table.row() + row.cell(etu.nom.upper()) # Nom + row.cell(etu.prenom) # Prénom + row.cell(etu.groupe_de_colle(periode).libelle) # Groupe + row.cell(etu.groupe_du_critere(periode, "TD")) # TD + row.cell("??") # LV1 + row.cell("??") # LV2 + + + def table_colloscope(self, creneaux, semaines, rotations): + with self.table( + align="LEFT", + width=190, + line_height=3, + col_widths=(2, 1, 1, 3, 1, *(1,)*len(semaines)), + num_heading_rows=2) as table: + + 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") + + header2 = table.row() + for sem in semaines: + header2.cell(jour_of_sem(sem, calendrier_zoneC).strftime("%d/%m/%y"), align="CENTER") + + for i, tr in enumerate(creneaux): + matiere, jour, heure, colleur, salle = tr + + row = table.row() + row.cell(matiere) + row.cell(jour) + row.cell(heure) + row.cell(colleur) + row.cell(salle) + + for s in semaines: + for rot in rotations: + if rot[2] == i and rot[0] == s: + row.cell(str(rot[1]), align="CENTER") + break + 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): + pdf = PDF(orientation="landscape", format="a4") + pdf.set_font("helvetica", size=6) + + pdf.set_title("Colloscope mp2i semestre 5/2") + pdf.set_author("projet colloscope") + pdf.set_author("projet colloscope") + + pdf.add_page() + pdf.cell(text="Colloscope MP2I Semestre 5/2", center=True, border=1, h=5) + base_y = pdf.t_margin + 10 + pdf.set_y(base_y) + pdf.liste_eleves(etudiants) + #pdf.set_y(base_y) + #pdf.table_colloscope(creneaux, semaines, rotations) + #pdf.y += 3 + #pdf.table_travaux() + + pdf.output("test.pdf") + +if __name__ == "__main__": + classe = Classe.get(id=1) + periode = Periode.get(classe=classe, libelle="Semestre 5/2") + + generate(periode) diff --git a/colloscope/migrations/0001_initial.py b/colloscope/migrations/0001_initial.py index 3ac3ff1..8896e3b 100644 --- a/colloscope/migrations/0001_initial.py +++ b/colloscope/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.4 on 2024-04-14 13:40 +# Generated by Django 5.0.4 on 2024-04-14 20:04 import django.db.models.deletion from django.db import migrations, models @@ -29,6 +29,13 @@ class Migration(migrations.Migration): ('nom', models.CharField(max_length=100)), ], ), + migrations.CreateModel( + name='Critere', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('libelle', models.CharField(max_length=100)), + ], + ), migrations.CreateModel( name='Lycee', fields=[ @@ -46,14 +53,6 @@ class Migration(migrations.Migration): ('code', models.CharField(max_length=20)), ], ), - migrations.CreateModel( - name='Groupe', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('libelle', models.CharField(max_length=100)), - ('classe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.classe')), - ], - ), migrations.CreateModel( name='Etudiant', fields=[ @@ -61,8 +60,10 @@ class Migration(migrations.Migration): ('prenom', models.CharField(max_length=100)), ('nom', models.CharField(max_length=100)), ('classe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.classe')), - ('groupes', models.ManyToManyField(to='colloscope.groupe')), ], + options={ + 'ordering': ['classe', 'nom', 'prenom'], + }, ), migrations.AddField( model_name='classe', @@ -79,6 +80,20 @@ class Migration(migrations.Migration): ('classe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.classe')), ], ), + migrations.CreateModel( + name='Groupe', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('libelle', models.CharField(max_length=100)), + ('critere', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='colloscope.critere')), + ('periode', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.periode')), + ], + ), + migrations.AddField( + model_name='critere', + name='periode', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.periode'), + ), migrations.CreateModel( name='Creneau', fields=[ @@ -95,6 +110,15 @@ class Migration(migrations.Migration): ('periode', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.periode')), ], ), + migrations.CreateModel( + name='Appartenance', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('etudiant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.etudiant')), + ('groupe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.groupe')), + ('periode', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.periode')), + ], + ), migrations.CreateModel( name='Rotation', fields=[ @@ -120,8 +144,8 @@ class Migration(migrations.Migration): ('username', models.CharField(max_length=100)), ('password', models.CharField(max_length=300)), ('timestamp', models.DateTimeField(auto_now_add=True)), - ('colleur', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.colleur')), - ('etudiant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='colloscope.etudiant')), + ('colleur', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='colloscope.colleur')), + ('etudiant', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='colloscope.etudiant')), ], ), ] diff --git a/colloscope/migrations/0002_alter_utilisateur_colleur_alter_utilisateur_etudiant.py b/colloscope/migrations/0002_alter_utilisateur_colleur_alter_utilisateur_etudiant.py deleted file mode 100644 index 9ad315f..0000000 --- a/colloscope/migrations/0002_alter_utilisateur_colleur_alter_utilisateur_etudiant.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-14 13:51 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('colloscope', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='utilisateur', - name='colleur', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='colloscope.colleur'), - ), - migrations.AlterField( - model_name='utilisateur', - name='etudiant', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='colloscope.etudiant'), - ), - ] diff --git a/colloscope/models.py b/colloscope/models.py index 4fa259f..f09f7f3 100644 --- a/colloscope/models.py +++ b/colloscope/models.py @@ -1,5 +1,5 @@ from django.db import models - +from django.db.models import F class Lycee(models.Model): uai = models.CharField(max_length=10) @@ -14,6 +14,7 @@ class Classe(models.Model): class Periode(models.Model): classe = models.ForeignKey(Classe, on_delete=models.CASCADE) + #critere_colle = models.ForeignKey(Critere, on_delete=models.SET_NULL, null=True) libelle = models.CharField(max_length=100) debut = models.DateField() fin = models.DateField() @@ -22,17 +23,44 @@ class Matiere(models.Model): libelle = models.CharField(max_length=100) code = models.CharField(max_length=20) +class Critere(models.Model): + periode = models.ForeignKey(Periode, on_delete=models.CASCADE) + libelle = models.CharField(max_length=100) + class Groupe(models.Model): - classe = models.ForeignKey(Classe, on_delete=models.CASCADE) + #class Meta: + # ordering=[F("periode").classe.libelle, F("periode").libelle, "libelle"] + + periode = models.ForeignKey(Periode, on_delete=models.CASCADE) + critere = models.ForeignKey(Critere, null=True, on_delete=models.CASCADE) libelle = models.CharField(max_length=100) class Etudiant(models.Model): + class Meta: + ordering=["classe", "nom", "prenom"] + classe = models.ForeignKey(Classe, on_delete=models.CASCADE) prenom = models.CharField(max_length=100) nom = models.CharField(max_length=100) #lv1 = models.ForeignKey(Matiere, on_delete=models.CASCADE) #lv2 = models.ForeignKey(Matiere, on_delete=models.CASCADE) - groupes = models.ManyToManyField(Groupe) + + def appartient(self, groupe, periode): + return Appartenance.objects.filter(periode=periode, etudiant=self, groupe=groupe).exists() + + def groupe_du_critere(self, periode, critere): + if isinstance(critere, str): + critere = Critere.objects.get(periode=periode, libelle=critere) + + return Appartenance.objects.get(periode=periode, etudiant=self, groupe__critere=critere).groupe + + def groupe_de_colle(self, periode): + return self.groupe_du_critere(periode, "colle") + +class Appartenance(models.Model): + periode = models.ForeignKey(Periode, on_delete=models.CASCADE) + etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE) + groupe = models.ForeignKey(Groupe, on_delete=models.CASCADE) class Colleur(models.Model): civilite = models.CharField(max_length=1) @@ -65,5 +93,5 @@ class Utilisateur(models.Model): username = models.CharField(max_length=100) password = models.CharField(max_length=300) timestamp = models.DateTimeField(auto_now_add=True) - etudiant = models.ForeignKey(Etudiant, on_delete=models.DO_NOTHING, null=True) - colleur = models.ForeignKey(Colleur, on_delete=models.DO_NOTHING, null=True) + etudiant = models.ForeignKey(Etudiant, on_delete=models.SET_NULL, null=True) + colleur = models.ForeignKey(Colleur, on_delete=models.SET_NULL, null=True) diff --git a/colloscope/pdfexport.py b/colloscope/pdfexport.py index b286c46..087f29e 100644 --- a/colloscope/pdfexport.py +++ b/colloscope/pdfexport.py @@ -1,5 +1,7 @@ from datetime import date, timedelta +from colloscope.models import Etudiant, Critere, Classe + from fpdf import FPDF from fpdf.fonts import FontFace from fpdf.enums import TableCellFillMode @@ -22,6 +24,7 @@ def jour_of_sem(n, cal): return jour +""" etudiants = [ ['Aboujaib', 'Alexandre', 4, 'A', '', ''], ['Ajan', 'George', 4, 'A', '', ''], @@ -69,6 +72,7 @@ etudiants = [ ['Ye', 'Luan', 15, 'B', '', ''], ['Zarka', 'Amélie', 15, 'B', '', ''], ] +""" creneaux = [ ["Mathématiques", "vendredi", "17:00", "M. OUBAHA", "C382"], @@ -96,7 +100,10 @@ rotations = [ ] class PDF(FPDF): - def liste_eleves(self, etudiants): + def liste_eleves(self, periode): + classe = periode.classe + etudiants = Etudiant.objects.filter(classe=classe) + with self.table( align="RIGHT", col_widths=(4, 3, 1, 1, 1, 1), @@ -108,12 +115,13 @@ class PDF(FPDF): for etu in etudiants: row = table.row() - row.cell(etu[0].upper()) # Nom - row.cell(etu[1]) # Prénom - row.cell(str(etu[2])) # Groupe - row.cell(etu[3]) # TD - row.cell(etu[4]) # LV1 - row.cell(etu[5]) # LV2 + row.cell(etu.nom.upper()) # Nom + row.cell(etu.prenom) # Prénom + row.cell(etu.groupe_de_colle(periode).libelle) # Groupe + row.cell("??") + #row.cell(etu.groupe_du_critere(periode, "TD")) # TD + row.cell("??") # LV1 + row.cell("??") # LV2 def table_colloscope(self, creneaux, semaines, rotations): @@ -170,25 +178,32 @@ class PDF(FPDF): for _ in range(len(semaines)): row.cell("9 à 15", align="CENTER") -def generate(): +def generate(periode): + classe = periode.classe + pdf = PDF(orientation="landscape", format="a4") pdf.set_font("helvetica", size=6) - pdf.set_title("colloscope mp2i semestre 5/2") + titre = f"Colloscope {classe.libelle} {periode.libelle}" + + pdf.set_title(titre) pdf.set_author("projet colloscope") pdf.set_author("projet colloscope") pdf.add_page() - pdf.cell(text="Colloscope MP2I Semestre 5/2", center=True, border=1, h=5) + pdf.cell(text=titre, center=True, border=1, h=5) base_y = pdf.t_margin + 10 pdf.set_y(base_y) - pdf.liste_eleves(etudiants) - pdf.set_y(base_y) - pdf.table_colloscope(creneaux, semaines, rotations) - pdf.y += 3 - pdf.table_travaux() + pdf.liste_eleves(periode) + #pdf.set_y(base_y) + #pdf.table_colloscope(creneaux, semaines, rotations) + #pdf.y += 3 + #pdf.table_travaux() pdf.output("test.pdf") if __name__ == "__main__": - generate() + classe = Classe.objects.get(id=1) + periode = Periode.objects.get(classe=classe, libelle="Semestre 5/2") + + generate(periode) diff --git a/db.sqlite3.bak b/db.sqlite3.bak new file mode 100644 index 0000000..726e926 Binary files /dev/null and b/db.sqlite3.bak differ diff --git a/test.pdf b/test.pdf index c05d5db..12c6f1a 100644 Binary files a/test.pdf and b/test.pdf differ