diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py
index 3cba7fc54..2c6288bb4 100644
--- a/app/but/bulletin_but.py
+++ b/app/but/bulletin_but.py
@@ -147,6 +147,7 @@ class BulletinBUT(ResultatsSemestreBUT):
def bulletin_etud(self, etud, formsemestre) -> dict:
"""Le bulletin de l'étudiant dans ce semestre"""
etat_inscription = etud.etat_inscription(formsemestre.id)
+ nb_inscrits = self.get_inscriptions_counts()[scu.INSCRIT]
d = {
"version": "0",
"type": "BUT",
@@ -189,7 +190,7 @@ class BulletinBUT(ResultatsSemestreBUT):
},
"rang": { # classement wrt moyenne général, indicatif
"value": self.etud_moy_gen_ranks[etud.id],
- "total": len(self.etuds),
+ "total": nb_inscrits,
},
},
)
@@ -212,7 +213,7 @@ class BulletinBUT(ResultatsSemestreBUT):
"moy": "",
"max": "",
},
- "rang": {"value": "DEM", "total": len(self.etuds)},
+ "rang": {"value": "DEM", "total": nb_inscrits},
}
)
d.update(
diff --git a/app/but/bulletin_but_xml_compat.py b/app/but/bulletin_but_xml_compat.py
index b3398ef9b..f318f236e 100644
--- a/app/but/bulletin_but_xml_compat.py
+++ b/app/but/bulletin_but_xml_compat.py
@@ -69,10 +69,11 @@ def bulletin_but_xml_compat(
% (formsemestre_id, etudid)
)
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
- etud = Identite.query.get_or_404(etudid)
+ etud: Identite = Identite.query.get_or_404(etudid)
results = bulletin_but.ResultatsSemestreBUT(formsemestre)
- nb_inscrits = len(results.etuds)
- etat_inscription = etud.etat_inscription(formsemestre.id)
+ nb_inscrits = results.get_inscriptions_counts()[scu.INSCRIT]
+ # etat_inscription = etud.etat_inscription(formsemestre.id)
+ etat_inscription = results.formsemestre.etuds_inscriptions[etudid].etat
if (not formsemestre.bul_hide_xml) or force_publishing:
published = 1
else:
diff --git a/app/comp/inscr_mod.py b/app/comp/inscr_mod.py
index c34547e6b..8a5f4bc8f 100644
--- a/app/comp/inscr_mod.py
+++ b/app/comp/inscr_mod.py
@@ -16,13 +16,13 @@ from app import models
#
def df_load_modimpl_inscr(formsemestre) -> pd.DataFrame:
"""Charge la matrice des inscriptions aux modules du semestre
- rows: etudid
+ rows: etudid (inscrits au semestre, avec DEM et DEF)
columns: moduleimpl_id (en chaîne)
value: bool (0/1 inscrit ou pas)
"""
# méthode la moins lente: une requete par module, merge les dataframes
moduleimpl_ids = [m.id for m in formsemestre.modimpls]
- etudids = [i.etudid for i in formsemestre.get_inscrits(include_dem=False)]
+ etudids = [inscr.etudid for inscr in formsemestre.inscriptions]
df = pd.DataFrame(index=etudids, dtype=int)
for moduleimpl_id in moduleimpl_ids:
ins_df = pd.read_sql_query(
diff --git a/app/comp/moy_mod.py b/app/comp/moy_mod.py
index 95524597f..2fee521d3 100644
--- a/app/comp/moy_mod.py
+++ b/app/comp/moy_mod.py
@@ -75,7 +75,7 @@ class ModuleImplResults:
"{ evaluation_id: EvaluationEtat }"
#
self.evals_notes = None
- """DataFrame, colonnes: EVALS, Lignes: etudid
+ """DataFrame, colonnes: EVALS, Lignes: etudid (inscrits au SEMESTRE)
valeur: notes brutes, float ou NOTES_ATTENTE, NOTES_NEUTRALISE,
NOTES_ABSENCE.
Les NaN désignent les notes manquantes (non saisies).
@@ -105,7 +105,7 @@ class ModuleImplResults:
Évaluation "complete" (prise en compte dans les calculs) si:
- soit tous les étudiants inscrits au module ont des notes
- - soit elle a été déclarée "à prise ne compte immédiate" (publish_incomplete)
+ - soit elle a été déclarée "à prise en compte immédiate" (publish_incomplete)
Évaluation "attente" (prise en compte dans les calculs, mais il y
manque des notes) ssi il y a des étudiants inscrits au semestre et au module
@@ -178,14 +178,12 @@ class ModuleImplResults:
return eval_df
def _etudids(self):
- """L'index du dataframe est la liste des étudiants inscrits au semestre,
- sans les démissionnaires.
- """
+ """L'index du dataframe est la liste de tous les étudiants inscrits au semestre"""
return [
- e.etudid
- for e in ModuleImpl.query.get(self.moduleimpl_id).formsemestre.get_inscrits(
- include_dem=False
- )
+ inscr.etudid
+ for inscr in ModuleImpl.query.get(
+ self.moduleimpl_id
+ ).formsemestre.inscriptions
]
def get_evaluations_coefs(self, moduleimpl: ModuleImpl) -> np.array:
diff --git a/app/comp/moy_sem.py b/app/comp/moy_sem.py
index 8797b856c..3c658988b 100644
--- a/app/comp/moy_sem.py
+++ b/app/comp/moy_sem.py
@@ -31,8 +31,10 @@ import numpy as np
import pandas as pd
-def compute_sem_moys_apc(etud_moy_ue_df, modimpl_coefs_df):
- """Calcule la moyenne générale indicative
+def compute_sem_moys_apc(
+ etud_moy_ue_df: pd.DataFrame, modimpl_coefs_df: pd.DataFrame
+) -> pd.Series:
+ """Calcule les moyennes générales indicatives de tous les étudiants
= moyenne des moyennes d'UE, pondérée par la somme de leurs coefs
etud_moy_ue_df: DataFrame, colonnes ue_id, lignes etudid
@@ -46,10 +48,11 @@ def compute_sem_moys_apc(etud_moy_ue_df, modimpl_coefs_df):
return moy_gen
-def comp_ranks_series(notes: pd.Series):
- """Calcul rangs à partir d'une séries ("vecteur") de notes (index etudid, valeur numérique)
- en tenant compte des ex-aequos
- Le resultat est: { etudid : rang } où rang est une chaine decrivant le rang
+def comp_ranks_series(notes: pd.Series) -> dict[int, str]:
+ """Calcul rangs à partir d'une séries ("vecteur") de notes (index etudid, valeur
+ numérique) en tenant compte des ex-aequos.
+
+ Result: { etudid : rang:str } où rang est une chaine decrivant le rang.
"""
notes = notes.sort_values(ascending=False) # Serie, tri par ordre décroissant
rangs = pd.Series(index=notes.index, dtype=str) # le rang est une chaîne
diff --git a/app/comp/moy_ue.py b/app/comp/moy_ue.py
index e3c9620ab..228c2c747 100644
--- a/app/comp/moy_ue.py
+++ b/app/comp/moy_ue.py
@@ -140,9 +140,14 @@ def notes_sem_assemble_cube(modimpls_notes: list[pd.DataFrame]) -> np.ndarray:
def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple:
- """Calcule le cube des notes du semestre
- (charge toutes les notes, calcule les moyenne des modules
- et assemble le cube)
+ """Construit le "cube" (tenseur) des notes du semestre.
+ Charge toutes les notes (sql), calcule les moyennes des modules
+ et assemble le cube.
+
+ etuds: tous les inscrits au semestre (avec dem. et def.)
+ modimpls: _tous_ les modimpls de ce semestre
+ UEs: X?X voir quelles sont les UE considérées ici
+
Resultat:
sem_cube : ndarray (etuds x modimpls x UEs)
modimpls_evals_poids dict { modimpl.id : evals_poids }
@@ -174,14 +179,14 @@ def compute_ue_moys_apc(
) -> pd.DataFrame:
"""Calcul de la moyenne d'UE en mode APC (BUT).
La moyenne d'UE est un nombre (note/20), ou NI ou NA ou ERR
- NI non inscrit à (au moins un) module de cette UE
- NA pas de notes disponibles
- ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
+ NI non inscrit à (au moins un) module de cette UE
+ NA pas de notes disponibles
+ ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
sem_cube: notes moyennes aux modules
ndarray (etuds x modimpls x UEs)
(floats avec des NaN)
- etuds : listes des étudiants (dim. 0 du cube)
+ etuds : liste des étudiants (dim. 0 du cube)
modimpls : liste des modules à considérer (dim. 1 du cube)
ues : liste des UE (dim. 2 du cube)
modimpl_inscr_df: matrice d'inscription du semestre (etud x modimpl)
@@ -235,12 +240,12 @@ def compute_ue_moys_classic(
ues: list,
modimpl_inscr_df: pd.DataFrame,
modimpl_coefs: np.array,
-) -> tuple:
+) -> tuple[pd.Series, pd.DataFrame, pd.DataFrame]:
"""Calcul de la moyenne d'UE en mode classique.
La moyenne d'UE est un nombre (note/20), ou NI ou NA ou ERR
- NI non inscrit à (au moins un) module de cette UE
- NA pas de notes disponibles
- ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
+ NI non inscrit à (au moins un) module de cette UE
+ NA pas de notes disponibles
+ ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
sem_matrix: notes moyennes aux modules
ndarray (etuds x modimpls)
@@ -253,6 +258,9 @@ def compute_ue_moys_classic(
Résultat:
- moyennes générales: pd.Series, index etudid
- moyennes d'UE: DataFrame columns UE, rows etudid
+ - coefficients d'UE: DataFrame, columns UE, rows etudid
+ les coefficients effectifs de chaque UE pour chaque étudiant
+ (sommes de coefs de modules pris en compte)
"""
nb_etuds, nb_modules = sem_matrix.shape
assert len(modimpl_coefs) == nb_modules
@@ -293,4 +301,9 @@ def compute_ue_moys_classic(
etud_moy_ue_df = pd.DataFrame(
etud_moy_ue, index=modimpl_inscr_df.index, columns=[ue.id for ue in ues]
)
- return etud_moy_gen_s, etud_moy_ue_df
+ etud_coef_ue_df = pd.DataFrame(
+ coefs.sum(axis=2).T,
+ index=modimpl_inscr_df.index, # etudids
+ columns=[ue.id for ue in ues],
+ )
+ return etud_moy_gen_s, etud_moy_ue_df, etud_coef_ue_df
diff --git a/app/comp/res_but.py b/app/comp/res_but.py
index aa9f3fe05..669380a31 100644
--- a/app/comp/res_but.py
+++ b/app/comp/res_but.py
@@ -6,6 +6,7 @@
"""Résultats semestres BUT
"""
+import pandas as pd
from app.comp import moy_ue, moy_sem, inscr_mod
from app.comp.res_common import NotesTableCompat
@@ -49,6 +50,10 @@ class ResultatsSemestreBUT(NotesTableCompat):
self.modimpl_inscr_df,
self.modimpl_coefs_df,
)
+ # Les coefficients d'UE ne sont pas utilisés en APC
+ self.etud_coef_ue_df = pd.DataFrame(
+ 1.0, index=self.etud_moy_ue.index, columns=self.etud_moy_ue.columns
+ )
self.etud_moy_gen = moy_sem.compute_sem_moys_apc(
self.etud_moy_ue, self.modimpl_coefs_df
)
diff --git a/app/comp/res_classic.py b/app/comp/res_classic.py
index 93e3a9fb0..68972ced6 100644
--- a/app/comp/res_classic.py
+++ b/app/comp/res_classic.py
@@ -8,6 +8,7 @@
"""
import numpy as np
import pandas as pd
+
from app.comp import moy_mod, moy_ue, moy_sem, inscr_mod
from app.comp.res_common import NotesTableCompat
from app.models.formsemestre import FormSemestre
@@ -45,7 +46,11 @@ class ResultatsSemestreClassic(NotesTableCompat):
self.modimpl_idx = {m.id: i for i, m in enumerate(self.formsemestre.modimpls)}
"l'idx de la colonne du mod modimpl.id est modimpl_idx[modimpl.id]"
- self.etud_moy_gen, self.etud_moy_ue = moy_ue.compute_ue_moys_classic(
+ (
+ self.etud_moy_gen,
+ self.etud_moy_ue,
+ self.etud_coef_ue_df,
+ ) = moy_ue.compute_ue_moys_classic(
self.formsemestre,
self.sem_matrix,
self.ues,
diff --git a/app/comp/res_common.py b/app/comp/res_common.py
index 7a922cf6a..1ff654686 100644
--- a/app/comp/res_common.py
+++ b/app/comp/res_common.py
@@ -4,13 +4,13 @@
# See LICENSE
##############################################################################
-from collections import defaultdict
+from collections import defaultdict, Counter
from functools import cached_property
import numpy as np
import pandas as pd
from app.comp.aux import StatsMoyenne
from app.comp.moy_mod import ModuleImplResults
-from app.models import FormSemestre, ModuleImpl
+from app.models import FormSemestre, Identite, ModuleImpl
from app.models.ues import UniteEns
from app.scodoc import sco_utils as scu
from app.scodoc.sco_cache import ResultatsSemestreCache
@@ -32,6 +32,7 @@ class ResultatsSemestre:
"etud_moy_ue",
"modimpl_inscr_df",
"modimpls_results",
+ "etud_coef_ue_df",
)
def __init__(self, formsemestre: FormSemestre):
@@ -45,7 +46,10 @@ class ResultatsSemestre:
self.etud_moy_gen = {}
self.etud_moy_gen_ranks = {}
self.modimpls_results: ModuleImplResults = None
- # TODO
+ self.etud_coef_ue_df = None
+ """coefs d'UE effectifs pour chaque etudiant (pour form. classiques)"""
+
+ # TODO ?
def load_cached(self) -> bool:
"Load cached dataframes, returns False si pas en cache"
@@ -68,24 +72,34 @@ class ResultatsSemestre:
# voir ce qui est chargé / calculé ici et dans les sous-classes
raise NotImplementedError()
- @cached_property
- def etuds(self):
- "Liste des inscrits au semestre, sans les démissionnaires"
- # nb: si la liste des inscrits change, ResultatsSemestre devient invalide
- return self.formsemestre.get_inscrits(include_dem=False)
+ def get_inscriptions_counts(self) -> Counter:
+ """Nombre d'inscrits, défaillants, démissionnaires.
+
+ Exemple: res.get_inscriptions_counts()[scu.INSCRIT]
+
+ Result: a collections.Counter instance
+ """
+ return Counter(ins.etat for ins in self.formsemestre.inscriptions)
@cached_property
- def etud_index(self):
+ def etuds(self) -> list[Identite]:
+ "Liste des inscrits au semestre, avec les démissionnaires et les défaillants"
+ # nb: si la liste des inscrits change, ResultatsSemestre devient invalide
+ return self.formsemestre.get_inscrits(include_demdef=True)
+
+ @cached_property
+ def etud_index(self) -> dict[int, int]:
"dict { etudid : indice dans les inscrits }"
return {e.id: idx for idx, e in enumerate(self.etuds)}
@cached_property
- def etuds_dict(self):
- "dict { etudid : Identite } inscrits au semestre, sans les démissionnaires"
+ def etuds_dict(self) -> dict[int, Identite]:
+ """dict { etudid : Identite } inscrits au semestre,
+ avec les démissionnaires et defs."""
return {etud.id: etud for etud in self.etuds}
@cached_property
- def ues(self) -> list:
+ def ues(self) -> list[UniteEns]:
"""Liste des UEs du semestre
(indices des DataFrames)
"""
@@ -153,6 +167,7 @@ class NotesTableCompat(ResultatsSemestre):
def __init__(self, formsemestre: FormSemestre):
super().__init__(formsemestre)
+
nb_etuds = len(self.etuds)
self.bonus = defaultdict(lambda: 0.0) # XXX TODO
self.ue_rangs = {u.id: (defaultdict(lambda: 0.0), nb_etuds) for u in self.ues}
@@ -178,12 +193,18 @@ class NotesTableCompat(ResultatsSemestre):
return [x["etudid"] for x in self.inscrlist]
+ @cached_property
+ def sem(self) -> dict:
+ """le formsemestre, comme un dict (nt.sem)"""
+ return self.formsemestre.to_dict()
+
@cached_property
def inscrlist(self) -> list[dict]: # utilisé par PE seulement
- """Liste de dict etud, avec démissionnaires
+ """Liste des inscrits au semestre (avec DEM et DEF),
+ sous forme de dict etud,
classée dans l'ordre alphabétique de noms.
"""
- etuds = self.formsemestre.get_inscrits(include_dem=True)
+ etuds = self.formsemestre.get_inscrits(include_demdef=True)
etuds.sort(key=lambda e: e.sort_key)
return [e.to_dict_scodoc7() for e in etuds]
@@ -256,9 +277,12 @@ class NotesTableCompat(ResultatsSemestre):
raise NotImplementedError() # virtual method
def get_etud_ue_status(self, etudid: int, ue_id: int):
+ coef_ue = self.etud_coef_ue_df[ue_id][etudid]
return {
"cur_moy_ue": self.etud_moy_ue[ue_id][etudid],
+ "moy": self.etud_moy_ue[ue_id][etudid],
"is_capitalized": False, # XXX TODO
+ "coef_ue": coef_ue, # XXX TODO
}
def get_etud_rang(self, etudid: int):
@@ -277,18 +301,20 @@ class NotesTableCompat(ResultatsSemestre):
for e in modimpl.evaluations:
if self.modimpls_results[moduleimpl_id].evaluations_completes_dict[e.id]:
d = e.to_dict()
+ moduleimpl_results = self.modimpls_results[e.moduleimpl_id]
d["heure_debut"] = e.heure_debut # datetime.time
d["heure_fin"] = e.heure_fin
d["jour"] = e.jour # datetime
d["notes"] = {
etud.id: {
"etudid": etud.id,
- "value": self.modimpls_evals_notes[e.moduleimpl_id][e.id][
- etud.id
- ],
+ "value": moduleimpl_results.evals_notes[e.id][etud.id],
}
for etud in self.etuds
}
+ d["etat"] = {
+ "evalattente": moduleimpl_results.evaluations_etat[e.id].nb_attente,
+ }
evals_results.append(d)
return evals_results
diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index a55188b6b..a74f1671d 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -117,11 +117,18 @@ class FormSemestre(db.Model):
d.pop("_sa_instance_state", None)
# ScoDoc7 output_formators: (backward compat)
d["formsemestre_id"] = self.id
- d["date_debut"] = (
- self.date_debut.strftime("%d/%m/%Y") if self.date_debut else ""
- )
- d["date_fin"] = self.date_fin.strftime("%d/%m/%Y") if self.date_fin else ""
+ if self.date_debut:
+ d["date_debut"] = self.date_debut.strftime("%d/%m/%Y")
+ d["date_debut_iso"] = self.date_debut.isoformat()
+ else:
+ d["date_debut"] = d["date_debut_iso"] = ""
+ if self.date_fin:
+ d["date_fin"] = self.date_fin.strftime("%d/%m/%Y")
+ d["date_fin_iso"] = self.date_fin.isoformat()
+ else:
+ d["date_fin"] = d["date_fin_iso"] = ""
d["responsables"] = [u.id for u in self.responsables]
+
return d
def query_ues(self, with_sport=False) -> flask_sqlalchemy.BaseQuery:
@@ -271,18 +278,19 @@ class FormSemestre(db.Model):
etudid, self.date_debut.isoformat(), self.date_fin.isoformat()
)
- def get_inscrits(self, include_dem=False) -> list[Identite]:
+ def get_inscrits(self, include_demdef=False) -> list[Identite]:
"""Liste des étudiants inscrits à ce semestre
- Si all, tous les étudiants, avec les démissionnaires.
+ Si include_demdef, tous les étudiants, avec les démissionnaires
+ et défaillants.
"""
- if include_dem:
+ if include_demdef:
return [ins.etud for ins in self.inscriptions]
else:
return [ins.etud for ins in self.inscriptions if ins.etat == scu.INSCRIT]
@cached_property
def etuds_inscriptions(self) -> dict:
- """Map { etudid : inscription }"""
+ """Map { etudid : inscription } (incluant DEM et DEF)"""
return {ins.etud.id: ins for ins in self.inscriptions}
diff --git a/app/scodoc/bonus_sport.py b/app/scodoc/bonus_sport.py
index 651c60812..75b08b501 100644
--- a/app/scodoc/bonus_sport.py
+++ b/app/scodoc/bonus_sport.py
@@ -62,7 +62,7 @@ Pour modifier les moyennes d'UE:
La valeur retournée est:
- formations classiques: ajoutée à la moyenne générale
- - BUT: ajoutée à chaque UE si le coef XXX
+ - BUT: valeur multipliée par la somme des coefs modules sport ajoutée à chaque UE.
"""
diff --git a/app/scodoc/notes_table.py b/app/scodoc/notes_table.py
index 828ea228c..eec178f14 100644
--- a/app/scodoc/notes_table.py
+++ b/app/scodoc/notes_table.py
@@ -171,6 +171,7 @@ class NotesTable:
def __init__(self, formsemestre_id):
log(f"NotesTable( formsemestre_id={formsemestre_id} )")
+ # raise NotImplementedError() # XXX
if not formsemestre_id:
raise ValueError("invalid formsemestre_id (%s)" % formsemestre_id)
self.formsemestre_id = formsemestre_id
@@ -409,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":
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index ae7e14a9e..1941d051f 100644
--- a/app/scodoc/sco_bulletins.py
+++ b/app/scodoc/sco_bulletins.py
@@ -48,6 +48,9 @@ import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType
import app.scodoc.notesdb as ndb
from app import log
+from app.comp import res_sem
+from app.comp.res_common import NotesTableCompat
+from app.models import FormSemestre
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
from app.scodoc import html_sco_header
@@ -136,7 +139,9 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
raise ValueError("invalid version code !")
prefs = sco_preferences.SemPreferences(formsemestre_id)
- nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes
+ # nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes
+ formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
+ nt: NotesTableCompat = res_sem.load_formsemestre_result(formsemestre)
if not nt.get_etud_etat(etudid):
raise ScoValueError("Etudiant non inscrit à ce semestre")
I = scu.DictDefault(defaultvalue="")
@@ -191,7 +196,9 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
I["decision_sem"] = ""
I.update(infos)
- I["etud_etat_html"] = nt.get_etud_etat_html(etudid)
+ I["etud_etat_html"] = _get_etud_etat_html(
+ formsemestre.etuds_inscriptions[etudid].etat
+ )
I["etud_etat"] = nt.get_etud_etat(etudid)
I["filigranne"] = ""
I["demission"] = ""
@@ -261,17 +268,18 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
# notes en attente dans ce semestre
rang = scu.RANG_ATTENTE_STR
rang_gr = scu.DictDefault(defaultvalue=scu.RANG_ATTENTE_STR)
+ inscriptions_counts = nt.get_inscriptions_counts()
I["rang"] = rang
I["rang_gr"] = rang_gr
I["gr_name"] = gr_name
I["ninscrits_gr"] = ninscrits_gr
I["nbetuds"] = len(nt.etud_moy_gen_ranks)
- I["nb_demissions"] = nt.nb_demissions
- I["nb_defaillants"] = nt.nb_defaillants
+ I["nb_demissions"] = inscriptions_counts[scu.DEMISSION]
+ I["nb_defaillants"] = inscriptions_counts[scu.DEF]
if prefs["bul_show_rangs"]:
I["rang_nt"] = "%s / %d" % (
rang,
- I["nbetuds"] - nt.nb_demissions - nt.nb_defaillants,
+ inscriptions_counts[scu.INSCRIT],
)
I["rang_txt"] = "Rang " + I["rang_nt"]
else:
@@ -379,7 +387,8 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
I["ues"].append(u) # ne montre pas les UE si non inscrit
# Accès par matieres
- I["matieres_modules"].update(_sort_mod_by_matiere(modules, nt, etudid))
+ # voir si on supporte encore cela en #sco92 XXX
+ # I["matieres_modules"].update(_sort_mod_by_matiere(modules, nt, etudid))
#
C = make_context_dict(I["sem"], I["etud"])
@@ -389,6 +398,18 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
return C
+def _get_etud_etat_html(etat: str) -> str:
+ """chaine html représentant l'état (backward compat sco7)"""
+ if etat == scu.INSCRIT: # "I"
+ return ""
+ elif etat == scu.DEMISSION: # "D"
+ return ' (DEMISSIONNAIRE) '
+ elif etat == scu.DEF: # "DEF"
+ return ' (DEFAILLANT) '
+ else:
+ return ' (%s) ' % etat
+
+
def _sort_mod_by_matiere(modlist, nt, etudid):
matmod = {} # { matiere_id : [] }
for mod in modlist:
diff --git a/app/scodoc/sco_groups.py b/app/scodoc/sco_groups.py
index 8248491af..2036a64d2 100644
--- a/app/scodoc/sco_groups.py
+++ b/app/scodoc/sco_groups.py
@@ -1433,18 +1433,19 @@ def create_etapes_partition(formsemestre_id, partition_name="apo_etapes"):
def do_evaluation_listeetuds_groups(
- evaluation_id, groups=None, getallstudents=False, include_dems=False
+ evaluation_id, groups=None, getallstudents=False, include_demdef=False
):
"""Donne la liste des etudids inscrits a cette evaluation dans les
groupes indiqués.
Si getallstudents==True, donne tous les etudiants inscrits a cette
evaluation.
- Si include_dems, compte aussi les etudiants démissionnaires
+ Si include_demdef, compte aussi les etudiants démissionnaires et défaillants
(sinon, par défaut, seulement les 'I')
Résultat: [ (etudid, etat) ], où etat='I', 'D', 'DEF'
"""
- # nb: pour notes_table / do_evaluation_etat, getallstudents est vrai et include_dems faux
+ # nb: pour notes_table / do_evaluation_etat, getallstudents est vrai et
+ # include_demdef faux
fromtables = [
"notes_moduleimpl_inscription Im",
"notes_formsemestre_inscription Isem",
@@ -1476,7 +1477,7 @@ def do_evaluation_listeetuds_groups(
and E.id = %(evaluation_id)s
"""
)
- if not include_dems:
+ if not include_demdef:
req += " and Isem.etat='I'"
req += r
cnx = ndb.GetDBConnexion()
diff --git a/app/scodoc/sco_liste_notes.py b/app/scodoc/sco_liste_notes.py
index 00e615893..2ee8c620a 100644
--- a/app/scodoc/sco_liste_notes.py
+++ b/app/scodoc/sco_liste_notes.py
@@ -309,7 +309,7 @@ def _make_table_notes(
anonymous_lst_key = "etudid"
etudid_etats = sco_groups.do_evaluation_listeetuds_groups(
- E["evaluation_id"], groups, include_dems=True
+ E["evaluation_id"], groups, include_demdef=True
)
for etudid, etat in etudid_etats:
css_row_class = None
diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py
index fb8a35ead..1d5ac6c42 100644
--- a/app/scodoc/sco_placement.py
+++ b/app/scodoc/sco_placement.py
@@ -307,7 +307,7 @@ class PlacementRunner:
self.evaluation_id,
self.groups,
getallstudents=get_all_students,
- include_dems=True,
+ include_demdef=True,
)
listetud = [] # liste de couples (nom,prenom)
for etudid, etat in etudid_etats:
diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py
index f79b06ea4..997e835ea 100644
--- a/app/scodoc/sco_recapcomplet.py
+++ b/app/scodoc/sco_recapcomplet.py
@@ -306,8 +306,8 @@ def make_formsemestre_recapcomplet(
)[0]
parcours = formsemestre.formation.get_parcours()
- # nt = sco_cache.NotesTableCache.get(formsemestre_id)
- # XXX EXPERIMENTAL
+ # nt = sco_cache.NotesTableCache.get(formsemestre_id) # sco91
+ # sco92 :
nt: NotesTableCompat = res_sem.load_formsemestre_result(formsemestre)
modimpls = nt.get_modimpls_dict()
ues = nt.get_ues_stat_dict() # incluant le(s) UE de sport
@@ -434,13 +434,12 @@ def make_formsemestre_recapcomplet(
e["admission"] = {}
if not hidebac:
- if etud_etat == scu.INSCRIT:
- e["admission"] = nt.etuds_dict[etudid].admission.first()
- if e["admission"]:
- bac = nt.etuds_dict[etudid].admission[0].get_bac()
- l.append(bac.abbrev())
- else:
- l.append("")
+ e["admission"] = nt.etuds_dict[etudid].admission.first()
+ if e["admission"]:
+ bac = nt.etuds_dict[etudid].admission[0].get_bac()
+ l.append(bac.abbrev())
+ else:
+ l.append("")
if format[:3] == "xls" or format == "csv": # tous les groupes
for partition in partitions:
diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py
index fc3fd0818..a714fb0ea 100644
--- a/app/scodoc/sco_saisie_notes.py
+++ b/app/scodoc/sco_saisie_notes.py
@@ -310,7 +310,7 @@ def do_evaluation_set_missing(evaluation_id, value, dialog_confirmed=False):
#
NotesDB = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
etudid_etats = sco_groups.do_evaluation_listeetuds_groups(
- evaluation_id, getallstudents=True, include_dems=False
+ evaluation_id, getallstudents=True, include_demdef=False
)
notes = []
for etudid, _ in etudid_etats: # pour tous les inscrits
@@ -482,7 +482,7 @@ def notes_add(
inscrits = {
x[0]
for x in sco_groups.do_evaluation_listeetuds_groups(
- evaluation_id, getallstudents=True, include_dems=True
+ evaluation_id, getallstudents=True, include_demdef=True
)
}
for (etudid, value) in notes:
@@ -833,7 +833,7 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
etudids = [
x[0]
for x in sco_groups.do_evaluation_listeetuds_groups(
- evaluation_id, groups, getallstudents=getallstudents, include_dems=True
+ evaluation_id, groups, getallstudents=getallstudents, include_demdef=True
)
]
@@ -1079,7 +1079,7 @@ def _form_saisie_notes(E, M, group_ids, destination=""):
etudids = [
x[0]
for x in sco_groups.do_evaluation_listeetuds_groups(
- evaluation_id, getallstudents=True, include_dems=True
+ evaluation_id, getallstudents=True, include_demdef=True
)
]
if not etudids: