Table recap: UE validables. Closes #260
This commit is contained in:
parent
c65689b2a3
commit
0d726aa428
@ -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):
|
|||||||
|
|
||||||
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):
|
|||||||
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):
|
|||||||
'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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
|
|
||||||
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):
|
|||||||
|
|
||||||
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 (
|
|||||||
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:
|
|||||||
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, ...)
|
|||||||
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}
|
|||||||
|
|
||||||
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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
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 = "⚠️" # 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)"""
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user