Skip to content
Snippets Groups Projects
Commit 0d726aa4 authored by Emmanuel Viennet's avatar Emmanuel Viennet
Browse files

Table recap: UE validables. Closes #260

parent c65689b2
No related branches found
No related tags found
No related merge requests found
...@@ -419,21 +419,23 @@ class ResultatsSemestre(ResultatsCache): ...@@ -419,21 +419,23 @@ class ResultatsSemestre(ResultatsCache):
else: else:
fmt_note = lambda x: x fmt_note = lambda x: x
barre_moy = ( parcours = self.formsemestre.formation.get_parcours()
self.formsemestre.formation.get_parcours().BARRE_MOY - scu.NOTES_TOLERANCE barre_moy = parcours.BARRE_MOY - scu.NOTES_TOLERANCE
) barre_valid_ue = parcours.NOTES_BARRE_VALID_UE
barre_valid_ue = self.formsemestre.formation.get_parcours().NOTES_BARRE_VALID_UE barre_warning_ue = parcours.BARRE_UE_DISPLAY_WARNING
NO_NOTE = "-" # contenu des cellules sans notes NO_NOTE = "-" # contenu des cellules sans notes
rows = [] rows = []
# column_id : title # column_id : title
titles = { titles = {
"rang": "Rg", "rang": "Rg",
# ordre des colonnes: # ordre des colonnes de gauche à droite:
"_civilite_str_col_order": 2, "_civilite_str_col_order": 2,
"_nom_disp_col_order": 3, "_nom_disp_col_order": 3,
"_prenom_col_order": 4, "_prenom_col_order": 4,
"_nom_short_col_order": 5, "_nom_short_col_order": 5,
"_rang_col_order": 6, "_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: # les titres en footer: les mêmes, mais avec des bulles et liens:
titles_bot = {} titles_bot = {}
...@@ -452,6 +454,7 @@ class ResultatsSemestre(ResultatsCache): ...@@ -452,6 +454,7 @@ class ResultatsSemestre(ResultatsCache):
etuds_inscriptions = self.formsemestre.etuds_inscriptions etuds_inscriptions = self.formsemestre.etuds_inscriptions
ues = self.formsemestre.query_ues(with_sport=True) # avec bonus 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 modimpl_ids = set() # modimpl effectivement présents dans la table
for etudid in etuds_inscriptions: for etudid in etuds_inscriptions:
etud = Identite.query.get(etudid) etud = Identite.query.get(etudid)
...@@ -479,7 +482,7 @@ class ResultatsSemestre(ResultatsCache): ...@@ -479,7 +482,7 @@ class ResultatsSemestre(ResultatsCache):
if moy_gen is False: if moy_gen is False:
moy_gen = NO_NOTE moy_gen = NO_NOTE
elif isinstance(moy_gen, float) and moy_gen < barre_moy: elif isinstance(moy_gen, float) and moy_gen < barre_moy:
note_class = " moy_inf" note_class = " moy_ue_warning" # en rouge
add_cell( add_cell(
row, row,
"moy_gen", "moy_gen",
...@@ -491,7 +494,8 @@ class ResultatsSemestre(ResultatsCache): ...@@ -491,7 +494,8 @@ class ResultatsSemestre(ResultatsCache):
'title="moyenne indicative"' if self.is_apc else "" 'title="moyenne indicative"' if self.is_apc else ""
) )
# --- Moyenne d'UE # --- 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) ue_status = self.get_etud_ue_status(etudid, ue.id)
if ue_status is not None: if ue_status is not None:
col_id = f"moy_ue_{ue.id}" col_id = f"moy_ue_{ue.id}"
...@@ -502,6 +506,10 @@ class ResultatsSemestre(ResultatsCache): ...@@ -502,6 +506,10 @@ class ResultatsSemestre(ResultatsCache):
note_class = " moy_inf" note_class = " moy_inf"
elif val >= barre_valid_ue: elif val >= barre_valid_ue:
note_class = " moy_ue_valid" 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( add_cell(
row, row,
col_id, col_id,
...@@ -557,7 +565,21 @@ class ResultatsSemestre(ResultatsCache): ...@@ -557,7 +565,21 @@ class ResultatsSemestre(ResultatsCache):
title="{modimpl.module.titre} title="{modimpl.module.titre}
({sco_users.user_info(modimpl.responsable_id)['nomcomplet']})" """ ({sco_users.user_info(modimpl.responsable_id)['nomcomplet']})" """
modimpl_ids.add(modimpl.id) 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) rows.append(row)
self._recap_add_partitions(rows, titles) self._recap_add_partitions(rows, titles)
self._recap_add_admissions(rows, titles) self._recap_add_admissions(rows, titles)
...@@ -565,9 +587,7 @@ class ResultatsSemestre(ResultatsCache): ...@@ -565,9 +587,7 @@ class ResultatsSemestre(ResultatsCache):
rows.sort(key=lambda e: e["_rang_order"]) rows.sort(key=lambda e: e["_rang_order"])
# INFOS POUR FOOTER # INFOS POUR FOOTER
bottom_infos = self._recap_bottom_infos( bottom_infos = self._recap_bottom_infos(ues_sans_bonus, modimpl_ids, fmt_note)
[ue for ue in ues if ue.type != UE_SPORT], modimpl_ids, fmt_note
)
# --- TABLE FOOTER: ECTS, moyennes, min, max... # --- TABLE FOOTER: ECTS, moyennes, min, max...
footer_rows = [] footer_rows = []
...@@ -667,7 +687,7 @@ class ResultatsSemestre(ResultatsCache): ...@@ -667,7 +687,7 @@ class ResultatsSemestre(ResultatsCache):
def _recap_add_admissions(self, rows: list[dict], titles: dict): def _recap_add_admissions(self, rows: list[dict], titles: dict):
"""Ajoute les colonnes "admission" """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" Les colonnes ont la classe css "admission"
""" """
fields = { fields = {
...@@ -693,7 +713,7 @@ class ResultatsSemestre(ResultatsCache): ...@@ -693,7 +713,7 @@ class ResultatsSemestre(ResultatsCache):
def _recap_add_partitions(self, rows: list[dict], titles: dict): def _recap_add_partitions(self, rows: list[dict], titles: dict):
"""Ajoute les colonnes indiquant les groupes """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" Les colonnes ont la classe css "partition"
""" """
partitions, partitions_etud_groups = sco_groups.get_formsemestre_groups( partitions, partitions_etud_groups = sco_groups.get_formsemestre_groups(
......
...@@ -51,8 +51,8 @@ from app.scodoc.sco_formsemestre import ( ...@@ -51,8 +51,8 @@ from app.scodoc.sco_formsemestre import (
from app.scodoc.sco_codes_parcours import ( from app.scodoc.sco_codes_parcours import (
DEF, DEF,
UE_SPORT, UE_SPORT,
UE_is_fondamentale, ue_is_fondamentale,
UE_is_professionnelle, ue_is_professionnelle,
) )
from app.scodoc.sco_parcours_dut import formsemestre_get_etud_capitalisation from app.scodoc.sco_parcours_dut import formsemestre_get_etud_capitalisation
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
...@@ -826,11 +826,11 @@ class NotesTable: ...@@ -826,11 +826,11 @@ class NotesTable:
and mu["moy"] >= self.parcours.NOTES_BARRE_VALID_UE and mu["moy"] >= self.parcours.NOTES_BARRE_VALID_UE
): ):
mu["ects_pot"] = ue["ects"] or 0.0 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"] mu["ects_pot_fond"] = mu["ects_pot"]
else: else:
mu["ects_pot_fond"] = 0.0 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"] mu["ects_pot_pro"] = mu["ects_pot"]
else: else:
mu["ects_pot_pro"] = 0.0 mu["ects_pot_pro"] = 0.0
......
...@@ -81,11 +81,11 @@ UE_PROFESSIONNELLE = 5 # UE "professionnelle" (ISCID, ...) ...@@ -81,11 +81,11 @@ UE_PROFESSIONNELLE = 5 # UE "professionnelle" (ISCID, ...)
UE_OPTIONNELLE = 6 # UE non fondamentales (ILEPS, ...) 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) return ue_type in (UE_STANDARD, UE_STAGE_LP, UE_PROFESSIONNELLE)
def UE_is_professionnelle(ue_type): def ue_is_professionnelle(ue_type):
return ( return (
ue_type == UE_PROFESSIONNELLE ue_type == UE_PROFESSIONNELLE
) # NB: les UE_PROFESSIONNELLE sont à la fois fondamentales et pro ) # NB: les UE_PROFESSIONNELLE sont à la fois fondamentales et pro
...@@ -211,7 +211,7 @@ DEVENIRS_NEXT2 = {NEXT_OR_NEXT2: 1, NEXT2: 1} ...@@ -211,7 +211,7 @@ DEVENIRS_NEXT2 = {NEXT_OR_NEXT2: 1, NEXT2: 1}
NO_SEMESTRE_ID = -1 # code semestre si pas de semestres NO_SEMESTRE_ID = -1 # code semestre si pas de semestres
# Regles gestion parcours # Règles gestion parcours
class DUTRule(object): class DUTRule(object):
def __init__(self, rule_id, premise, conclusion): def __init__(self, rule_id, premise, conclusion):
self.rule_id = rule_id self.rule_id = rule_id
...@@ -222,13 +222,13 @@ class DUTRule(object): ...@@ -222,13 +222,13 @@ class DUTRule(object):
def match(self, state): def match(self, state):
"True if state match rule premise" "True if state match rule premise"
assert len(state) == len(self.premise) assert len(state) == len(self.premise)
for i in range(len(state)): for i, stat in enumerate(state):
prem = self.premise[i] prem = self.premise[i]
if isinstance(prem, (list, tuple)): if isinstance(prem, (list, tuple)):
if not state[i] in prem: if not stat in prem:
return False return False
else: else:
if prem != ALL and prem != state[i]: if prem not in (ALL, stat):
return False return False
return True return True
...@@ -244,6 +244,7 @@ class TypeParcours(object): ...@@ -244,6 +244,7 @@ class TypeParcours(object):
COMPENSATION_UE = True # inutilisé COMPENSATION_UE = True # inutilisé
BARRE_MOY = 10.0 BARRE_MOY = 10.0
BARRE_UE_DEFAULT = 8.0 BARRE_UE_DEFAULT = 8.0
BARRE_UE_DISPLAY_WARNING = 8.0
BARRE_UE = {} BARRE_UE = {}
NOTES_BARRE_VALID_UE_TH = 10.0 # seuil pour valider 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 NOTES_BARRE_VALID_UE = NOTES_BARRE_VALID_UE_TH - NOTES_TOLERANCE # barre sur UE
......
...@@ -931,6 +931,9 @@ def icontag(name, file_format="png", no_size=False, **attrs): ...@@ -931,6 +931,9 @@ def icontag(name, file_format="png", no_size=False, **attrs):
ICON_PDF = icontag("pdficon16x20_img", title="Version PDF") ICON_PDF = icontag("pdficon16x20_img", title="Version PDF")
ICON_XLS = icontag("xlsicon_img", title="Version tableur") ICON_XLS = icontag("xlsicon_img", title="Version tableur")
# HTML emojis
EMO_WARNING = "&#9888;&#65039;" # warning /!\
def sort_dates(L, reverse=False): def sort_dates(L, reverse=False):
"""Return sorted list of dates, allowing None items (they are put at the beginning)""" """Return sorted list of dates, allowing None items (they are put at the beginning)"""
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment