From d3fe08689e750edf6e774a75e8b1150653e329d3 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Wed, 9 Feb 2022 18:43:03 +0100 Subject: [PATCH 1/8] Fix: calcul moy avec ue_cap quand ue courante NaN --- app/comp/res_common.py | 13 +++++++++---- app/scodoc/sco_formsemestre_validation.py | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/comp/res_common.py b/app/comp/res_common.py index 1aa993e85..cad318972 100644 --- a/app/comp/res_common.py +++ b/app/comp/res_common.py @@ -233,24 +233,29 @@ class ResultatsSemestre(ResultatsCache): "ue": ue.to_dict(), "formsemestre_id": None, "capitalized_ue_id": None, + "ects_pot": 0.0, } cur_moy_ue = self.etud_moy_ue[ue_id][etudid] moy_ue = cur_moy_ue is_capitalized = False if etudid in self.validations.ue_capitalisees.index: ue_cap = self._get_etud_ue_cap(etudid, ue) - if ue_cap is not None and not ue_cap.empty: - if ue_cap["moy_ue"] > cur_moy_ue: + if ( + ue_cap is not None + and not ue_cap.empty + and not np.isnan(ue_cap["moy_ue"]) + ): + if ue_cap["moy_ue"] > cur_moy_ue or np.isnan(cur_moy_ue): moy_ue = ue_cap["moy_ue"] is_capitalized = True - if is_capitalized: - coef_ue = 1.0 + coef_ue = self.etud_coef_ue_df[ue_id][etudid] return { "is_capitalized": is_capitalized, "is_external": ue_cap["is_external"] if is_capitalized else ue.is_external, "coef_ue": coef_ue, + "ects_pot": ue.ects or 0.0, "cur_moy_ue": cur_moy_ue, "moy": moy_ue, "event_date": ue_cap["event_date"] if is_capitalized else None, diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py index 425d13946..138dc74f3 100644 --- a/app/scodoc/sco_formsemestre_validation.py +++ b/app/scodoc/sco_formsemestre_validation.py @@ -702,7 +702,7 @@ def formsemestre_recap_parcours_table( ) # total ECTS (affiché sous la moyenne générale) H.append( - 'ECTS:%g' + 'ECTS:%g' % (etud_ects_infos["ects_pot"]) ) H.append('') From 4465a735fc6cdbefa52a3aabfb3b867155a7ee1a Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Wed, 9 Feb 2022 23:22:00 +0100 Subject: [PATCH 2/8] =?UTF-8?q?WIP:=20=C3=A9limination=20de=20notes=5Ftabl?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/bulletin_but.py | 89 +++++++++++++++++--------------- app/comp/res_common.py | 36 ++++++++++++- app/pe/pe_semestretag.py | 13 +++-- app/scodoc/notes_table.py | 4 -- app/scodoc/sco_bulletins.py | 10 +++- app/scodoc/sco_bulletins_json.py | 14 +++-- app/scodoc/sco_bulletins_xml.py | 10 ++-- app/scodoc/sco_evaluations.py | 17 +++--- app/scodoc/sco_formsemestre.py | 2 +- app/scodoc/sco_parcours_dut.py | 78 ++++++++++++++++++---------- app/scodoc/sco_pvjury.py | 17 +++--- app/scodoc/sco_recapcomplet.py | 2 +- 12 files changed, 184 insertions(+), 108 deletions(-) diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py index 9a886efff..70a83a5b5 100644 --- a/app/but/bulletin_but.py +++ b/app/but/bulletin_but.py @@ -9,6 +9,7 @@ import datetime from flask import url_for, g +from app.models.formsemestre import FormSemestre from app.scodoc import sco_utils as scu from app.scodoc import sco_bulletins_json @@ -18,30 +19,35 @@ from app.scodoc.sco_utils import fmt_note from app.comp.res_but import ResultatsSemestreBUT -class BulletinBUT(ResultatsSemestreBUT): +class BulletinBUT: """Génération du bulletin BUT. Cette classe génère des dictionnaires avec toutes les informations du bulletin, qui sont immédiatement traduisibles en JSON. """ + def __init__(self, formsemestre: FormSemestre): + """ """ + self.res = ResultatsSemestreBUT(formsemestre) + def etud_ue_mod_results(self, etud, ue, modimpls) -> dict: "dict synthèse résultats dans l'UE pour les modules indiqués" + res = self.res d = {} - etud_idx = self.etud_index[etud.id] + etud_idx = res.etud_index[etud.id] if ue.type != UE_SPORT: - ue_idx = self.modimpl_coefs_df.index.get_loc(ue.id) - etud_moy_module = self.sem_cube[etud_idx] # module x UE + ue_idx = res.modimpl_coefs_df.index.get_loc(ue.id) + etud_moy_module = res.sem_cube[etud_idx] # module x UE for modimpl in modimpls: - if self.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit + if res.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit if ue.type != UE_SPORT: - coef = self.modimpl_coefs_df[modimpl.id][ue.id] + coef = res.modimpl_coefs_df[modimpl.id][ue.id] if coef > 0: d[modimpl.module.code] = { "id": modimpl.id, "coef": coef, "moyenne": fmt_note( etud_moy_module[ - self.modimpl_coefs_df.columns.get_loc(modimpl.id) + res.modimpl_coefs_df.columns.get_loc(modimpl.id) ][ue_idx] ), } @@ -55,40 +61,39 @@ class BulletinBUT(ResultatsSemestreBUT): def etud_ue_results(self, etud, ue): "dict synthèse résultats UE" + res = self.res d = { "id": ue.id, "titre": ue.titre, "numero": ue.numero, "type": ue.type, "ECTS": { - "acquis": 0, # XXX TODO voir jury + "acquis": 0, # XXX TODO voir jury #sco92 "total": ue.ects, }, "color": ue.color, "competence": None, # XXX TODO lien avec référentiel "moyenne": None, # Le bonus sport appliqué sur cette UE - "bonus": fmt_note(self.bonus_ues[ue.id][etud.id]) - if self.bonus_ues is not None and ue.id in self.bonus_ues + "bonus": fmt_note(res.bonus_ues[ue.id][etud.id]) + if res.bonus_ues is not None and ue.id in res.bonus_ues else fmt_note(0.0), - "malus": self.malus[ue.id][etud.id], - "capitalise": None, # "AAAA-MM-JJ" TODO - "ressources": self.etud_ue_mod_results(etud, ue, self.ressources), - "saes": self.etud_ue_mod_results(etud, ue, self.saes), + "malus": res.malus[ue.id][etud.id], + "capitalise": None, # "AAAA-MM-JJ" TODO #sco92 + "ressources": self.etud_ue_mod_results(etud, ue, res.ressources), + "saes": self.etud_ue_mod_results(etud, ue, res.saes), } if ue.type != UE_SPORT: - if sco_preferences.get_preference( - "bul_show_ue_rangs", self.formsemestre.id - ): - rangs, effectif = self.ue_rangs[ue.id] + if sco_preferences.get_preference("bul_show_ue_rangs", res.formsemestre.id): + rangs, effectif = res.ue_rangs[ue.id] rang = rangs[etud.id] else: rang, effectif = "", 0 d["moyenne"] = { - "value": fmt_note(self.etud_moy_ue[ue.id][etud.id]), - "min": fmt_note(self.etud_moy_ue[ue.id].min()), - "max": fmt_note(self.etud_moy_ue[ue.id].max()), - "moy": fmt_note(self.etud_moy_ue[ue.id].mean()), + "value": fmt_note(res.etud_moy_ue[ue.id][etud.id]), + "min": fmt_note(res.etud_moy_ue[ue.id].min()), + "max": fmt_note(res.etud_moy_ue[ue.id].max()), + "moy": fmt_note(res.etud_moy_ue[ue.id].mean()), "rang": rang, "total": effectif, # nb etud avec note dans cette UE } @@ -98,7 +103,7 @@ class BulletinBUT(ResultatsSemestreBUT): d["bonus_description"] = self.etud_bonus_description(etud.id) modimpls_spo = [ modimpl - for modimpl in self.formsemestre.modimpls_sorted + for modimpl in res.formsemestre.modimpls_sorted if modimpl.module.ue.type == UE_SPORT ] d["modules"] = self.etud_mods_results(etud, modimpls_spo) @@ -107,6 +112,7 @@ class BulletinBUT(ResultatsSemestreBUT): def etud_mods_results(self, etud, modimpls) -> dict: """dict synthèse résultats des modules indiqués, avec évaluations de chacun.""" + res = self.res d = {} # etud_idx = self.etud_index[etud.id] for modimpl in modimpls: @@ -123,8 +129,8 @@ class BulletinBUT(ResultatsSemestreBUT): # moy_indicative_mod = np.nanmean(self.sem_cube[etud_idx, mod_idx]) # except RuntimeWarning: # all nans in np.nanmean # pass - modimpl_results = self.modimpls_results[modimpl.id] - if self.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit + modimpl_results = res.modimpls_results[modimpl.id] + if res.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit d[modimpl.module.code] = { "id": modimpl.id, "titre": modimpl.module.titre, @@ -153,7 +159,7 @@ class BulletinBUT(ResultatsSemestreBUT): def etud_eval_results(self, etud, e) -> dict: "dict resultats d'un étudiant à une évaluation" # eval_notes est une pd.Series avec toutes les notes des étudiants inscrits - eval_notes = self.modimpls_results[e.moduleimpl_id].evals_notes[e.id] + eval_notes = self.res.modimpls_results[e.moduleimpl_id].evals_notes[e.id] notes_ok = eval_notes.where(eval_notes > scu.NOTES_ABSENCE).dropna() d = { "id": e.id, @@ -182,18 +188,18 @@ class BulletinBUT(ResultatsSemestreBUT): def etud_bonus_description(self, etudid): """description du bonus affichée dans la section "UE bonus".""" - if self.bonus_ues is None or self.bonus_ues.shape[1] == 0: + res = self.res + if res.bonus_ues is None or res.bonus_ues.shape[1] == 0: return "" - import random - bonus_vect = self.bonus_ues.loc[etudid] + bonus_vect = res.bonus_ues.loc[etudid] if bonus_vect.nunique() > 1: # détail UE par UE details = [ f"{fmt_note(bonus_vect[ue.id])} sur {ue.acronyme}" - for ue in self.ues - if self.modimpls_in_ue(ue.id, etudid) - and ue.id in self.bonus_ues + for ue in res.ues + if res.modimpls_in_ue(ue.id, etudid) + and ue.id in res.bonus_ues and bonus_vect[ue.id] > 0.0 ] if details: @@ -208,6 +214,7 @@ class BulletinBUT(ResultatsSemestreBUT): Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai (bulletins non publiés). """ + res = self.res etat_inscription = etud.etat_inscription(formsemestre.id) nb_inscrits = self.get_inscriptions_counts()[scu.INSCRIT] published = (not formsemestre.bul_hide_xml) or force_publishing @@ -235,7 +242,7 @@ class BulletinBUT(ResultatsSemestreBUT): "etapes": [str(x.etape_apo) for x in formsemestre.etapes if x.etape_apo], "date_debut": formsemestre.date_debut.isoformat(), "date_fin": formsemestre.date_fin.isoformat(), - "annee_universitaire": self.formsemestre.annee_scolaire_str(), + "annee_universitaire": formsemestre.annee_scolaire_str(), "numero": formsemestre.semestre_id, "inscription": "", # inutilisé mais nécessaire pour le js de Seb. "groupes": [], # XXX TODO @@ -251,24 +258,24 @@ class BulletinBUT(ResultatsSemestreBUT): semestre_infos.update( { "notes": { # moyenne des moyennes générales du semestre - "value": fmt_note(self.etud_moy_gen[etud.id]), - "min": fmt_note(self.etud_moy_gen.min()), - "moy": fmt_note(self.etud_moy_gen.mean()), - "max": fmt_note(self.etud_moy_gen.max()), + "value": fmt_note(res.etud_moy_gen[etud.id]), + "min": fmt_note(res.etud_moy_gen.min()), + "moy": fmt_note(res.etud_moy_gen.mean()), + "max": fmt_note(res.etud_moy_gen.max()), }, "rang": { # classement wrt moyenne général, indicatif - "value": self.etud_moy_gen_ranks[etud.id], + "value": res.etud_moy_gen_ranks[etud.id], "total": nb_inscrits, }, }, ) d.update( { - "ressources": self.etud_mods_results(etud, self.ressources), - "saes": self.etud_mods_results(etud, self.saes), + "ressources": self.etud_mods_results(etud, res.ressources), + "saes": self.etud_mods_results(etud, res.saes), "ues": { ue.acronyme: self.etud_ue_results(etud, ue) - for ue in self.ues + for ue in res.ues if self.modimpls_in_ue( ue.id, etud.id ) # si l'UE comporte des modules auxquels on est inscrit diff --git a/app/comp/res_common.py b/app/comp/res_common.py index cad318972..90cb8ebe6 100644 --- a/app/comp/res_common.py +++ b/app/comp/res_common.py @@ -20,7 +20,6 @@ from app.models import FormSemestre, Identite, ModuleImpl from app.models import FormSemestreUECoef from app.models.ues import UniteEns from app.scodoc import sco_utils as scu -from app.scodoc import sco_evaluations from app.scodoc.sco_cache import ResultatsSemestreCache from app.scodoc.sco_codes_parcours import UE_SPORT, ATT, DEF from app.scodoc.sco_exceptions import ScoValueError @@ -388,7 +387,7 @@ class NotesTableCompat(ResultatsSemestre): def compute_rangs(self): """Calcule les classements Moyenne générale: etud_moy_gen_ranks - Par UE: + Par UE (sauf ue bonus) """ self.etud_moy_gen_ranks = moy_sem.comp_ranks_series(self.etud_moy_gen) for ue in self.formsemestre.query_ues(): @@ -399,6 +398,37 @@ class NotesTableCompat(ResultatsSemestre): ) # .count() -> nb of non NaN values + def get_etud_ue_rang(self, ue_id, etudid) -> tuple[str, int]: + """Le rang de l'étudiant dans cette ue + Result: rang:str, effectif:str + """ + rangs, effectif = self.ue_rangs[ue_id] + if rangs is not None: + rang = rangs[etudid] + else: + return "", "" + return rang, effectif + + def etud_check_conditions_ues(self, etudid): + """Vrai si les conditions sur les UE sont remplies. + Ne considère que les UE ayant des notes (moyenne calculée). + (les UE sans notes ne sont pas comptées comme sous la barre) + Prend en compte les éventuelles UE capitalisées. + + Pour les parcours habituels, cela revient à vérifier que + les moyennes d'UE sont toutes > à leur barre (sauf celles sans notes) + + Pour les parcours non standards (LP2014), cela peut être plus compliqué. + + Return: True|False, message explicatif + """ + return self.parcours.check_barre_ues( + [ + self.get_etud_ue_status(etudid, ue.id) + for ue in self.formsemestre.query_ues() + ] + ) + def get_etud_decision_ues(self, etudid: int) -> dict: """Decisions du jury pour les UE de cet etudiant, ou None s'il n'y en pas eu. Ne tient pas compte des UE capitalisées. @@ -521,6 +551,8 @@ class NotesTableCompat(ResultatsSemestre): def get_evaluations_etats(self): """[ {...evaluation et son etat...} ]""" # TODO: à moderniser + from app.scodoc import sco_evaluations + if not hasattr(self, "_evaluations_etats"): self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem( self.formsemestre.id diff --git a/app/pe/pe_semestretag.py b/app/pe/pe_semestretag.py index 9a33f57ce..baa12b117 100644 --- a/app/pe/pe_semestretag.py +++ b/app/pe/pe_semestretag.py @@ -37,6 +37,7 @@ Created on Fri Sep 9 09:15:05 2016 """ from app import log +from app.models.ues import UniteEns from app.scodoc import sco_codes_parcours from app.scodoc import sco_cache from app.scodoc import sco_tag_module @@ -238,7 +239,7 @@ class SemestreTag(pe_tagtable.TableTag): etudid ) # les ue capitalisées des étudiants ue_capitalisees_id = [ - ue["ue_id"] for ue in ue_capitalisees + ue.id for ue in ue_capitalisees ] # les id des ue capitalisées # Si le module ne fait pas partie des UE capitalisées @@ -260,7 +261,7 @@ class SemestreTag(pe_tagtable.TableTag): fids_prec = [ ue["formsemestre_id"] for ue in ue_capitalisees - if ue["ue_code"] == modimpl["ue"]["ue_code"] + if ue.ue_code == modimpl["ue"]["ue_code"] ] # and ue['semestre_id'] == semestre_id] if len(fids_prec) > 0: # => le formsemestre_id du semestre dont vient la capitalisation @@ -299,10 +300,12 @@ class SemestreTag(pe_tagtable.TableTag): return (note, coeff_norm) # ----------------------------------------------------------------------------- - def get_ue_capitalisees(self, etudid): + def get_ue_capitalisees(self, etudid) -> list[UniteEns]: """Renvoie la liste des ue_id effectivement capitalisées par un étudiant""" - # return [ ue for ue in self.nt.ue_capitalisees[etudid] if self.nt.get_etud_ue_status(etudid,ue['ue_id'])['is_capitalized'] ] - return self.nt.ue_capitalisees[etudid] + ue_ids = [ + ue_id for ue_id in self.nt.validations.ue_capitalisees.loc[etudid]["ue_id"] + ] + return [UniteEns.query.get(ue_id) for ue_id in ue_ids] # ----------------------------------------------------------------------------- def get_listesNotesEtCoeffsTagEtudiant(self, tag, etudid): diff --git a/app/scodoc/notes_table.py b/app/scodoc/notes_table.py index e5077543b..d4db93382 100644 --- a/app/scodoc/notes_table.py +++ b/app/scodoc/notes_table.py @@ -1314,10 +1314,6 @@ class NotesTable: return self._evaluations_etats - def get_sem_evaluation_etat_list(self): - """Liste des evaluations de ce semestre, avec leur etat""" - return self.get_evaluations_etats() - def get_mod_evaluation_etat_list(self, moduleimpl_id) -> list[dict]: """Liste des évaluations de ce module""" return [ diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index 37299c3c3..41f79ce07 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -366,9 +366,15 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"): # log('cap details %s' % ue_status['moy']) if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]: # detail des modules de l'UE capitalisee - nt_cap = sco_cache.NotesTableCache.get( + # nt_cap = sco_cache.NotesTableCache.get( + # ue_status["formsemestre_id"] + # ) # > toutes notes + formsemestre_cap = FormSemestre.query.get_or_404( ue_status["formsemestre_id"] - ) # > toutes notes + ) + nt_cap: NotesTableCompat = res_sem.load_formsemestre_results( + formsemestre_cap + ) u["modules_capitalized"], _ = _ue_mod_bulletin( etudid, diff --git a/app/scodoc/sco_bulletins_json.py b/app/scodoc/sco_bulletins_json.py index 31271822d..f25cdfcfe 100644 --- a/app/scodoc/sco_bulletins_json.py +++ b/app/scodoc/sco_bulletins_json.py @@ -32,13 +32,14 @@ import datetime import json from app.but import bulletin_but +from app.comp import res_sem +from app.comp.res_common import NotesTableCompat from app.models.formsemestre import FormSemestre from app.models.etudiants import Identite import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc import sco_abs -from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_evaluation_db from app.scodoc import sco_formsemestre @@ -90,11 +91,7 @@ def formsemestre_bulletinetud_published_dict( etud = Identite.query.get(etudid) sem = sco_formsemestre.get_formsemestre(formsemestre_id) - if formsemestre.formation.is_apc(): - nt = bulletin_but.APCNotesTableCompat(formsemestre) - else: - nt = sco_cache.NotesTableCache.get(formsemestre_id) - + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) d = {} if (not sem["bul_hide_xml"]) or force_publishing: @@ -205,6 +202,7 @@ def formsemestre_bulletinetud_published_dict( ects_txt = "" else: ects_txt = f"{ue['ects']:2.3g}" + rang, effectif = nt.get_etud_ue_rang(ue["ue_id"], etudid) u = dict( id=ue["ue_id"], numero=scu.quote_xml_attr(ue["numero"]), @@ -218,8 +216,8 @@ def formsemestre_bulletinetud_published_dict( ue["moy"] ), # CM : ajout pour faire apparaitre la moyenne des UE ), - rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]), - effectif=str(nt.ue_rangs[ue["ue_id"]][1]), + rang=rang, + effectif=effectif, ects=ects_txt, code_apogee=scu.quote_xml_attr(ue["code_apogee"]), ) diff --git a/app/scodoc/sco_bulletins_xml.py b/app/scodoc/sco_bulletins_xml.py index 5d6ba7def..fda6869c3 100644 --- a/app/scodoc/sco_bulletins_xml.py +++ b/app/scodoc/sco_bulletins_xml.py @@ -44,6 +44,8 @@ import datetime from xml.etree import ElementTree from xml.etree.ElementTree import Element +from app.comp import res_sem +from app.comp.res_common import NotesTableCompat import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app import log @@ -152,7 +154,8 @@ def make_xml_formsemestre_bulletinetud( pid = partition["partition_id"] partitions_etud_groups[pid] = sco_groups.get_etud_groups_in_partition(pid) - nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes + formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) ues = nt.get_ues_stat_dict() modimpls = nt.get_modimpls_dict() nbetuds = len(nt.etud_moy_gen_ranks) @@ -230,8 +233,9 @@ def make_xml_formsemestre_bulletinetud( except (ValueError, TypeError): ects_txt = "" x_ue.append(Element("ects", value=ects_txt)) - x_ue.append(Element("rang", value=str(nt.ue_rangs[ue["ue_id"]][0][etudid]))) - x_ue.append(Element("effectif", value=str(nt.ue_rangs[ue["ue_id"]][1]))) + rang, effectif = nt.get_etud_ue_rang(ue["ue_id"], etudid) + x_ue.append(Element("rang", value=str(rang))) + x_ue.append(Element("effectif", value=str(effectif))) # Liste les modules de l'UE ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]] for modimpl in ue_modimpls: diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py index c54806e23..67c8efb60 100644 --- a/app/scodoc/sco_evaluations.py +++ b/app/scodoc/sco_evaluations.py @@ -31,13 +31,17 @@ import datetime import operator import time -import flask from flask import url_for from flask import g from flask_login import current_user from flask import request from app import log + +from app.comp import res_sem +from app.comp.res_common import NotesTableCompat +from app.models import FormSemestre + import app.scodoc.sco_utils as scu from app.scodoc.sco_utils import ModuleType import app.scodoc.notesdb as ndb @@ -379,10 +383,9 @@ def _eval_etat(evals): def do_evaluation_etat_in_sem(formsemestre_id): """-> nb_eval_completes, nb_evals_en_cours, nb_evals_vides, date derniere modif, attente""" - nt = sco_cache.NotesTableCache.get( - formsemestre_id - ) # > liste evaluations et moduleimpl en attente - evals = nt.get_sem_evaluation_etat_list() + formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) + evals = nt.get_evaluations_etats() etat = _eval_etat(evals) # Ajoute information sur notes en attente etat["attente"] = len(nt.get_moduleimpls_attente()) > 0 @@ -403,7 +406,7 @@ def formsemestre_evaluations_cal(formsemestre_id): sem = sco_formsemestre.get_formsemestre(formsemestre_id) nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations - evals = nt.get_sem_evaluation_etat_list() + evals = nt.get_evaluations_etats() nb_evals = len(evals) color_incomplete = "#FF6060" @@ -538,7 +541,7 @@ def formsemestre_evaluations_delai_correction(formsemestre_id, format="html"): sem = sco_formsemestre.get_formsemestre(formsemestre_id) nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations - evals = nt.get_sem_evaluation_etat_list() + evals = nt.get_evaluations_etats() T = [] for e in evals: M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=e["moduleimpl_id"])[0] diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py index f51afd791..e5f8129e8 100644 --- a/app/scodoc/sco_formsemestre.py +++ b/app/scodoc/sco_formsemestre.py @@ -342,7 +342,7 @@ def do_formsemestre_uecoef_delete(cnx, formsemestre_id, ue_id): formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"]) -def read_formsemestre_etapes(formsemestre_id): +def read_formsemestre_etapes(formsemestre_id): # OBSOLETE """recupere liste des codes etapes associés à ce semestre :returns: liste d'instance de ApoEtapeVDI """ diff --git a/app/scodoc/sco_parcours_dut.py b/app/scodoc/sco_parcours_dut.py index 0d682c017..4214b70bc 100644 --- a/app/scodoc/sco_parcours_dut.py +++ b/app/scodoc/sco_parcours_dut.py @@ -28,7 +28,10 @@ """Semestres: gestion parcours DUT (Arreté du 13 août 2005) """ -from app.models.ues import UniteEns +from app.comp import res_sem +from app.comp.res_common import NotesTableCompat +from app.models import FormSemestre, UniteEns + import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app import log @@ -108,9 +111,11 @@ class DecisionSem(object): def SituationEtudParcours(etud, formsemestre_id): """renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)""" - nt = sco_cache.NotesTableCache.get( - formsemestre_id - ) # > get_etud_decision_sem, get_etud_moy_gen, get_ues_stat_dict, get_etud_ue_status, etud_check_conditions_ues + # nt = sco_cache.NotesTableCache.get( + # formsemestre_id + # ) # > get_etud_decision_sem, get_etud_moy_gen, get_ues_stat_dict, get_etud_ue_status, etud_check_conditions_ues + formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) parcours = nt.parcours # if parcours.ECTS_ONLY: @@ -131,7 +136,7 @@ class SituationEtudParcoursGeneric(object): self.formsemestre_id = formsemestre_id self.sem = sco_formsemestre.get_formsemestre(formsemestre_id) self.nt = nt - self.formation = self.nt.formation + self.formation = self.nt.formsemestre.formation self.parcours = self.nt.parcours # Ce semestre est-il le dernier de la formation ? (e.g. semestre 4 du DUT) # pour le DUT, le dernier est toujours S4. @@ -295,11 +300,15 @@ class SituationEtudParcoursGeneric(object): for sem in self.get_semestres(): if ( sem["semestre_id"] == n1 - and sem["formation_code"] == self.formation["formation_code"] + and sem["formation_code"] == self.formation.formation_code ): - nt = sco_cache.NotesTableCache.get( - sem["formsemestre_id"] - ) # > get_etud_decision_sem + # nt = sco_cache.NotesTableCache.get( + # sem["formsemestre_id"] + # ) # > get_etud_decision_sem + formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"]) + nt: NotesTableCompat = res_sem.load_formsemestre_results( + formsemestre + ) decision = nt.get_etud_decision_sem(self.etudid) if decision and ( code_semestre_validant(decision["code"]) @@ -312,10 +321,12 @@ class SituationEtudParcoursGeneric(object): """True si les semestres dont les indices sont donnés en argument (modifié) sont validés. En sortie, sem_idx_set contient ceux qui n'ont pas été validés.""" for sem in self.get_semestres(): - if sem["formation_code"] == self.formation["formation_code"]: - nt = sco_cache.NotesTableCache.get( - sem["formsemestre_id"] - ) # > get_etud_decision_sem + if sem["formation_code"] == self.formation.formation_code: + # nt = sco_cache.NotesTableCache.get( + # sem["formsemestre_id"] + # ) # > get_etud_decision_sem + formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"]) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) decision = nt.get_etud_decision_sem(self.etudid) if decision and code_semestre_validant(decision["code"]): # validé @@ -331,9 +342,11 @@ class SituationEtudParcoursGeneric(object): ue_acros = {} # acronyme ue : 1 nb_max_ue = 0 for sem in sems: - nt = sco_cache.NotesTableCache.get( - sem["formsemestre_id"] - ) # > get_ues_stat_dict + # nt = sco_cache.NotesTableCache.get( + # sem["formsemestre_id"] + # ) # > get_ues_stat_dict + formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"]) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) ues = nt.get_ues_stat_dict(filter_sport=True) for ue in ues: ue_acros[ue["acronyme"]] = 1 @@ -401,9 +414,11 @@ class SituationEtudParcoursGeneric(object): if not sem: code = "" # non inscrit à ce semestre else: - nt = sco_cache.NotesTableCache.get( - sem["formsemestre_id"] - ) # > get_etud_decision_sem + # nt = sco_cache.NotesTableCache.get( + # sem["formsemestre_id"] + # ) # > get_etud_decision_sem + formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"]) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) decision = nt.get_etud_decision_sem(self.etudid) if decision: code = decision["code"] @@ -459,7 +474,7 @@ class SituationEtudParcoursGeneric(object): prev = None while i >= 0: if ( - self.sems[i]["formation_code"] == self.formation["formation_code"] + self.sems[i]["formation_code"] == self.formation.formation_code and self.sems[i]["semestre_id"] == cur["semestre_id"] - 1 ): prev = self.sems[i] @@ -471,8 +486,9 @@ class SituationEtudParcoursGeneric(object): # Verifications basiques: # ? # Code etat du semestre precedent: - nt = sco_cache.NotesTableCache.get(prev["formsemestre_id"]) - # > get_etud_decision_sem, get_etud_moy_gen, etud_check_conditions_ues + # nt = sco_cache.NotesTableCache.get(prev["formsemestre_id"]) + formsemestre = FormSemestre.query.get_or_404(prev["formsemestre_id"]) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) self.prev_decision = nt.get_etud_decision_sem(self.etudid) self.prev_moy_gen = nt.get_etud_moy_gen(self.etudid) self.prev_barres_ue_ok = nt.etud_check_conditions_ues(self.etudid)[0] @@ -526,11 +542,15 @@ class SituationEtudParcoursGeneric(object): validated = False for sem in self.sems: if ( - sem["formation_code"] == self.formation["formation_code"] + sem["formation_code"] == self.formation.formation_code and sem["semestre_id"] == s ): - nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) + # nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) # > get_etud_decision_sem + formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"]) + nt: NotesTableCompat = res_sem.load_formsemestre_results( + formsemestre + ) decision = nt.get_etud_decision_sem(self.etudid) if decision and code_semestre_validant(decision["code"]): validated = True @@ -642,7 +662,7 @@ class SituationEtudParcoursGeneric(object): cnx, { "etudid": self.etudid, - "formation_code": self.formation["formation_code"], + "formation_code": self.formation.formation_code, "semestre_id": next_semestre_id, "origin_formsemestre_id": self.formsemestre_id, }, @@ -904,9 +924,11 @@ def formsemestre_validate_ues(formsemestre_id, etudid, code_etat_sem, assiduite) """ valid_semestre = CODES_SEM_VALIDES.get(code_etat_sem, False) cnx = ndb.GetDBConnexion() - nt = sco_cache.NotesTableCache.get( - formsemestre_id - ) # > get_ues_stat_dict, get_etud_ue_status + # nt = sco_cache.NotesTableCache.get( + # formsemestre_id + # ) # > get_ues_stat_dict, get_etud_ue_status + formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) ue_ids = [x["ue_id"] for x in nt.get_ues_stat_dict(filter_sport=True)] for ue_id in ue_ids: ue_status = nt.get_etud_ue_status(etudid, ue_id) diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index 4479409d0..aa741c0a1 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -53,7 +53,10 @@ from reportlab.lib import styles import flask from flask import url_for, g, request -from app.models.ues import UniteEns + +from app.comp import res_sem +from app.comp.res_common import NotesTableCompat +from app.models import FormSemestre, UniteEns import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb @@ -98,9 +101,9 @@ def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem): except: log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue)) # Les UE capitalisées dans d'autres semestres: - for ue in nt.ue_capitalisees[etudid]: + for ue_id in nt.validations.ue_capitalisees.loc[etudid]["ue_id"]: try: - uelist.append(nt.get_etud_ue_status(etudid, ue["ue_id"])["ue"]) + uelist.append(nt.get_etud_ue_status(etudid, ue_id)["ue"]) except KeyError: pass uelist.sort(key=itemgetter("numero")) @@ -213,9 +216,11 @@ def dict_pvjury( 'decisions_dict' : { etudid : decision (comme ci-dessus) }, } """ - nt = sco_cache.NotesTableCache.get( - formsemestre_id - ) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues + # nt = sco_cache.NotesTableCache.get( + # formsemestre_id + # ) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues + formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) if etudids is None: etudids = nt.get_etudids() if not etudids: diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index 3b45330d8..fa569e5ca 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -977,7 +977,7 @@ def _formsemestre_recapcomplet_json( def formsemestres_bulletins(annee_scolaire): """Tous les bulletins des semestres publiés des semestres de l'année indiquée. - :param annee_scolaire(int): année de début de l'année scoalaire + :param annee_scolaire(int): année de début de l'année scolaire :returns: JSON """ jslist = [] From f5bc6fb1d197d3abb2e1ee3a7174a3c27d9f827d Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 10 Feb 2022 11:54:03 +0100 Subject: [PATCH 3/8] =?UTF-8?q?affiche=20UE=20capitalis=C3=A9es=20sur=20bu?= =?UTF-8?q?lletins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_bulletins.py | 14 ++++++-------- app/scodoc/sco_bulletins_legacy.py | 2 +- app/scodoc/sco_bulletins_standard.py | 8 +++++++- app/static/css/scodoc.css | 11 +++++++++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index 41f79ce07..beb224d0e 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -352,18 +352,16 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"): ] = [] # modules de l'UE capitalisée (liste vide si pas capitalisée) if ue_status["is_capitalized"]: sem_origin = sco_formsemestre.get_formsemestre(ue_status["formsemestre_id"]) - u["ue_descr_txt"] = "Capitalisée le %s" % ndb.DateISOtoDMY( + u["ue_descr_txt"] = "capitalisée le %s" % ndb.DateISOtoDMY( ue_status["event_date"] ) u[ "ue_descr_html" - ] = '%s' % ( - sem_origin["formsemestre_id"], - etudid, - sem_origin["titreannee"], - u["ue_descr_txt"], - ) - # log('cap details %s' % ue_status['moy']) + ] = f"""{u["ue_descr_txt"]} pouet + """ if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]: # detail des modules de l'UE capitalisee # nt_cap = sco_cache.NotesTableCache.get( diff --git a/app/scodoc/sco_bulletins_legacy.py b/app/scodoc/sco_bulletins_legacy.py index 8be1d0c50..fcc714e35 100644 --- a/app/scodoc/sco_bulletins_legacy.py +++ b/app/scodoc/sco_bulletins_legacy.py @@ -169,7 +169,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator): ) ) - # Contenu table: UE apres UE + # Contenu table: UE après UE for ue in I["ues"]: ue_descr = ue["ue_descr_html"] coef_ue = ue["coef_ue_txt"] diff --git a/app/scodoc/sco_bulletins_standard.py b/app/scodoc/sco_bulletins_standard.py index 12dd9d12b..0cae4b92e 100644 --- a/app/scodoc/sco_bulletins_standard.py +++ b/app/scodoc/sco_bulletins_standard.py @@ -430,7 +430,13 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator): t = { "titre": ue["acronyme"] + " " + ue["titre"], - "_titre_html": plusminus + ue["acronyme"] + " " + ue["titre"], + "_titre_html": plusminus + + ue["acronyme"] + + " " + + ue["titre"] + + ' ' + + ue["ue_descr_txt"] + + "", "_titre_help": ue["ue_descr_txt"], "_titre_colspan": 2, "module": ue_descr, diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css index 8ca51f7b5..e88930857 100644 --- a/app/static/css/scodoc.css +++ b/app/static/css/scodoc.css @@ -1959,7 +1959,6 @@ tr.notes_bulletin_row_ue { tr.bul_row_ue_cur { background-color: rgb(180,180,180); - color: rgb(50,50,50); } tr.bul_row_ue_cap { @@ -2004,6 +2003,11 @@ tr.notes_bulletin_row_eval td.module { border-left: 1px dashed rgb(170,170,170); } +span.bul_ue_descr { + font-weight: normal; + font-style: italic; +} + table.notes_bulletin td.note { padding-left: 1em; } @@ -2012,10 +2016,13 @@ table.notes_bulletin td.min, table.notes_bulletin td.max, table.notes_bulletin t } table.notes_bulletin tr.notes_bulletin_row_ue_cur td.note, table.notes_bulletin tr.notes_bulletin_row_ue_cur td.min, table.notes_bulletin tr.notes_bulletin_row_ue_cur td.max { - color: rgb(80,80,80); font-style: italic; } +table.notes_bulletin tr.bul_row_ue_cur td, table.notes_bulletin tr.bul_row_ue_cur td a { + color:rgb(114, 89, 89); +} + .note_bold { font-weight: bold; } From c05660bf839143573302bd1f11377f067ab77163 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 10 Feb 2022 12:13:24 +0100 Subject: [PATCH 4/8] Fix 2 bugs / fiche etud --- app/models/etudiants.py | 1 + app/scodoc/sco_formsemestre_validation.py | 4 ++-- app/scodoc/sco_pvjury.py | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/models/etudiants.py b/app/models/etudiants.py index 35c3fc858..ff91981b6 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -123,6 +123,7 @@ class Identite(db.Model): e = dict(self.__dict__) e.pop("_sa_instance_state", None) # ScoDoc7 output_formators: (backward compat) + e["etudid"] = self.id e["date_naissance"] = ndb.DateISOtoDMY(e["date_naissance"]) return {k: e[k] or "" for k in e} # convert_null_outputs_to_empty diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py index 138dc74f3..7148ad166 100644 --- a/app/scodoc/sco_formsemestre_validation.py +++ b/app/scodoc/sco_formsemestre_validation.py @@ -560,7 +560,7 @@ def formsemestre_recap_parcours_table( else: type_sem = "" class_sem = "sem_autre" - if sem["formation_code"] != Se.formation["formation_code"]: + if sem["formation_code"] != Se.formation.formation_code: class_sem += " sem_autre_formation" if sem["bul_bgcolor"]: bgcolor = sem["bul_bgcolor"] @@ -628,7 +628,7 @@ def formsemestre_recap_parcours_table( if not sem["etat"]: # locked lockicon = scu.icontag("lock32_img", title="verrouillé", border="0") default_sem_info += lockicon - if sem["formation_code"] != Se.formation["formation_code"]: + if sem["formation_code"] != Se.formation.formation_code: default_sem_info += "Autre formation: %s" % sem["formation_code"] H.append( '%s%s' diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index aa741c0a1..828719080 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -101,11 +101,12 @@ def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem): except: log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue)) # Les UE capitalisées dans d'autres semestres: - for ue_id in nt.validations.ue_capitalisees.loc[etudid]["ue_id"]: - try: - uelist.append(nt.get_etud_ue_status(etudid, ue_id)["ue"]) - except KeyError: - pass + if etudid in nt.validations.ue_capitalisees.index: + for ue_id in nt.validations.ue_capitalisees.loc[etudid]["ue_id"]: + try: + uelist.append(nt.get_etud_ue_status(etudid, ue_id)["ue"]) + except KeyError: + pass uelist.sort(key=itemgetter("numero")) return uelist From 78e97a43e4567f0d933a7a1a8eefedf231a7f101 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 10 Feb 2022 12:42:07 +0100 Subject: [PATCH 5/8] Tableau recap: affichage UE cap. --- app/comp/res_common.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/app/comp/res_common.py b/app/comp/res_common.py index 90cb8ebe6..ea17bb14a 100644 --- a/app/comp/res_common.py +++ b/app/comp/res_common.py @@ -484,7 +484,7 @@ class NotesTableCompat(ResultatsSemestre): def get_etud_moy_gen(self, etudid): # -> float | str """Moyenne générale de cet etudiant dans ce semestre. - Prend(ra) en compte les UE capitalisées. (TODO) XXX + Prend en compte les UE capitalisées. Si apc, moyenne indicative. Si pas de notes: 'NA' """ @@ -610,7 +610,7 @@ class NotesTableCompat(ResultatsSemestre): """ table_moyennes = [] etuds_inscriptions = self.formsemestre.etuds_inscriptions - + ues = self.formsemestre.query_ues() # sans bonus for etudid in etuds_inscriptions: moy_gen = self.etud_moy_gen.get(etudid, False) if moy_gen is False: @@ -621,11 +621,19 @@ class NotesTableCompat(ResultatsSemestre): + ["NI"] * len(self.formsemestre.modimpls_sorted) ) else: - moy_ues = self.etud_moy_ue.loc[etudid] + moy_ues = [] + ue_is_cap = {} + for ue in ues: + ue_status = self.get_etud_ue_status(etudid, ue.id) + moy_ues.append(ue_status["moy"]) + ue_is_cap[ue.id] = ue_status["is_capitalized"] t = [moy_gen] + list(moy_ues) - # TODO UE capitalisées: ne pas afficher moyennes modules + # Moyennes modules: for modimpl in self.formsemestre.modimpls_sorted: - val = self.get_etud_mod_moy(modimpl.id, etudid) + if ue_is_cap.get(modimpl.module.ue.id, False): + val = "-c-" + else: + val = self.get_etud_mod_moy(modimpl.id, etudid) t.append(val) t.append(etudid) table_moyennes.append(t) From 38d7f31408e456d71abdd722465459cd20f39816 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 10 Feb 2022 14:34:16 +0100 Subject: [PATCH 6/8] Fix (bul BUT) --- app/but/bulletin_but.py | 10 ++++++---- app/comp/res_common.py | 2 -- app/scodoc/notes_table.py | 4 ++-- app/scodoc/sco_recapcomplet.py | 2 +- app/views/notes.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py index 70a83a5b5..2f1637fbb 100644 --- a/app/but/bulletin_but.py +++ b/app/but/bulletin_but.py @@ -123,7 +123,8 @@ class BulletinBUT: # np.nanmean(self.sem_cube[:, mod_idx, :], axis=1), # copy=False, # ) - # except RuntimeWarning: # all nans in np.nanmean (sur certains etuds sans notes valides) + # except RuntimeWarning: + # # all nans in np.nanmean (sur certains etuds sans notes valides) # pass # try: # moy_indicative_mod = np.nanmean(self.sem_cube[etud_idx, mod_idx]) @@ -141,7 +142,8 @@ class BulletinBUT: moduleimpl_id=modimpl.id, ), "moyenne": { - # # moyenne indicative de module: moyenne des UE, ignorant celles sans notes (nan) + # # moyenne indicative de module: moyenne des UE, + # # ignorant celles sans notes (nan) # "value": fmt_note(moy_indicative_mod), # "min": fmt_note(moyennes_etuds.min()), # "max": fmt_note(moyennes_etuds.max()), @@ -216,7 +218,7 @@ class BulletinBUT: """ res = self.res etat_inscription = etud.etat_inscription(formsemestre.id) - nb_inscrits = self.get_inscriptions_counts()[scu.INSCRIT] + nb_inscrits = self.res.get_inscriptions_counts()[scu.INSCRIT] published = (not formsemestre.bul_hide_xml) or force_publishing d = { "version": "0", @@ -276,7 +278,7 @@ class BulletinBUT: "ues": { ue.acronyme: self.etud_ue_results(etud, ue) for ue in res.ues - if self.modimpls_in_ue( + if self.res.modimpls_in_ue( ue.id, etud.id ) # si l'UE comporte des modules auxquels on est inscrit }, diff --git a/app/comp/res_common.py b/app/comp/res_common.py index ea17bb14a..616ddb719 100644 --- a/app/comp/res_common.py +++ b/app/comp/res_common.py @@ -9,8 +9,6 @@ from functools import cached_property import numpy as np import pandas as pd -from flask import g - from app.comp.aux_stats import StatsMoyenne from app.comp import moy_sem from app.comp.res_cache import ResultatsCache diff --git a/app/scodoc/notes_table.py b/app/scodoc/notes_table.py index d4db93382..d014d9faf 100644 --- a/app/scodoc/notes_table.py +++ b/app/scodoc/notes_table.py @@ -410,7 +410,7 @@ class NotesTable: return "" def get_etud_etat_html(self, etudid): - + etat = self.inscrdict[etudid]["etat"] if etat == "I": return "" elif etat == "D": @@ -1169,7 +1169,7 @@ class NotesTable: and moy_ue_cap >= self.parcours.NOTES_BARRE_VALID_UE ): if not cnx: - cnx = ndb.GetDBConnexion(autocommit=False) + cnx = ndb.GetDBConnexion() sco_parcours_dut.do_formsemestre_validate_ue( cnx, nt_cap, diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index fa569e5ca..3b87f8f58 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -495,7 +495,7 @@ def make_formsemestre_recapcomplet( j += 1 if not hidebac: for k in admission_extra_cols: - l.append(getattr(e["admission"], k, "")) + l.append(getattr(e["admission"], k, "") or "") l.append( nt.identdict[etudid]["code_nip"] or "" ) # avant-derniere colonne = code_nip diff --git a/app/views/notes.py b/app/views/notes.py index 0762a5cee..afd7b855c 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -133,7 +133,7 @@ from app.scodoc.TrivialFormulator import TrivialFormulator from app.views import ScoData -def sco_publish(route, function, permission, methods=["GET"]): +def sco_publish(route, function, permission, methods=("GET",)): """Declare a route for a python function, protected by permission and called following ScoDoc 7 Zope standards. """ From 2c8eee1432bc384cae397a2f1457272cfe2959c9 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 10 Feb 2022 14:46:52 +0100 Subject: [PATCH 7/8] Fix (jury) --- app/pe/pe_semestretag.py | 3 ++- app/scodoc/sco_pvjury.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/pe/pe_semestretag.py b/app/pe/pe_semestretag.py index baa12b117..695bbe5e6 100644 --- a/app/pe/pe_semestretag.py +++ b/app/pe/pe_semestretag.py @@ -303,7 +303,8 @@ class SemestreTag(pe_tagtable.TableTag): def get_ue_capitalisees(self, etudid) -> list[UniteEns]: """Renvoie la liste des ue_id effectivement capitalisées par un étudiant""" ue_ids = [ - ue_id for ue_id in self.nt.validations.ue_capitalisees.loc[etudid]["ue_id"] + ue_id + for ue_id in self.nt.validations.ue_capitalisees.loc[[etudid]]["ue_id"] ] return [UniteEns.query.get(ue_id) for ue_id in ue_ids] diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index 828719080..78ec14394 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -102,7 +102,7 @@ def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem): log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue)) # Les UE capitalisées dans d'autres semestres: if etudid in nt.validations.ue_capitalisees.index: - for ue_id in nt.validations.ue_capitalisees.loc[etudid]["ue_id"]: + for ue_id in nt.validations.ue_capitalisees.loc[[etudid]]["ue_id"]: try: uelist.append(nt.get_etud_ue_status(etudid, ue_id)["ue"]) except KeyError: From 4b7297bf1e854930c8c57f5f82a993a35962bffa Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 10 Feb 2022 15:29:51 +0100 Subject: [PATCH 8/8] moduleimpl_status sans nt --- app/scodoc/notes_table.py | 2 +- app/scodoc/sco_moduleimpl_status.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/scodoc/notes_table.py b/app/scodoc/notes_table.py index d014d9faf..a9aaf7e16 100644 --- a/app/scodoc/notes_table.py +++ b/app/scodoc/notes_table.py @@ -171,7 +171,7 @@ class NotesTable: def __init__(self, formsemestre_id): # log(f"NotesTable( formsemestre_id={formsemestre_id} )") - # raise NotImplementedError() # XXX + raise NotImplementedError() # XXX if not formsemestre_id: raise ValueError("invalid formsemestre_id (%s)" % formsemestre_id) self.formsemestre_id = formsemestre_id diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index 700115e52..d3b6fbd95 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -33,10 +33,14 @@ from flask import g, url_for from flask_login import current_user from app.auth.models import User +from app.comp import res_sem +from app.comp.res_common import NotesTableCompat +from app.models import FormSemestre from app.models import ModuleImpl from app.models.evaluations import Evaluation import app.scodoc.sco_utils as scu from app.scodoc.sco_exceptions import ScoInvalidIdType +from app.scodoc.sco_parcours_dut import formsemestre_has_decisions from app.scodoc.sco_permissions import Permission from app.scodoc import html_sco_header @@ -199,7 +203,9 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): moduleimpl_id=M["moduleimpl_id"] ) - nt = sco_cache.NotesTableCache.get(formsemestre_id) + # nt = sco_cache.NotesTableCache.get(formsemestre_id) + nt: NotesTableCompat = res_sem.load_formsemestre_results(modimpl.formsemestre) + mod_evals = sco_evaluation_db.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) mod_evals.sort( key=lambda x: (x["numero"], x["jour"], x["heure_debut"]), reverse=True @@ -335,7 +341,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): if has_expression and nt.expr_diagnostics: H.append(sco_formsemestre_status.html_expr_diagnostic(nt.expr_diagnostics)) # - if nt.sem_has_decisions(): + if formsemestre_has_decisions(formsemestre_id): H.append( """
  • Décisions de jury saisies: seul le responsable du semestre peut saisir des notes (il devra modifier les décisions de jury).
""" )