Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
3 changed files with 183 additions and 125 deletions
Showing only changes of commit 898270d2f0 - Show all commits

View File

@ -78,20 +78,24 @@ def comp_nom_semestre_dans_parcours(sem):
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
class JuryPE(object): class JuryPE(object):
"""Classe memorisant toutes les informations necessaires pour etablir un jury de PE. Modele """Classe mémorisant toutes les informations nécessaires pour établir un jury de PE.
base sur NotesTable Modèle basé sur NotesTable.
Attributs : - diplome : l'annee d'obtention du diplome DUT et du jury de PE (generalement fevrier XXXX) Attributs :
- juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives +
celles des semestres valides à prendre en compte permettant le calcul des moyennes ...
{'etudid : { 'nom', 'prenom', 'civilite', 'diplome', '', }}
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
* diplome : l'annee d'obtention du diplome BUT et du jury de PE (generalement fevrier XXXX)
* juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives +
celles des semestres valides à prendre en compte permettant le calcul des moyennes ...
``{'etudid : { 'nom', 'prenom', 'civilite', 'diplome', '', }}``
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
""" """
# Variables de classe décrivant les aggrégats, leur ordre d'apparition temporelle et # Variables de classe décrivant les aggrégats, leur ordre d'apparition temporelle et
# leur affichage dans les avis latex # leur affichage dans les avis latex
NBRE_SEMESTRES_PARCOURS = 6
PARCOURS = { PARCOURS = {
"S1": { "S1": {
"aggregat": ["S1"], "aggregat": ["S1"],
@ -105,6 +109,12 @@ class JuryPE(object):
"affichage_court": "S2", "affichage_court": "S2",
"affichage_long": "Semestre 2", "affichage_long": "Semestre 2",
}, },
"1A": {
"aggregat": ["S1", "S2"],
"ordre": 3,
"affichage_court": "1A",
"affichage_long": "1ère année",
},
"S3": { "S3": {
"aggregat": ["S3"], "aggregat": ["S3"],
"ordre": 4, "ordre": 4,
@ -117,12 +127,6 @@ class JuryPE(object):
"affichage_court": "S4", "affichage_court": "S4",
"affichage_long": "Semestre 4", "affichage_long": "Semestre 4",
}, },
"1A": {
"aggregat": ["S1", "S2"],
"ordre": 3,
"affichage_court": "1A",
"affichage_long": "1ère année",
},
"2A": { "2A": {
"aggregat": ["S3", "S4"], "aggregat": ["S3", "S4"],
"ordre": 6, "ordre": 6,
@ -133,16 +137,52 @@ class JuryPE(object):
"aggregat": ["S1", "S2", "S3"], "aggregat": ["S1", "S2", "S3"],
"ordre": 7, "ordre": 7,
"affichage_court": "S1+S2+S3", "affichage_court": "S1+S2+S3",
"affichage_long": "DUT du semestre 1 au semestre 3", "affichage_long": "BUT du semestre 1 au semestre 3",
}, },
"4S": { "4S": {
"aggregat": ["S1", "S2", "S3", "S4"], "aggregat": ["S1", "S2", "S3", "S4"],
"ordre": 8, "ordre": 8,
"affichage_court": "DUT", "affichage_court": "BUT",
"affichage_long": "DUT (tout semestre inclus)", "affichage_long": "BUT du semestre 1 au semestre 4",
}, },
"S5": {
"aggregat": ["S5"],
"ordre": 9,
"affichage_court": "S5",
"affichage_long": "Semestre 5",
},
"S6": {
"aggregat": ["S6"],
"ordre": 10,
"affichage_court": "S6",
"affichage_long": "Semestre 6",
},
"3A": {
"aggregat": ["S5", "S6"],
"ordre": 11,
"affichage_court": "3A",
"affichage_long": "3ème année",
},
"5S": {
"aggregat": ["S1", "S2", "S3", "S4", "S5"],
"ordre": 12,
"affichage_court": "S1+S2+S3+S4+S5",
"affichage_long": "BUT du semestre 1 au semestre 5",
},
"6S": {
"aggregat": ["S1", "S2", "S3", "S4", "S5", "S6"],
"ordre": 13,
"affichage_court": "BUT",
"affichage_long": "BUT (tout semestre inclus)",
},
} }
AGGREGAT_DIPLOMANT = "6S" # aggrégat correspondant à la totalité des notes pour le diplôme
TOUS_LES_SEMESTRES = PARCOURS["6S"]["aggregat"]
TOUS_LES_AGGREGATS = [cle for cle in PARCOURS.keys() if not cle.startswith("S")]
TOUS_LES_PARCOURS = list(PARCOURS.keys())
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
def __init__(self, semBase): def __init__(self, semBase):
""" """
@ -325,7 +365,7 @@ class JuryPE(object):
for sem in semsListe: # pour chacun des semestres de la liste for sem in semsListe: # pour chacun des semestres de la liste
nt = self.get_cache_notes_d_un_semestre(sem["formsemestre_id"]) nt = self.get_cache_notes_d_un_semestre(sem["formsemestre_id"])
etudiantsDuSemestre = ( etudiantsDuSemestre = (
nt.get_etudids() [ins.etudid for ins in nt.formsemestre.inscriptions] # nt.get_etudids()
) # identification des etudiants du semestre ) # identification des etudiants du semestre
if pe_tools.PE_DEBUG: if pe_tools.PE_DEBUG:
@ -341,7 +381,7 @@ class JuryPE(object):
def get_etudids_du_jury(self, def get_etudids_du_jury(self,
ordre="aucun"): ordre="aucun"):
"""Renvoie la liste de tous les étudiants (concrètement leur etudid) """Renvoie la liste de tous les étudiants (concrètement leur etudid)
participant au jury c'est à dire, ceux dont la date du 'jury' est self.diplome participant au jury c'est-à-dire, ceux dont la date du 'jury' est self.diplome
et n'ayant pas abandonné. et n'ayant pas abandonné.
Si l'ordre est précisé, donne une liste etudid dont le nom, prenom trié par ordre alphabétique Si l'ordre est précisé, donne une liste etudid dont le nom, prenom trié par ordre alphabétique
""" """
@ -365,13 +405,18 @@ class JuryPE(object):
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
def add_etudiants(self, def add_etudiants(self,
etudid): etudid):
"""Ajoute un étudiant (via son etudid) au dictionnaire de synthèse jurydict. """Ajoute un étudiant connaissant son etudid au dictionnaire de synthèse jurydict.
L'ajout consiste à : L'ajout consiste à :
> insérer une entrée pour l'étudiant en mémorisant ses infos (get_etudInfo), * insérer une entrée pour l'étudiant en mémorisant ses infos (get_etudInfo),
avec son nom, prénom, etc... avec son nom, prénom, etc...
> à analyser son parcours, pour vérifier s'il n'a pas abandonné l'IUT en cours de route => clé abandon * à analyser son parcours, pour vérifier s'il n'a pas abandonné l'IUT en cours de
> à chercher ses semestres valides (formsemestre_id) et ses années valides (formannee_id), route (cf. clé abandon)
c'est à dire ceux pour lesquels il faudra prendre en compte ses notes dans les calculs de moyenne (type 1A=S1+S2/2) * à chercher ses semestres valides (formsemestre_id) et ses années valides (formannee_id),
c'est-à-dire ceux pour lesquels il faudra prendre en compte ses notes dans les calculs de
moyenne (type 1A=S1+S2/2)
Args:
etudid: L'etudid d'un étudiant, à ajouter au jury s'il respecte les critères précédents
""" """
if etudid not in self.PARCOURSINFO_DICT: if etudid not in self.PARCOURSINFO_DICT:
@ -391,7 +436,7 @@ class JuryPE(object):
# Sa date prévisionnelle de diplome # Sa date prévisionnelle de diplome
self.PARCOURSINFO_DICT[etudid][ self.PARCOURSINFO_DICT[etudid][
"diplome" "diplome"
] = self.calcul_anneePromoDUT_d_un_etudiant(etudid) ] = self.calcul_anneePromoBUT_d_un_etudiant(etudid)
if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2:
pe_tools.pe_print( pe_tools.pe_print(
"promo=" + str(self.PARCOURSINFO_DICT[etudid]["diplome"]), end="" "promo=" + str(self.PARCOURSINFO_DICT[etudid]["diplome"]), end=""
@ -412,11 +457,10 @@ class JuryPE(object):
# et s'ils existent quelles sont ses notes utiles ? # et s'ils existent quelles sont ses notes utiles ?
sesFormsemestre_idValidants = [ sesFormsemestre_idValidants = [
self.get_Fid_d_un_Si_valide_d_un_etudiant(etudid, nom_sem) self.get_Fid_d_un_Si_valide_d_un_etudiant(etudid, nom_sem)
for nom_sem in JuryPE.PARCOURS["4S"][ for nom_sem in JuryPE.TOUS_LES_SEMESTRES
"aggregat" # Recherche du formsemestre_id de son Si valide (ou a défaut en cours)
] # Recherche du formsemestre_id de son Si valide (ou a défaut en cours)
] ]
for i, nom_sem in enumerate(JuryPE.PARCOURS["4S"]["aggregat"]): for i, nom_sem in enumerate(JuryPE.TOUS_LES_SEMESTRES):
fid = sesFormsemestre_idValidants[i] fid = sesFormsemestre_idValidants[i]
self.PARCOURSINFO_DICT[etudid][nom_sem] = fid # ['formsemestre_id'] self.PARCOURSINFO_DICT[etudid][nom_sem] = fid # ['formsemestre_id']
if fid != None and pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: if fid != None and pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2:
@ -424,13 +468,11 @@ class JuryPE(object):
# self.get_moyennesEtClassements_par_semestre_d_un_etudiant( etudid, fid ) # self.get_moyennesEtClassements_par_semestre_d_un_etudiant( etudid, fid )
# Quelles sont ses années validantes ('1A', '2A') et ses parcours (3S, 4S) validants ? # Quelles sont ses années validantes ('1A', '2A') et ses parcours (3S, 4S) validants ?
for parcours in ["1A", "2A", "3S", "4S"]: for parcours in JuryPE.TOUS_LES_AGGREGATS:
lesSemsDuParcours = JuryPE.PARCOURS[parcours][ lesSemsDuParcours = JuryPE.PARCOURS[parcours]["aggregat"] # les semestres du parcours : par ex. ['S1', 'S2', 'S3']
"aggregat"
] # les semestres du parcours : par ex. ['S1', 'S2', 'S3']
lesFidsValidantDuParcours = [ lesFidsValidantDuParcours = [
sesFormsemestre_idValidants[ sesFormsemestre_idValidants[
JuryPE.PARCOURS["4S"]["aggregat"].index(nom_sem) JuryPE.TOUS_LES_SEMESTRES.index(nom_sem)
] ]
for nom_sem in lesSemsDuParcours # par ex. ['SEM4532', 'SEM567', ...] for nom_sem in lesSemsDuParcours # par ex. ['SEM4532', 'SEM567', ...]
] ]
@ -482,7 +524,7 @@ class JuryPE(object):
n'existe pas parmi les semestres existants dans scodoc un semestre postérieur (en terme de date de n'existe pas parmi les semestres existants dans scodoc un semestre postérieur (en terme de date de
début) de n° au moins égal à celui de son dernier semestre valide dans lequel il aurait pu début) de n° au moins égal à celui de son dernier semestre valide dans lequel il aurait pu
s'inscrire mais ne l'a pas fait.""" s'inscrire mais ne l'a pas fait."""
sessems = self.get_semestresDUT_d_un_etudiant( sessems = self.get_semestresBUT_d_un_etudiant(
etudid etudid
) # les semestres de l'étudiant ) # les semestres de l'étudiant
sonDernierSidValide = self.get_dernier_semestre_id_valide_d_un_etudiant(etudid) sonDernierSidValide = self.get_dernier_semestre_id_valide_d_un_etudiant(etudid)
@ -556,8 +598,8 @@ class JuryPE(object):
"""Récupère le formsemestre_id valide d'un étudiant fourni son etudid à un semestre DUT de n° semestre_id """Récupère le formsemestre_id valide d'un étudiant fourni son etudid à un semestre DUT de n° semestre_id
donné. Si le semestre est en cours (pas encore de jury), renvoie le formsemestre_id actuel. donné. Si le semestre est en cours (pas encore de jury), renvoie le formsemestre_id actuel.
""" """
semestre_id = JuryPE.PARCOURS["4S"]["aggregat"].index(nom_semestre) + 1 semestre_id = JuryPE.TOUS_LES_SEMESTRES.index(nom_semestre) + 1
sesSi = self.get_semestresDUT_d_un_etudiant( sesSi = self.get_semestresBUT_d_un_etudiant(
etudid, semestre_id etudid, semestre_id
) # extrait uniquement les Si par ordre temporel décroissant ) # extrait uniquement les Si par ordre temporel décroissant
@ -590,7 +632,8 @@ class JuryPE(object):
Calcule les moyennes et les classements de chaque semestre par tag et les statistiques de ces semestres. Calcule les moyennes et les classements de chaque semestre par tag et les statistiques de ces semestres.
""" """
lesFids = self.get_formsemestreids_du_jury( lesFids = self.get_formsemestreids_du_jury(
self.get_etudids_du_jury(), liste_semestres=["S1", "S2", "S3", "S4"] self.get_etudids_du_jury(),
liste_semestres=JuryPE.TOUS_LES_SEMESTRES
) )
for i, fid in enumerate(lesFids): for i, fid in enumerate(lesFids):
if pe_tools.PE_DEBUG: if pe_tools.PE_DEBUG:
@ -634,7 +677,7 @@ class JuryPE(object):
" - %d étudiants classés " % (nbinscrit) " - %d étudiants classés " % (nbinscrit)
+ ": " + ": "
+ ",".join( + ",".join(
[etudid for etudid in self.semTagDict[fid].get_etudids()] [str(etudid) for etudid in self.semTagDict[fid].get_etudids()]
) )
) )
if lesEtudidsManquants: if lesEtudidsManquants:
@ -642,7 +685,7 @@ class JuryPE(object):
" - dont %d étudiants manquants ajoutés aux données du jury" " - dont %d étudiants manquants ajoutés aux données du jury"
% (len(lesEtudidsManquants)) % (len(lesEtudidsManquants))
+ ": " + ": "
+ ", ".join(lesEtudidsManquants) + ", ".join([str(etudid) for etudid in lesEtudidsManquants])
) )
pe_tools.pe_print(" - Export csv") pe_tools.pe_print(" - Export csv")
filename = self.NOM_EXPORT_ZIP + self.semTagDict[fid].nom + ".csv" filename = self.NOM_EXPORT_ZIP + self.semTagDict[fid].nom + ".csv"
@ -651,7 +694,7 @@ class JuryPE(object):
# ---------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------
def get_formsemestreids_du_jury(self, def get_formsemestreids_du_jury(self,
etudids, etudids,
liste_semestres="4S"): liste_semestres="6S"):
"""Renvoie la liste des formsemestre_id validants des étudiants en parcourant les semestres valides des étudiants mémorisés dans """Renvoie la liste des formsemestre_id validants des étudiants en parcourant les semestres valides des étudiants mémorisés dans
self.PARCOURSINFO_DICT. self.PARCOURSINFO_DICT.
Les étudiants sont identifiés par leur etudic donnés dans la liste etudids (généralement self.get_etudids_in_jury() ). Les étudiants sont identifiés par leur etudic donnés dans la liste etudids (généralement self.get_etudids_in_jury() ).
@ -736,8 +779,8 @@ class JuryPE(object):
# '3S' : ['S1', 'S2', 'S3'], '4S' : ['S1', 'S2', 'S3', 'S4'] } # '3S' : ['S1', 'S2', 'S3'], '4S' : ['S1', 'S2', 'S3', 'S4'] }
# ---> sur 2 parcours DUT (cas S3 fini, cas S4 fini) # ---> sur 2 parcours DUT (cas S3 fini, cas S4 fini)
combinaisons = ["1A", "2A", "3S", "4S"]
for i, nom in enumerate(combinaisons): for i, nom in enumerate(JuryPE.TOUS_LES_AGGREGATS):
parcours = JuryPE.PARCOURS[nom][ parcours = JuryPE.PARCOURS[nom][
"aggregat" "aggregat"
] # La liste des noms de semestres (S1, S2, ...) impliqués dans l'aggrégat ] # La liste des noms de semestres (S1, S2, ...) impliqués dans l'aggrégat
@ -806,7 +849,7 @@ class JuryPE(object):
pe_tools.pe_print( pe_tools.pe_print(
"%d) %s avec interclassement sur la promo" % (i + 1, nom) "%d) %s avec interclassement sur la promo" % (i + 1, nom)
) )
if nom in ["S1", "S2", "S3", "S4"]: if nom in JuryPE.TOUS_LES_SEMESTRES:
settag.set_SetTagDict(self.semTagDict) settag.set_SetTagDict(self.semTagDict)
else: # cas des aggrégats else: # cas des aggrégats
settag.set_SetTagDict(self.setTagDict[nom]) settag.set_SetTagDict(self.setTagDict[nom])
@ -859,7 +902,7 @@ class JuryPE(object):
if ( if (
self.PARCOURSINFO_DICT[etudid][nom] != None self.PARCOURSINFO_DICT[etudid][nom] != None
): # Un parcours valide existe ): # Un parcours valide existe
if nom in ["S1", "S2", "S3", "S4"]: if nom in JuryPE.TOUS_LES_SEMESTRES:
tagtable = self.semTagDict[self.PARCOURSINFO_DICT[etudid][nom]] tagtable = self.semTagDict[self.PARCOURSINFO_DICT[etudid][nom]]
else: else:
tagtable = self.setTagDict[nom][ tagtable = self.setTagDict[nom][
@ -883,7 +926,7 @@ class JuryPE(object):
etudid): etudid):
"""Renvoie l'année d'entrée de l'étudiant à l'IUT""" """Renvoie l'année d'entrée de l'étudiant à l'IUT"""
# etudinfo = self.ETUDINFO_DICT[etudid] # etudinfo = self.ETUDINFO_DICT[etudid]
semestres = self.get_semestresDUT_d_un_etudiant(etudid) semestres = self.get_semestresBUT_d_un_etudiant(etudid)
if semestres: if semestres:
# le 1er sem à l'IUT # le 1er sem à l'IUT
return semestres[0]["annee_debut"] return semestres[0]["annee_debut"]
@ -894,7 +937,7 @@ class JuryPE(object):
etudid): etudid):
"""Renvoie une liste d'infos sur les semestres du parcours d'un étudiant""" """Renvoie une liste d'infos sur les semestres du parcours d'un étudiant"""
# etudinfo = self.ETUDINFO_DICT[etudid] # etudinfo = self.ETUDINFO_DICT[etudid]
sems = self.get_semestresDUT_d_un_etudiant(etudid) sems = self.get_semestresBUT_d_un_etudiant(etudid)
infos = [] infos = []
for sem in sems: for sem in sems:
@ -915,7 +958,7 @@ class JuryPE(object):
delim=";"): delim=";"):
# En tete: # En tete:
entete = ["Id", "Nom", "Abandon", "Diplome"] entete = ["Id", "Nom", "Abandon", "Diplome"]
for nom_sem in ["S1", "S2", "S3", "S4", "1A", "2A", "3S", "4S"]: for nom_sem in JuryPE.TOUS_LES_PARCOURS:
entete += [nom_sem, "descr"] entete += [nom_sem, "descr"]
chaine = delim.join(entete) + "\n" chaine = delim.join(entete) + "\n"
@ -930,8 +973,8 @@ class JuryPE(object):
str(donnees["diplome"]), str(donnees["diplome"]),
] ]
# les semestres # les semestres et les aggrégats
for nom_sem in ["S1", "S2", "S3", "S4", "1A", "2A", "3S", "4S"]: for nom_sem in JuryPE.TOUS_LES_PARCOURS:
table = ( table = (
self.semTagDict[donnees[nom_sem]].nom self.semTagDict[donnees[nom_sem]].nom
if donnees[nom_sem] in self.semTagDict if donnees[nom_sem] in self.semTagDict
@ -968,9 +1011,10 @@ class JuryPE(object):
return list(taglist) return list(taglist)
def get_allTagInSyntheseJury(self): def get_allTagInSyntheseJury(self):
"""Extrait tous les tags du dictionnaire syntheseJury trié par ordre alphabétique. [] si aucun tag""" """Extrait tous les tags du dictionnaire syntheseJury trié par
ordre alphabétique. [] si aucun tag"""
allTags = set() allTags = set()
for nom in JuryPE.PARCOURS.keys(): for nom in JuryPE.TOUS_LES_PARCOURS:
allTags = allTags.union(set(self.get_allTagForAggregat(nom))) allTags = allTags.union(set(self.get_allTagForAggregat(nom)))
return sorted(list(allTags)) if len(allTags) > 0 else [] return sorted(list(allTags)) if len(allTags) > 0 else []
@ -1160,7 +1204,7 @@ class JuryPE(object):
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
def get_semestresDUT_d_un_etudiant(self, def get_semestresBUT_d_un_etudiant(self,
etudid, etudid,
semestre_id=None): semestre_id=None):
"""Renvoie la liste des semestres DUT d'un étudiant """Renvoie la liste des semestres DUT d'un étudiant
@ -1169,18 +1213,19 @@ class JuryPE(object):
les semestres étant triés par ordre décroissant. les semestres étant triés par ordre décroissant.
Si semestre_id == None renvoie tous les semestres""" Si semestre_id == None renvoie tous les semestres"""
etud = self.get_cache_etudInfo_d_un_etudiant(etudid) etud = self.get_cache_etudInfo_d_un_etudiant(etudid)
nbre_semestres = int(JuryPE.AGGREGAT_DIPLOMANT[0]) # 6
if semestre_id == None: if semestre_id == None:
sesSems = [sem for sem in etud["sems"] if 1 <= sem["semestre_id"] <= 4] sesSems = [sem for sem in etud["sems"] if 1 <= sem["semestre_id"] <= nbre_semestres]
else: else:
sesSems = [sem for sem in etud["sems"] if sem["semestre_id"] == semestre_id] sesSems = [sem for sem in etud["sems"] if sem["semestre_id"] == semestre_id]
return sesSems return sesSems
# ********************************************** # **********************************************
def calcul_anneePromoDUT_d_un_etudiant(self, def calcul_anneePromoBUT_d_un_etudiant(self,
etudid) -> int: etudid) -> int:
"""Calcule et renvoie la date de diplome prévue pour un étudiant fourni avec son etudid """Calcule et renvoie la date de diplome prévue pour un étudiant fourni avec son etudid
en fonction de ses semestres de scolarisation""" en fonction de ses semestres de scolarisation"""
semestres = self.get_semestresDUT_d_un_etudiant(etudid) semestres = self.get_semestresBUT_d_un_etudiant(etudid)
if semestres: if semestres:
return max([get_annee_diplome_semestre(sem) for sem in semestres]) return max([get_annee_diplome_semestre(sem) for sem in semestres])
else: else:
@ -1191,7 +1236,7 @@ class JuryPE(object):
def get_resultat_d_un_etudiant(self, def get_resultat_d_un_etudiant(self,
etudid): etudid):
chaine = "" chaine = ""
for nom_sem in ["S1", "S2", "S3", "S4"]: for nom_sem in JuryPE.TOUS_LES_SEMESTRES:
semtagid = self.PARCOURSINFO_DICT[etudid][ semtagid = self.PARCOURSINFO_DICT[etudid][
nom_sem nom_sem
] # le formsemestre_id du semestre taggué de l'étudiant ] # le formsemestre_id du semestre taggué de l'étudiant
@ -1230,27 +1275,37 @@ class JuryPE(object):
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def get_annee_diplome_semestre(sem) -> int: def get_annee_diplome_semestre(sem) -> int:
"""Pour un semestre donne, décrit par le biais du dictionnaire sem usuel : """Pour un semestre donne, décrit par le biais du dictionnaire sem usuel :
sem = {'formestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
à condition qu'il soit un semestre de formation DUT, sem = {'formestre_id': ..., 'semestre_id': ..., 'annee_debut': ...}
predit l'annee à laquelle sera remis le diplome DUT des etudiants scolarisés dans le semestre
à condition qu'il soit un semestre de formation BUT,
predit l'annee à laquelle sera remis le diplome BUT des etudiants scolarisés dans le semestre
(en supposant qu'il n'y ait plus de redoublement) et la renvoie sous la forme d'un int. (en supposant qu'il n'y ait plus de redoublement) et la renvoie sous la forme d'un int.
Hypothese : les semestres de 1ere partie d'annee universitaire (comme des S1 ou des S3) s'etalent
sur deux annees civiles - contrairement au semestre de seconde partie d'annee universitaire (comme Les semestres de 1ère partie d'année (S1, S3, S5 ou S4, S6 pour des semestres décalés)
des S2 ou des S4). s'étalent sur deux années civiles ; contrairement au semestre de seconde partie d'annee universitaire.
Par exemple : Par exemple :
> S4 debutant en 2016 finissant en 2016 => diplome en 2016 * S5 débutant en 2025 finissant en 2026 => diplome en 2026
> S3 debutant en 2015 et finissant en 2016 => diplome en 2016 * S3 debutant en 2025 et finissant en 2026 => diplome en 2027
> S3 (decale) debutant en 2015 et finissant en 2015 => diplome en 2016 * S5 décalé débutant en 2025 et finissant en 2025 => diplome en 2026
La regle de calcul utilise l'annee_fin du semestre sur le principe suivant : * S3 decale débutant en 2025 et finissant en 2025 => diplome en 2027
nbreSemRestant = nombre de semestres restant avant diplome
nbreAnneeRestant = nombre d'annees restant avant diplome La règle de calcul utilise l'``annee_fin`` du semestre sur le principe suivant :
1 - delta = 0 si semestre de 1ere partie d'annee / 1 sinon
decalage = active ou desactive un increment a prendre en compte en cas de semestre decale * nbreSemRestant = nombre de semestres restant avant diplome
* nbreAnneeRestant = nombre d'annees restant avant diplome
* 1 - delta = 0 si semestre de 1ere partie d'annee / 1 sinon
* decalage = active ou désactive un increment à prendre en compte en cas de semestre decale
Args:
sem: Le semestre
""" """
nbre_semestres = int(JuryPE.AGGREGAT_DIPLOMANT[0]) # 6
if ( if (
1 <= sem["semestre_id"] <= 4 1 <= sem["semestre_id"] <= nbre_semestres
): # Si le semestre est un semestre DUT => problème si formation DUT en 1 an ?? ): # Si le semestre est un semestre BUT => problème si formation BUT en 1 an ??
nbreSemRestant = 4 - sem["semestre_id"] nbreSemRestant = nbre_semestres - sem["semestre_id"]
nbreAnRestant = nbreSemRestant // 2 nbreAnRestant = nbreSemRestant // 2
delta = int(sem["annee_fin"]) - int(sem["annee_debut"]) delta = int(sem["annee_fin"]) - int(sem["annee_debut"])
decalage = nbreSemRestant % 2 # 0 si S4, 1 si S3, 0 si S2, 1 si S1 decalage = nbreSemRestant % 2 # 0 si S4, 1 si S3, 0 si S2, 1 si S1

View File

@ -291,7 +291,7 @@ class TableTag(object):
for etudid in self.identdict: for etudid in self.identdict:
descr = delim.join( descr = delim.join(
[ [
etudid, str(etudid),
self.identdict[etudid]["nom"], self.identdict[etudid]["nom"],
self.identdict[etudid]["prenom"], self.identdict[etudid]["prenom"],
] ]

View File

@ -106,39 +106,40 @@ def pe_view_sem_recap(
# (chaines unicodes, html non quoté) # (chaines unicodes, html non quoté)
template_latex = "" template_latex = ""
# template fourni via le formulaire Web # template fourni via le formulaire Web
if avis_tmpl_file: if False:
try: if avis_tmpl_file:
template_latex = avis_tmpl_file.read().decode("utf-8") try:
except UnicodeDecodeError as e: template_latex = avis_tmpl_file.read().decode("utf-8")
raise ScoValueError( except UnicodeDecodeError as e:
"Données (template) invalides (caractères non UTF8 ?)" raise ScoValueError(
) from e "Données (template) invalides (caractères non UTF8 ?)"
else: ) from e
# template indiqué dans préférences ScoDoc ? else:
template_latex = pe_avislatex.get_code_latex_from_scodoc_preference( # template indiqué dans préférences ScoDoc ?
formsemestre_id, champ="pe_avis_latex_tmpl" template_latex = pe_avislatex.get_code_latex_from_scodoc_preference(
) formsemestre_id, champ="pe_avis_latex_tmpl"
)
template_latex = template_latex.strip() template_latex = template_latex.strip()
if not template_latex: if not template_latex:
# pas de preference pour le template: utilise fichier du serveur # pas de preference pour le template: utilise fichier du serveur
template_latex = pe_avislatex.get_templates_from_distrib("avis") template_latex = pe_avislatex.get_templates_from_distrib("avis")
# Footer: # Footer:
footer_latex = "" footer_latex = ""
# template fourni via le formulaire Web # template fourni via le formulaire Web
if footer_tmpl_file: if footer_tmpl_file:
footer_latex = footer_tmpl_file.read().decode("utf-8") footer_latex = footer_tmpl_file.read().decode("utf-8")
else: else:
footer_latex = pe_avislatex.get_code_latex_from_scodoc_preference( footer_latex = pe_avislatex.get_code_latex_from_scodoc_preference(
formsemestre_id, champ="pe_avis_latex_footer" formsemestre_id, champ="pe_avis_latex_footer"
) )
footer_latex = footer_latex.strip() footer_latex = footer_latex.strip()
if not footer_latex: if not footer_latex:
# pas de preference pour le footer: utilise fichier du serveur # pas de preference pour le footer: utilise fichier du serveur
footer_latex = pe_avislatex.get_templates_from_distrib( footer_latex = pe_avislatex.get_templates_from_distrib(
"footer" "footer"
) # fallback: footer vides ) # fallback: footer vides
tag_annotation_pe = pe_avislatex.get_code_latex_from_scodoc_preference( tag_annotation_pe = pe_avislatex.get_code_latex_from_scodoc_preference(
formsemestre_id, champ="pe_tag_annotation_avis_latex" formsemestre_id, champ="pe_tag_annotation_avis_latex"
@ -151,27 +152,29 @@ def pe_view_sem_recap(
jury.NOM_EXPORT_ZIP + "_annotationsPE" + scu.XLSX_SUFFIX, sT.excel() jury.NOM_EXPORT_ZIP + "_annotationsPE" + scu.XLSX_SUFFIX, sT.excel()
) )
latex_pages = {} # Dictionnaire de la forme nom_fichier => contenu_latex if False:
for etudid in etudids: latex_pages = {} # Dictionnaire de la forme nom_fichier => contenu_latex
[nom_fichier, contenu_latex] = pe_avislatex.get_avis_poursuite_par_etudiant( for etudid in etudids:
jury, [nom_fichier, contenu_latex] = pe_avislatex.get_avis_poursuite_par_etudiant(
etudid, jury,
template_latex, etudid,
tag_annotation_pe, template_latex,
footer_latex, tag_annotation_pe,
prefs, footer_latex,
prefs,
)
jury.add_file_to_zip("avis/" + nom_fichier + ".tex", contenu_latex)
latex_pages[nom_fichier] = contenu_latex # Sauvegarde dans un dico
# Nouvelle version : 1 fichier par étudiant avec 1 fichier appelant créée ci-dessous
doc_latex = "\n% -----\n".join(
["\\include{" + nom + "}" for nom in sorted(latex_pages.keys())]
) )
jury.add_file_to_zip("avis/" + nom_fichier + ".tex", contenu_latex) jury.add_file_to_zip("avis/avis_poursuite.tex", doc_latex)
latex_pages[nom_fichier] = contenu_latex # Sauvegarde dans un dico
# Nouvelle version : 1 fichier par étudiant avec 1 fichier appelant créée ci-dessous # Ajoute image, LaTeX class file(s) and modeles
doc_latex = "\n% -----\n".join( pe_tools.add_pe_stuff_to_zip(jury.zipfile, jury.NOM_EXPORT_ZIP)
["\\include{" + nom + "}" for nom in sorted(latex_pages.keys())]
)
jury.add_file_to_zip("avis/avis_poursuite.tex", doc_latex)
# Ajoute image, LaTeX class file(s) and modeles
pe_tools.add_pe_stuff_to_zip(jury.zipfile, jury.NOM_EXPORT_ZIP)
data = jury.get_zipped_data() data = jury.get_zipped_data()
return send_file( return send_file(