diff --git a/app/pe/pe_etudiant.py b/app/pe/pe_etudiant.py index cda39fa1..29d5f597 100644 --- a/app/pe/pe_etudiant.py +++ b/app/pe/pe_etudiant.py @@ -57,11 +57,13 @@ class EtudiantsJuryPE: "Les identités des étudiants traités pour le jury" self.identites = {} # ex. ETUDINFO_DICT - "Les cursus (semestres suivis, abandons, ...) des étudiants" + "Les cursus (semestres suivis, abandons, dernier S1, S2, ...) des étudiants" self.cursus = {} + """Les aggrégats des semestres suivis (par ex: 3S=S1+S2+S3 à prendre en compte avec d'éventuels redoublements) des étudiants""" + self.aggregats = {} "Les etudids des étudiants à considérer au jury (ceux qui seront effectivement diplômés)" - self.etudiants_jury_ids = {} + self.diplomes_ids = {} "Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)" self.etudiants_ids = {} @@ -116,7 +118,7 @@ class EtudiantsJuryPE: pe_tools.pe_print() """Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris""" - self.etudiants_jury_ids = self.get_etudiants(annee_diplome) + self.diplomes_ids = self.get_etudiants(annee_diplome) """Les étudiants dont il faut calculer les moyennes""" self.etudiants_ids = {etudid for etudid in self.cursus} @@ -126,13 +128,13 @@ class EtudiantsJuryPE: # Synthèse pe_tools.pe_print( - f" => {len(self.etudiants_jury_ids)} étudiants à diplômer en {annee_diplome}" + f" => {len(self.diplomes_ids)} étudiants à diplômer en {annee_diplome}" ) nbre_abandons = len(self.etudiants_ids) - len(self.etudiants_ids) pe_tools.pe_print(f" => {nbre_abandons} étudiants éliminer pour abandon") pe_tools.pe_print( f" => quelques étudiants futurs diplômés : " - + ", ".join([str(etudid) for etudid in list(self.etudiants_jury_ids)[:10]]) + + ", ".join([str(etudid) for etudid in list(self.diplomes_ids)[:10]]) ) pe_tools.pe_print( f" => semestres dont il faut calculer les moyennes : " @@ -194,8 +196,6 @@ class EtudiantsJuryPE: "etat_civil": identite.etat_civil, # Ajout à la table jury "diplome": annee_diplome(identite), # Le date prévisionnelle de son diplôme "formsemestres": semestres_etudiant, # les semestres de l'étudiant - "semestres": {}, - "aggregats": {}, } """ Est-il réorienté / démissionnaire ou a-t-il arrêté volontairement sa formation ?""" @@ -207,18 +207,22 @@ class EtudiantsJuryPE: étudiant, pour identifier les semestres qui seront pris en compte lors de ses calculs de moyennes PE. - La structure s'appuie sur les numéros de semestre: pour chaque Si, stocke : - * le (ou les) formsemestres de numéro i qu'a suivi un étudiant (2 si redoublant) - * le dernier semestre de numéro i qu'il a suivi (1 ou 0 si pas encore suivi) + Cette structuration (cf. attribut self.cursus) s'appuie sur les numéros de semestre: pour chaque Si, stocke : + le dernier semestre (en date) de numéro i qu'il a suivi (1 ou 0 si pas encore suivi). Ce semestre influera les + interclassement par semestre dans la promo. - Elle s'appuie également sur les aggrégats: pour chaque aggrégat (par ex, 3A=S1+S2+S3), - identifie les semestres que l'étudiant a suivi pour l'amener jusqu'au semestre terminal - de l'aggrégat. Ce parcours peut être : - * S1+S2+S1+S2+S3 si redoublement de la 1ère année - * S1+S2+(année de césure)+S3 si césure, ... + Elle calcule également sur les aggrégats (cf. attribut self.aggregats): + + * pour un semestre de type Si, elle stocke le (ou les) formsemestres de numéro i qu'a suivi un étudiant + (2 si redoublant) dans self.aggregats + * pour des aggrégats de type iS ou iA (par ex, 3A=S1+S2+S3), elle identifie les semestres que l'étudiant + a suivi pour l'amener jusqu'au semestre terminal de l'aggrégat. Ce parcours peut être : + ** S1+S2+S1+S2+S3 si redoublement de la 1ère année + ** S1+S2+(année de césure)+S3 si césure, ... """ semestres_etudiant = self.cursus[etudid]["formsemestres"] + """Tri des semestres par numéro de semestre""" for nom_sem in pe_tools.TOUS_LES_SEMESTRES: i = int(nom_sem[1]) # le n° du semestre semestres_i = { @@ -226,22 +230,21 @@ class EtudiantsJuryPE: for fid in semestres_etudiant if semestres_etudiant[fid].semestre_id == i } # les semestres de n°i de l'étudiant - self.cursus[etudid]["aggregats"][nom_sem] = semestres_i - self.cursus[etudid]["semestres"][nom_sem] = get_dernier_semestre(semestres_i) + self.aggregats[etudid][nom_sem] = semestres_i + self.cursus[etudid][nom_sem] = get_dernier_semestre(semestres_i) """Tri des semestres par aggrégat et par semestre terminal""" for aggregat in pe_tools.TOUS_LES_AGGREGATS: - self.cursus[etudid][aggregat] = {} + self.aggregat[etudid][aggregat] = {} + """L'aggrégat considéré (par ex: 3S), son nom de son semestre terminal (par ex: S3) et son numéro (par ex: 3)""" noms_semestre_de_aggregat = pe_tools.PARCOURS[aggregat]["aggregat"] nom_semestre_terminal = noms_semestre_de_aggregat[-1] numero_semestre_terminal = int(nom_semestre_terminal[-1]) - """Les semestres terminaux de l'aggrégat""" - # formsemestres_terminal = self.cursus[etudid]["aggregats"][nom_semestre_terminal] - # dernier_formsemestre_terminal = get_dernier_semestre(formsemestres_terminal) # le dernier en date - dernier_formsemestre_terminal = self.cursus[etudid]["semestres"][nom_semestre_terminal] + """Le formsemestre terminal de l'aggrégat (par ex: son dernier S3 en date)""" + dernier_formsemestre_terminal = self.cursus[etudid][nom_semestre_terminal] # for formsem_id_term in formsemestres_terminal: if dernier_formsemestre_terminal: # ne considérant que le dernier @@ -259,7 +262,7 @@ class EtudiantsJuryPE: ): semestres_aggreges[fid] = semestre - self.cursus[etudid][aggregat][formsem_id_term] = semestres_aggreges + self.aggregat[etudid][aggregat][formsem_id_term] = semestres_aggreges def get_formsemestres_terminaux_aggregat(self, aggregat: str): """Pour un aggrégat donné, ensemble des formsemestres terminaux possibles pour l'aggrégat (pour l'aggrégat '3S' @@ -422,17 +425,32 @@ def annee_diplome(identite: Identite) -> int: def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> bool: - """Détermine si un étudiant a arrêté sa formation. Il peut s'agir : + """Détermine si un étudiant a arrêté sa formation. Il peut s'agir : - * d'une réorientation à l'initiative du jury de semestre ou d'une démission ; dans ce cas, utilise les - décisions prises dans les jury de semestres (code NAR pour réorienté & DEM pour démissionnaire) + * d'une réorientation à l'initiative du jury de semestre ou d'une démission (on pourrait + utiliser les code NAR pour réorienté & DEM pour démissionnaire des résultats du jury renseigné dans la BDD, + mais pas nécessaire ici) - * d'un arrêt volontaire : l'étudiant disparait des listes d'inscrit, sans - pour autant avoir été indiqué NAR ou DEM. Dans ce cas, recherche son dernier semestre validé et - regarde s'il 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 - s'inscrire mais ne l'a pas fait. + * d'un arrêt volontaire : l'étudiant disparait des listes d'inscrits (sans pour autant avoir été indiqué NAR ou DEM). + + Dans les cas, on considérera que l'étudiant a arrêté sa formation s'il n'est pas dans l'un des "derniers" cosemestres + (semestres conduisant à la même année de diplômation) connu dans Scodoc. + + Par ex: au moment du jury PE en fin de S5 (pas de S6 renseigné dans Scodoc), l'étudiant doit appartenir à une + instance des S5 qui conduisent à la diplomation dans l'année visée. S'il n'est que dans un S4, il a sans doute + arrêté. A moins qu'il ne soit parti à l'étranger et là, pas de notes. + TODO:: Cas de l'étranger, à coder/tester + + **Attention** : Cela suppose que toutes les instances d'un semestre donné (par ex: toutes les instances de S6 + accueillant un étudiant soient créées ; sinon les étudiants non inscrits dans un S6 seront considérés comme + ayant abandonnés) + TODO:: Peut-être à mettre en regard avec les propositions d'inscriptions d'étudiants dans un nouveau semestre + + Pour chaque étudiant, recherche son dernier semestre en date (validé ou non) et + regarde s'il n'existe pas parmi les semestres existants dans Scodoc un semestre : + * dont les dates sont postérieures (en terme de date de début) + * de n° au moins égal à celui de son dernier semestre valide (S5 -> S5 ou S5 -> S6) + dans lequel il aurait pu s'inscrire mais ne l'a pas fait. Args: identite: L'identité d'un étudiant @@ -441,30 +459,22 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b Returns: Est-il réorienté, démissionnaire ou a-t-il arrêté de son propre chef sa formation ? - TODO:: A reprendre avec l'accès aux résultats des jury prévu par Scodoc9 + TODO:: A reprendre pour le cas des étudiants à l'étranger """ etudid = identite.etudid reponse = False etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] (code, parcours) = sco_report.get_code_cursus_etud(etud) - # Est-il réorienté ou démissionnaire ? - if ( - len(codes_cursus.CODES_SEM_REO & set(parcours.values())) > 0 - ): # Eliminé car NAR apparait dans le parcours - if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: - pe_tools.pe_print(" -> à éliminer car réorienté (NAR)") - return True - - if "DEM" in list(parcours.values()): # Eliminé car DEM - if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: - pe_tools.pe_print(" -> à éliminer car DEM") - return True - - # A-t-il arrêté volontairement sa formation ? + """Son dernier semestre en date""" dernier_formsemestre = identite.get_formsemestres()[0] + numero_dernier_formsemestre = dernier_formsemestre.semestre_id - # Y-a-t-il des cosemestres dans lesquels il aurait pu s'incrire ? + """Les numéro de semestres possible dans lesquels il pourrait s'incrire""" + if numero_dernier_formsemestre % 2 == 1: # semestre impair + numeros_possibles = list(range(numero_dernier_formsemestre+1, pe_tools.)) + + """Y-a-t-il des cosemestres dans lesquels il aurait pu s'incrire ?""" formsestres_superieurs_possibles = [] for fid, sem in cosemestres.items(): # Les semestres ayant des inscrits if (