Table recap: UE validables. Closes #260

This commit is contained in:
Emmanuel Viennet 2022-04-02 14:26:16 +02:00
parent c65689b2a3
commit 0d726aa428
5 changed files with 1470 additions and 1010 deletions

View File

@ -419,21 +419,23 @@ class ResultatsSemestre(ResultatsCache):
else:
fmt_note = lambda x: x
barre_moy = (
self.formsemestre.formation.get_parcours().BARRE_MOY - scu.NOTES_TOLERANCE
)
barre_valid_ue = self.formsemestre.formation.get_parcours().NOTES_BARRE_VALID_UE
parcours = self.formsemestre.formation.get_parcours()
barre_moy = parcours.BARRE_MOY - scu.NOTES_TOLERANCE
barre_valid_ue = parcours.NOTES_BARRE_VALID_UE
barre_warning_ue = parcours.BARRE_UE_DISPLAY_WARNING
NO_NOTE = "-" # contenu des cellules sans notes
rows = []
# column_id : title
titles = {
"rang": "Rg",
# ordre des colonnes:
# ordre des colonnes de gauche à droite:
"_civilite_str_col_order": 2,
"_nom_disp_col_order": 3,
"_prenom_col_order": 4,
"_nom_short_col_order": 5,
"_rang_col_order": 6,
# les colonnes des groupes sont à la position 10
"_ues_validables_col_order": 20,
}
# les titres en footer: les mêmes, mais avec des bulles et liens:
titles_bot = {}
@ -452,6 +454,7 @@ class ResultatsSemestre(ResultatsCache):
etuds_inscriptions = self.formsemestre.etuds_inscriptions
ues = self.formsemestre.query_ues(with_sport=True) # avec bonus
ues_sans_bonus = [ue for ue in ues if ue.type != UE_SPORT]
modimpl_ids = set() # modimpl effectivement présents dans la table
for etudid in etuds_inscriptions:
etud = Identite.query.get(etudid)
@ -479,7 +482,7 @@ class ResultatsSemestre(ResultatsCache):
if moy_gen is False:
moy_gen = NO_NOTE
elif isinstance(moy_gen, float) and moy_gen < barre_moy:
note_class = " moy_inf"
note_class = " moy_ue_warning" # en rouge
add_cell(
row,
"moy_gen",
@ -491,7 +494,8 @@ class ResultatsSemestre(ResultatsCache):
'title="moyenne indicative"' if self.is_apc else ""
)
# --- Moyenne d'UE
for ue in [ue for ue in ues if ue.type != UE_SPORT]:
nb_ues_validables, nb_ues_warning = 0, 0
for ue in ues_sans_bonus:
ue_status = self.get_etud_ue_status(etudid, ue.id)
if ue_status is not None:
col_id = f"moy_ue_{ue.id}"
@ -502,6 +506,10 @@ class ResultatsSemestre(ResultatsCache):
note_class = " moy_inf"
elif val >= barre_valid_ue:
note_class = " moy_ue_valid"
nb_ues_validables += 1
if val < barre_warning_ue:
note_class = " moy_ue_warning" # notes très basses
nb_ues_warning += 1
add_cell(
row,
col_id,
@ -557,7 +565,21 @@ class ResultatsSemestre(ResultatsCache):
title="{modimpl.module.titre}
({sco_users.user_info(modimpl.responsable_id)['nomcomplet']})" """
modimpl_ids.add(modimpl.id)
ue_valid_txt = f"{nb_ues_validables}/{len(ues_sans_bonus)}"
if nb_ues_warning:
ue_valid_txt += " " + scu.EMO_WARNING
add_cell(
row,
"ues_validables",
"Nb UE",
ue_valid_txt,
"col_ue col_ues_validables",
)
if nb_ues_warning:
row["_ues_validables_class"] += " moy_ue_warning"
elif nb_ues_validables < len(ues_sans_bonus):
row["_ues_validables_class"] += " moy_inf"
row["_ues_validables_order"] = nb_ues_validables # pour tri
rows.append(row)
self._recap_add_partitions(rows, titles)
self._recap_add_admissions(rows, titles)
@ -565,9 +587,7 @@ class ResultatsSemestre(ResultatsCache):
rows.sort(key=lambda e: e["_rang_order"])
# INFOS POUR FOOTER
bottom_infos = self._recap_bottom_infos(
[ue for ue in ues if ue.type != UE_SPORT], modimpl_ids, fmt_note
)
bottom_infos = self._recap_bottom_infos(ues_sans_bonus, modimpl_ids, fmt_note)
# --- TABLE FOOTER: ECTS, moyennes, min, max...
footer_rows = []
@ -667,7 +687,7 @@ class ResultatsSemestre(ResultatsCache):
def _recap_add_admissions(self, rows: list[dict], titles: dict):
"""Ajoute les colonnes "admission"
rows est une liste de dict avec un clé "etudid"
rows est une liste de dict avec une clé "etudid"
Les colonnes ont la classe css "admission"
"""
fields = {
@ -693,7 +713,7 @@ class ResultatsSemestre(ResultatsCache):
def _recap_add_partitions(self, rows: list[dict], titles: dict):
"""Ajoute les colonnes indiquant les groupes
rows est une liste de dict avec un clé "etudid"
rows est une liste de dict avec une clé "etudid"
Les colonnes ont la classe css "partition"
"""
partitions, partitions_etud_groups = sco_groups.get_formsemestre_groups(

View File

@ -51,8 +51,8 @@ from app.scodoc.sco_formsemestre import (
from app.scodoc.sco_codes_parcours import (
DEF,
UE_SPORT,
UE_is_fondamentale,
UE_is_professionnelle,
ue_is_fondamentale,
ue_is_professionnelle,
)
from app.scodoc.sco_parcours_dut import formsemestre_get_etud_capitalisation
from app.scodoc import sco_codes_parcours
@ -826,11 +826,11 @@ class NotesTable:
and mu["moy"] >= self.parcours.NOTES_BARRE_VALID_UE
):
mu["ects_pot"] = ue["ects"] or 0.0
if UE_is_fondamentale(ue["type"]):
if ue_is_fondamentale(ue["type"]):
mu["ects_pot_fond"] = mu["ects_pot"]
else:
mu["ects_pot_fond"] = 0.0
if UE_is_professionnelle(ue["type"]):
if ue_is_professionnelle(ue["type"]):
mu["ects_pot_pro"] = mu["ects_pot"]
else:
mu["ects_pot_pro"] = 0.0

View File

@ -81,11 +81,11 @@ UE_PROFESSIONNELLE = 5 # UE "professionnelle" (ISCID, ...)
UE_OPTIONNELLE = 6 # UE non fondamentales (ILEPS, ...)
def UE_is_fondamentale(ue_type):
def ue_is_fondamentale(ue_type):
return ue_type in (UE_STANDARD, UE_STAGE_LP, UE_PROFESSIONNELLE)
def UE_is_professionnelle(ue_type):
def ue_is_professionnelle(ue_type):
return (
ue_type == UE_PROFESSIONNELLE
) # NB: les UE_PROFESSIONNELLE sont à la fois fondamentales et pro
@ -211,7 +211,7 @@ DEVENIRS_NEXT2 = {NEXT_OR_NEXT2: 1, NEXT2: 1}
NO_SEMESTRE_ID = -1 # code semestre si pas de semestres
# Regles gestion parcours
# Règles gestion parcours
class DUTRule(object):
def __init__(self, rule_id, premise, conclusion):
self.rule_id = rule_id
@ -222,13 +222,13 @@ class DUTRule(object):
def match(self, state):
"True if state match rule premise"
assert len(state) == len(self.premise)
for i in range(len(state)):
for i, stat in enumerate(state):
prem = self.premise[i]
if isinstance(prem, (list, tuple)):
if not state[i] in prem:
if not stat in prem:
return False
else:
if prem != ALL and prem != state[i]:
if prem not in (ALL, stat):
return False
return True
@ -244,6 +244,7 @@ class TypeParcours(object):
COMPENSATION_UE = True # inutilisé
BARRE_MOY = 10.0
BARRE_UE_DEFAULT = 8.0
BARRE_UE_DISPLAY_WARNING = 8.0
BARRE_UE = {}
NOTES_BARRE_VALID_UE_TH = 10.0 # seuil pour valider UE
NOTES_BARRE_VALID_UE = NOTES_BARRE_VALID_UE_TH - NOTES_TOLERANCE # barre sur UE

View File

@ -931,6 +931,9 @@ def icontag(name, file_format="png", no_size=False, **attrs):
ICON_PDF = icontag("pdficon16x20_img", title="Version PDF")
ICON_XLS = icontag("xlsicon_img", title="Version tableur")
# HTML emojis
EMO_WARNING = "&#9888;&#65039;" # warning /!\
def sort_dates(L, reverse=False):
"""Return sorted list of dates, allowing None items (they are put at the beginning)"""

File diff suppressed because it is too large Load Diff