diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py
index 0eb28fe402..3cba7fc542 100644
--- a/app/but/bulletin_but.py
+++ b/app/but/bulletin_but.py
@@ -30,17 +30,18 @@ class BulletinBUT(ResultatsSemestreBUT):
ue_idx = self.modimpl_coefs_df.index.get_loc(ue.id)
etud_moy_module = self.sem_cube[etud_idx] # module x UE
for modimpl in modimpls:
- coef = self.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)
- ][ue_idx]
- ),
- }
+ if self.modimpl_inscr_df[str(modimpl.id)][etud.id]: # si inscrit
+ coef = self.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)
+ ][ue_idx]
+ ),
+ }
return d
def etud_ue_results(self, etud, ue):
@@ -87,29 +88,30 @@ class BulletinBUT(ResultatsSemestreBUT):
# except RuntimeWarning: # all nans in np.nanmean
# pass
modimpl_results = self.modimpls_results[modimpl.id]
- d[modimpl.module.code] = {
- "id": modimpl.id,
- "titre": modimpl.module.titre,
- "code_apogee": modimpl.module.code_apogee,
- "url": url_for(
- "notes.moduleimpl_status",
- scodoc_dept=g.scodoc_dept,
- moduleimpl_id=modimpl.id,
- ),
- "moyenne": {
- # # 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()),
- # "moy": fmt_note(moyennes_etuds.mean()),
- },
- "evaluations": [
- self.etud_eval_results(etud, e)
- for e in modimpl.evaluations
- if e.visibulletin
- and modimpl_results.evaluations_etat[e.id].is_complete
- ],
- }
+ if self.modimpl_inscr_df[str(modimpl.id)][etud.id]: # si inscrit
+ d[modimpl.module.code] = {
+ "id": modimpl.id,
+ "titre": modimpl.module.titre,
+ "code_apogee": modimpl.module.code_apogee,
+ "url": url_for(
+ "notes.moduleimpl_status",
+ scodoc_dept=g.scodoc_dept,
+ moduleimpl_id=modimpl.id,
+ ),
+ "moyenne": {
+ # # 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()),
+ # "moy": fmt_note(moyennes_etuds.mean()),
+ },
+ "evaluations": [
+ self.etud_eval_results(etud, e)
+ for e in modimpl.evaluations
+ if e.visibulletin
+ and modimpl_results.evaluations_etat[e.id].is_complete
+ ],
+ }
return d
def etud_eval_results(self, etud, e) -> dict:
diff --git a/app/but/bulletin_but_xml_compat.py b/app/but/bulletin_but_xml_compat.py
index 9b0996c134..b3398ef9bb 100644
--- a/app/but/bulletin_but_xml_compat.py
+++ b/app/but/bulletin_but_xml_compat.py
@@ -68,11 +68,12 @@ def bulletin_but_xml_compat(
"bulletin_but_xml_compat( formsemestre_id=%s, etudid=%s )"
% (formsemestre_id, etudid)
)
- sem = FormSemestre.query.get_or_404(formsemestre_id)
+ formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
etud = Identite.query.get_or_404(etudid)
- results = bulletin_but.ResultatsSemestreBUT(sem)
+ results = bulletin_but.ResultatsSemestreBUT(formsemestre)
nb_inscrits = len(results.etuds)
- if (not sem.bul_hide_xml) or force_publishing:
+ etat_inscription = etud.etat_inscription(formsemestre.id)
+ if (not formsemestre.bul_hide_xml) or force_publishing:
published = 1
else:
published = 0
@@ -86,10 +87,10 @@ def bulletin_but_xml_compat(
"date": docdate,
"publie": str(published),
}
- if sem.etapes:
- el["etape_apo"] = sem.etapes[0].etape_apo or ""
+ if formsemestre.etapes:
+ el["etape_apo"] = formsemestre.etapes[0].etape_apo or ""
n = 2
- for et in sem.etapes[1:]:
+ for et in formsemestre.etapes[1:]:
el["etape_apo" + str(n)] = et.etape_apo or ""
n += 1
x = Element("bulletinetud", **el)
@@ -120,78 +121,72 @@ def bulletin_but_xml_compat(
return sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(
scu.SCO_ENCODING
) # stop !
- # Moyenne générale:
- doc.append(
- Element(
- "note",
- value=scu.fmt_note(results.etud_moy_gen[etud.id]),
- min=scu.fmt_note(results.etud_moy_gen.min()),
- max=scu.fmt_note(results.etud_moy_gen.max()),
- moy=scu.fmt_note(results.etud_moy_gen.mean()), # moyenne des moy. gen.
- )
- )
- rang = 0 # XXX TODO rang de l'étduiant selon la moy gen indicative
- bonus = 0 # XXX TODO valeur du bonus sport
- doc.append(Element("rang", value=str(rang), ninscrits=str(nb_inscrits)))
- # XXX TODO: ajouter "rang_group" : rangs dans les partitions
- doc.append(Element("note_max", value="20")) # notes toujours sur 20
- doc.append(Element("bonus_sport_culture", value=str(bonus)))
- # Liste les UE / modules /evals
- for ue in results.ues:
- rang_ue = 0 # XXX TODO rang de l'étudiant dans cette UE
- nb_inscrits_ue = (
- nb_inscrits # approx: compliqué de définir le "nb d'inscrit à une UE"
- )
- x_ue = Element(
- "ue",
- id=str(ue.id),
- numero=scu.quote_xml_attr(ue.numero),
- acronyme=scu.quote_xml_attr(ue.acronyme or ""),
- titre=scu.quote_xml_attr(ue.titre or ""),
- code_apogee=scu.quote_xml_attr(ue.code_apogee or ""),
- )
- doc.append(x_ue)
- if ue.type != sco_codes_parcours.UE_SPORT:
- v = results.etud_moy_ue[ue.id][etud.id]
- else:
- v = 0 # XXX TODO valeur bonus sport pour cet étudiant
- x_ue.append(
+
+ if etat_inscription == scu.INSCRIT:
+ # Moyenne générale:
+ doc.append(
Element(
"note",
- value=scu.fmt_note(v),
- min=scu.fmt_note(results.etud_moy_ue[ue.id].min()),
- max=scu.fmt_note(results.etud_moy_ue[ue.id].max()),
+ value=scu.fmt_note(results.etud_moy_gen[etud.id]),
+ min=scu.fmt_note(results.etud_moy_gen.min()),
+ max=scu.fmt_note(results.etud_moy_gen.max()),
+ moy=scu.fmt_note(results.etud_moy_gen.mean()), # moyenne des moy. gen.
)
)
- x_ue.append(Element("ects", value=str(ue.ects if ue.ects else 0)))
- x_ue.append(Element("rang", value=str(rang_ue)))
- x_ue.append(Element("effectif", value=str(nb_inscrits_ue)))
- # Liste les modules rattachés à cette UE
- for modimpl in results.modimpls:
- # Liste ici uniquement les modules rattachés à cette UE
- if modimpl.module.ue.id == ue.id:
- mod_moy = scu.fmt_note(results.etud_moy_ue[ue.id][etud.id])
- coef = results.modimpl_coefs_df[modimpl.id][ue.id]
- x_mod = Element(
- "module",
- id=str(modimpl.id),
- code=str(modimpl.module.code or ""),
- coefficient=str(coef),
- numero=str(modimpl.module.numero or 0),
- titre=scu.quote_xml_attr(modimpl.module.titre or ""),
- abbrev=scu.quote_xml_attr(modimpl.module.abbrev or ""),
- code_apogee=scu.quote_xml_attr(modimpl.module.code_apogee or ""),
+ rang = 0 # XXX TODO rang de l'étduiant selon la moy gen indicative
+ bonus = 0 # XXX TODO valeur du bonus sport
+ doc.append(Element("rang", value=str(rang), ninscrits=str(nb_inscrits)))
+ # XXX TODO: ajouter "rang_group" : rangs dans les partitions
+ doc.append(Element("note_max", value="20")) # notes toujours sur 20
+ doc.append(Element("bonus_sport_culture", value=str(bonus)))
+ # Liste les UE / modules /evals
+ for ue in results.ues:
+ rang_ue = 0 # XXX TODO rang de l'étudiant dans cette UE
+ nb_inscrits_ue = (
+ nb_inscrits # approx: compliqué de définir le "nb d'inscrit à une UE"
+ )
+ x_ue = Element(
+ "ue",
+ id=str(ue.id),
+ numero=scu.quote_xml_attr(ue.numero),
+ acronyme=scu.quote_xml_attr(ue.acronyme or ""),
+ titre=scu.quote_xml_attr(ue.titre or ""),
+ code_apogee=scu.quote_xml_attr(ue.code_apogee or ""),
+ )
+ doc.append(x_ue)
+ if ue.type != sco_codes_parcours.UE_SPORT:
+ v = results.etud_moy_ue[ue.id][etud.id]
+ else:
+ v = 0 # XXX TODO valeur bonus sport pour cet étudiant
+ x_ue.append(
+ Element(
+ "note",
+ value=scu.fmt_note(v),
+ min=scu.fmt_note(results.etud_moy_ue[ue.id].min()),
+ max=scu.fmt_note(results.etud_moy_ue[ue.id].max()),
)
- x_ue.append(x_mod)
- x_mod.append(
- Element(
- "note",
- value=mod_moy,
- min=scu.fmt_note(results.etud_moy_ue[ue.id].min()),
- max=scu.fmt_note(results.etud_moy_ue[ue.id].max()),
- moy=scu.fmt_note(results.etud_moy_ue[ue.id].mean()),
+ )
+ x_ue.append(Element("ects", value=str(ue.ects if ue.ects else 0)))
+ x_ue.append(Element("rang", value=str(rang_ue)))
+ x_ue.append(Element("effectif", value=str(nb_inscrits_ue)))
+ # Liste les modules rattachés à cette UE
+ for modimpl in results.modimpls:
+ # Liste ici uniquement les modules rattachés à cette UE
+ if modimpl.module.ue.id == ue.id:
+ # mod_moy = scu.fmt_note(results.etud_moy_ue[ue.id][etud.id])
+ coef = results.modimpl_coefs_df[modimpl.id][ue.id]
+ x_mod = Element(
+ "module",
+ id=str(modimpl.id),
+ code=str(modimpl.module.code or ""),
+ coefficient=str(coef),
+ numero=str(modimpl.module.numero or 0),
+ titre=scu.quote_xml_attr(modimpl.module.titre or ""),
+ abbrev=scu.quote_xml_attr(modimpl.module.abbrev or ""),
+ code_apogee=scu.quote_xml_attr(
+ modimpl.module.code_apogee or ""
+ ),
)
- )
# XXX TODO rangs et effectifs
# --- notes de chaque eval:
if version != "short":
@@ -226,11 +221,11 @@ def bulletin_but_xml_compat(
)
)
# XXX TODO: Evaluations incomplètes ou futures: XXX
- # XXX TODO UE capitalisee (listee seulement si meilleure que l'UE courante)
+ # XXX TODO UE capitalisee (listee seulement si meilleure que l'UE courante)
# --- Absences
if sco_preferences.get_preference("bul_show_abs", formsemestre_id):
- nbabs, nbabsjust = sem.get_abs_count(etud.id)
+ nbabs, nbabsjust = formsemestre.get_abs_count(etud.id)
doc.append(Element("absences", nbabs=str(nbabs), nbabsjust=str(nbabsjust)))
# -------- LA SUITE EST COPIEE SANS MODIF DE sco_bulletins_xml.py ---------
diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py
index fe48555efa..2aa36da9cb 100644
--- a/app/models/moduleimpls.py
+++ b/app/models/moduleimpls.py
@@ -44,6 +44,9 @@ class ModuleImpl(db.Model):
def __init__(self, **kwargs):
super(ModuleImpl, self).__init__(**kwargs)
+ def __repr__(self):
+ return f"<{self.__class__.__name__} {self.id} module={repr(self.module)}>"
+
def get_evaluations_poids(self) -> pd.DataFrame:
"""Les poids des évaluations vers les UE (accès via cache)"""
evaluations_poids = df_cache.EvaluationsPoidsCache.get(self.id)
diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py
index 07ff217ab4..6b7884591a 100644
--- a/app/scodoc/sco_edit_ue.py
+++ b/app/scodoc/sco_edit_ue.py
@@ -470,7 +470,13 @@ def ue_delete(ue_id=None, delete_validations=False, dialog_confirmed=False):
if ue.modules.all():
raise ScoValueError(
f"""Suppression de l'UE {ue.titre} impossible car
- des modules (ou SAÉ ou ressources) lui sont rattachés."""
+ des modules (ou SAÉ ou ressources) lui sont rattachés.""",
+ dest_url=url_for(
+ "notes.ue_table",
+ scodoc_dept=g.scodoc_dept,
+ formation_id=ue.formation.id,
+ semestre_idx=ue.semestre_idx,
+ ),
)
if not can_delete_ue(ue):
raise ScoNonEmptyFormationObject(
diff --git a/app/static/css/releve-but.css b/app/static/css/releve-but.css
index 60d4f01c1e..3f132d6a40 100644
--- a/app/static/css/releve-but.css
+++ b/app/static/css/releve-but.css
@@ -77,6 +77,17 @@ section>div:nth-child(1){
display: flex !important;
}
+.listeOff .ue::before,
+.listeOff .module::before,
+.moduleOnOff .ue::before,
+.moduleOnOff .module::before{
+ transform: rotate(0);
+}
+.listeOff .moduleOnOff .ue::before,
+.listeOff .moduleOnOff .module::before{
+ transform: rotate(180deg) !important;
+}
+
/***********************/
/* Options d'affichage */
/***********************/
@@ -118,11 +129,16 @@ section>div:nth-child(1){
/************/
/* Semestre */
/************/
+.flex{
+ display: flex;
+ gap: 16px;
+}
.infoSemestre{
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 4px;
+ flex: none;
}
.infoSemestre>div{
border: 1px solid var(--couleurIntense);
@@ -141,7 +157,12 @@ section>div:nth-child(1){
.rang{
text-decoration: underline var(--couleurIntense);
}
-
+.decision{
+ margin: 5px 0;
+ font-weight: bold;
+ font-size: 20px;
+ text-decoration: underline var(--couleurIntense);
+}
.enteteSemestre{
color: black;
font-weight: bold;
@@ -174,8 +195,21 @@ section>div:nth-child(1){
display: flex;
gap: 16px;
margin: 4px 0 2px 0;
- overflow: auto;
+ overflow-x: auto;
+ overflow-y: hidden;
cursor: pointer;
+ position: relative;
+}
+.module::before, .ue::before {
+ content:url("data:image/svg+xml;utf8,");
+ width: 26px;
+ height: 26px;
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ margin-left: -13px;
+ transform: rotate(180deg);
+ transition: 0.2s;
}
h3{
display: flex;
diff --git a/app/static/js/releve-but.js b/app/static/js/releve-but.js
index 126cb219ea..5042031b37 100644
--- a/app/static/js/releve-but.js
+++ b/app/static/js/releve-but.js
@@ -75,10 +75,15 @@ class releveBUT extends HTMLElement {
Semestre
-