diff --git a/app/comp/res_but.py b/app/comp/res_but.py
index c5267596a4..f70ed0b086 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,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 self.sem_cube[etud_idx, mod_idx].mean()
+ 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 09d3ed75f0..1aa993e853 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 932e3fecb3..9ed1636a4f 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/models/modules.py b/app/models/modules.py
index ac82b127e5..393cc8c0f4 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 3497414c0e..09469fb051 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 04a2fe2c56..4cae177240 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))
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index d1127110c4..37299c3c38 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 4e81ce7add..2195d1eef2 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 e835f1dd82..425d139461 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("")
diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py
index 16830b0811..3b45330d8a 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 84e9b0f57b..a75f9a9403 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"