From 9fc4e8381167803770898bdce18fa26059a1fd93 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Tue, 8 Feb 2022 00:04:07 +0100 Subject: [PATCH 1/3] 9.1.50a --- app/comp/res_but.py | 3 ++- app/scodoc/sco_recapcomplet.py | 7 ++----- sco_version.py | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/comp/res_but.py b/app/comp/res_but.py index c5267596a..7b9797760 100644 --- a/app/comp/res_but.py +++ b/app/comp/res_but.py @@ -6,6 +6,7 @@ """Résultats semestres BUT """ +import numpy as np import pandas as pd from app.comp import moy_ue, moy_sem, inscr_mod @@ -113,7 +114,7 @@ class ResultatsSemestreBUT(NotesTableCompat): mod_idx = self.modimpl_coefs_df.columns.get_loc(moduleimpl_id) etud_idx = self.etud_index[etudid] # moyenne sur les UE: - return self.sem_cube[etud_idx, mod_idx].mean() + return np.nanmean(self.sem_cube[etud_idx, mod_idx]) def compute_etud_ue_coef(self, etudid: int, ue: UniteEns) -> float: """Détermine le coefficient de l'UE pour cet étudiant. diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index 16830b081..3b45330d8 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -85,8 +85,8 @@ def formsemestre_recapcomplet( sem = sco_formsemestre.get_formsemestre(formsemestre_id) F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0] parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) - # Options pour APC BUT: cache les modules par défaut car moyenne n'a pas de sens formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + # Pour APC (BUT): cache les modules par défaut car moyenne n'a pas de sens if formsemestre.formation.is_apc(): hidemodules = True # traduit du DTML @@ -312,10 +312,7 @@ def make_formsemestre_recapcomplet( nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) modimpls = formsemestre.modimpls_sorted ues = nt.get_ues_stat_dict() # incluant le(s) UE de sport - # - # if formsemestre.formation.is_apc(): - # nt.apc_recompute_moyennes() - # + partitions, partitions_etud_groups = sco_groups.get_formsemestre_groups( formsemestre_id ) diff --git a/sco_version.py b/sco_version.py index 84e9b0f57..a75f9a940 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.2.0a" +SCOVERSION = "9.1.50a" SCONAME = "ScoDoc" From 7a183185a2c80c9e75915d94846784abb1a43e2a Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Tue, 8 Feb 2022 23:58:02 +0100 Subject: [PATCH 2/3] =?UTF-8?q?Fix:=20codes=20Apog=C3=A9e=20nulls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/modules.py | 1 + app/models/ues.py | 1 + app/scodoc/sco_apogee_csv.py | 12 ++++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/models/modules.py b/app/models/modules.py index ac82b127e..393cc8c0f 100644 --- a/app/models/modules.py +++ b/app/models/modules.py @@ -63,6 +63,7 @@ class Module(db.Model): e["numero"] = 0 if self.numero is None else self.numero e["coefficient"] = 0.0 if self.coefficient is None else self.coefficient e["module_type"] = 0 if self.module_type is None else self.module_type + e["code_apogee"] = e["code_apogee"] or "" # pas de None return e def is_apc(self): diff --git a/app/models/ues.py b/app/models/ues.py index 3497414c0..09469fb05 100644 --- a/app/models/ues.py +++ b/app/models/ues.py @@ -62,6 +62,7 @@ class UniteEns(db.Model): e["numero"] = e["numero"] if e["numero"] else 0 e["ects"] = e["ects"] if e["ects"] else 0.0 e["coefficient"] = e["coefficient"] if e["coefficient"] else 0.0 + e["code_apogee"] = e["code_apogee"] or "" # pas de None return e def is_locked(self): diff --git a/app/scodoc/sco_apogee_csv.py b/app/scodoc/sco_apogee_csv.py index 04a2fe2c5..4cae17724 100644 --- a/app/scodoc/sco_apogee_csv.py +++ b/app/scodoc/sco_apogee_csv.py @@ -413,7 +413,7 @@ class ApoEtud(dict): # Elements UE decisions_ue = nt.get_etud_decision_ues(etudid) for ue in nt.get_ues_stat_dict(): - if code in ue["code_apogee"].split(","): + if ue["code_apogee"] and code in ue["code_apogee"].split(","): if self.export_res_ues: if decisions_ue and ue["ue_id"] in decisions_ue: ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"]) @@ -434,7 +434,9 @@ class ApoEtud(dict): modimpls = nt.get_modimpls_dict() module_code_found = False for modimpl in modimpls: - if code in modimpl["module"]["code_apogee"].split(","): + if modimpl["module"]["code_apogee"] and code in modimpl["module"][ + "code_apogee" + ].split(","): n = nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid) if n != "NI" and self.export_res_modules: return dict(N=_apo_fmt_note(n), B=20, J="", R="") @@ -947,13 +949,15 @@ class ApoData(object): # associé à une UE: nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) for ue in nt.get_ues_stat_dict(): - if code in ue["code_apogee"].split(","): + if ue["code_apogee"] and code in ue["code_apogee"].split(","): s.add(code) continue # associé à un module: modimpls = nt.get_modimpls_dict() for modimpl in modimpls: - if code in modimpl["module"]["code_apogee"].split(","): + if modimpl["module"]["code_apogee"] and code in modimpl["module"][ + "code_apogee" + ].split(","): s.add(code) continue # log('codes_by_sem=%s' % pprint.pformat(codes_by_sem)) From c29312e5114c353db4efeb4ff0498d77514d285c Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Wed, 9 Feb 2022 00:36:50 +0100 Subject: [PATCH 3/3] Fix: divers petits bugs --- app/comp/res_but.py | 4 +- app/comp/res_common.py | 17 ++++++++- app/models/formsemestre.py | 45 +++++++++++++++++++++++ app/scodoc/sco_bulletins.py | 2 +- app/scodoc/sco_bulletins_pdf.py | 2 +- app/scodoc/sco_formsemestre_validation.py | 9 ++--- 6 files changed, 68 insertions(+), 11 deletions(-) diff --git a/app/comp/res_but.py b/app/comp/res_but.py index 7b9797760..f70ed0b08 100644 --- a/app/comp/res_but.py +++ b/app/comp/res_but.py @@ -114,7 +114,9 @@ class ResultatsSemestreBUT(NotesTableCompat): mod_idx = self.modimpl_coefs_df.columns.get_loc(moduleimpl_id) etud_idx = self.etud_index[etudid] # moyenne sur les UE: - return np.nanmean(self.sem_cube[etud_idx, mod_idx]) + if len(self.sem_cube[etud_idx, mod_idx]): + return np.nanmean(self.sem_cube[etud_idx, mod_idx]) + return np.nan def compute_etud_ue_coef(self, etudid: int, ue: UniteEns) -> float: """Détermine le coefficient de l'UE pour cet étudiant. diff --git a/app/comp/res_common.py b/app/comp/res_common.py index 09d3ed75f..1aa993e85 100644 --- a/app/comp/res_common.py +++ b/app/comp/res_common.py @@ -216,11 +216,24 @@ class ResultatsSemestre(ResultatsCache): def get_etud_ue_status(self, etudid: int, ue_id: int) -> dict: """L'état de l'UE pour cet étudiant. - Result: dict + L'UE doit être du semestre. + Result: dict. """ if not self.validations: self.validations = res_sem.load_formsemestre_validations(self.formsemestre) ue = UniteEns.query.get(ue_id) # TODO cacher nos UEs ? + if ue.type == UE_SPORT: + return { + "is_capitalized": False, + "is_external": False, + "coef_ue": 0.0, + "cur_moy_ue": 0.0, + "moy": 0.0, + "event_date": None, + "ue": ue.to_dict(), + "formsemestre_id": None, + "capitalized_ue_id": None, + } cur_moy_ue = self.etud_moy_ue[ue_id][etudid] moy_ue = cur_moy_ue is_capitalized = False @@ -464,7 +477,7 @@ class NotesTableCompat(ResultatsSemestre): ects_pot += ue.ects return { "ects_pot": ects_pot, - "ects_fond": 0.0, # not implemented (anciennemment pour école ingé) + "ects_pot_fond": 0.0, # not implemented (anciennemment pour école ingé) } def get_etud_rang(self, etudid: int): diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py index 932e3fecb..9ed1636a4 100644 --- a/app/models/formsemestre.py +++ b/app/models/formsemestre.py @@ -132,7 +132,47 @@ class FormSemestre(db.Model): else: d["date_fin"] = d["date_fin_iso"] = "" d["responsables"] = [u.id for u in self.responsables] + return d + def get_infos_dict(self) -> dict: + """Un dict avec des informations sur le semestre + pour les bulletins et autres templates + (contenu compatible scodoc7 / anciens templates) + """ + d = self.to_dict() + d["anneescolaire"] = self.annee_scolaire_str() + d["annee_debut"] = str(self.date_debut.year) + d["annee"] = d["annee_debut"] + d["annee_fin"] = str(self.date_fin.year) + d["mois_debut_ord"] = self.date_debut.month + d["mois_fin_ord"] = self.date_fin.month + # La période: considère comme "S1" (ou S3) les débuts en aout-sept-octobre + # devrait sans doute pouvoir etre changé... + if self.date_debut.month >= 8 and self.date_debut.month <= 10: + d["periode"] = 1 # typiquement, début en septembre: S1, S3... + else: + d["periode"] = 2 # typiquement, début en février: S2, S4... + d["titre_num"] = self.titre_num + d["titreannee"] = "%s %s %s" % ( + d["titre_num"], + self.modalite or "", + self.date_debut.year, + ) + if d["annee_fin"] != d["annee_debut"]: + d["titreannee"] += "-" + str(d["annee_fin"]) + d["annee"] += "-" + str(d["annee_fin"]) + d["mois_debut"] = f"{self.date_debut.month} {self.date_debut.year}" + d["mois_fin"] = f"{self.date_fin.month} {self.date_fin.year}" + d["titremois"] = "%s %s (%s - %s)" % ( + d["titre_num"], + self.modalite or "", + d["mois_debut"], + d["mois_fin"], + ) + d["session_id"] = self.session_id() + d["etapes"] = self.etapes_apo_vdi() + d["etapes_apo_str"] = self.etapes_apo_str() + d["responsables"] = [u.id for u in self.responsables] # liste des ids return d def query_ues(self, with_sport=False) -> flask_sqlalchemy.BaseQuery: @@ -231,6 +271,11 @@ class FormSemestre(db.Model): not self.semestre_id % 2 and self.date_debut.month > 6 ) + def etapes_apo_vdi(self) -> list[ApoEtapeVDI]: + "Liste des vdis" + # was read_formsemestre_etapes + return [e.as_apovdi() for e in self.etapes if e.etape_apo] + def etapes_apo_str(self) -> str: """Chaine décrivant les étapes de ce semestre ex: "V1RT, V1RT3, V1RT4" diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index d1127110c..37299c3c3 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -148,7 +148,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"): I = scu.DictDefault(defaultvalue="") I["etudid"] = etudid I["formsemestre_id"] = formsemestre_id - I["sem"] = nt.sem + I["sem"] = formsemestre.get_infos_dict() I["server_name"] = request.url_root # Formation et parcours diff --git a/app/scodoc/sco_bulletins_pdf.py b/app/scodoc/sco_bulletins_pdf.py index 4e81ce7ad..2195d1eef 100644 --- a/app/scodoc/sco_bulletins_pdf.py +++ b/app/scodoc/sco_bulletins_pdf.py @@ -141,7 +141,7 @@ def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"): except: log("process_field: invalid format=%s" % field) text = ( - "format invalide !" + "format invalide !" + traceback.format_exc() + "" ) diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py index e835f1dd8..425d13946 100644 --- a/app/scodoc/sco_formsemestre_validation.py +++ b/app/scodoc/sco_formsemestre_validation.py @@ -702,17 +702,14 @@ def formsemestre_recap_parcours_table( ) # total ECTS (affiché sous la moyenne générale) H.append( - 'ECTS:%g %g' - % (etud_ects_infos["ects_pot"], etud_ects_infos["ects_pot_fond"]) + 'ECTS:%g' + % (etud_ects_infos["ects_pot"]) ) H.append('') # ECTS validables dans chaque UE for ue in ues: ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"]) - H.append( - '%g %g' - % (ue_status["ects_pot"], ue_status["ects_pot_fond"]) - ) + H.append('%g' % (ue_status["ects_pot"])) H.append("") H.append("")