diff --git a/app/scodoc/sco_archives.py b/app/scodoc/sco_archives.py index 5e09bf96..00e02c9d 100644 --- a/app/scodoc/sco_archives.py +++ b/app/scodoc/sco_archives.py @@ -344,7 +344,7 @@ def do_formsemestre_archive( if data: PVArchive.store(archive_id, "Tableau_moyennes" + scu.XLSX_SUFFIX, data) # Tableau recap notes en HTML (pour tous les etudiants, n'utilise pas les groupes) - table_html, _ = gen_formsemestre_recapcomplet_html_table( + table_html, _, _ = gen_formsemestre_recapcomplet_html_table( formsemestre, res, include_evaluations=True ) if table_html: diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index 9ebe4e87..791fdb0f 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -27,6 +27,7 @@ """Tableau récapitulatif des notes d'un semestre """ +import collections import datetime import time from xml.etree import ElementTree @@ -109,7 +110,7 @@ def formsemestre_recapcomplet( force_publishing=force_publishing, ) - table_html, table = _formsemestre_recapcomplet_to_html( + table_html, table, freq_codes_annuels = _formsemestre_recapcomplet_to_html( formsemestre, filename=filename, mode_jury=mode_jury, @@ -215,33 +216,37 @@ def formsemestre_recapcomplet( """ ) - if mode_jury and table and sum(table.freq_codes_annuels.values()) > 0: + if mode_jury and freq_codes_annuels and sum(freq_codes_annuels.values()) > 0: + nb_etud_avec_decision_annuelle = ( + sum(freq_codes_annuels.values()) - freq_codes_annuels["total"] + ) H.append( f"""
-
Nb d'étudiants avec décision annuelle: - {sum(table.freq_codes_annuels.values())} / {len(table)} +
Nb d'étudiants avec décision annuelle: + {nb_etud_avec_decision_annuelle} / {freq_codes_annuels["total"]}
-
Codes annuels octroyés:
- """ ) - for code in sorted(table.freq_codes_annuels.keys()): + if nb_etud_avec_decision_annuelle > 0: H.append( - f""" - - - - """ + """
Codes annuels octroyés:
+
{code}{table.freq_codes_annuels[code]}{ - (100*table.freq_codes_annuels[code] / len(table)):2.1f}% -
+ """ ) - H.append( - """ -
-
- """ - ) + for code in sorted(freq_codes_annuels.keys()): + if code != "total": + H.append( + f""" + {code} + {freq_codes_annuels[code]} + { + (100*freq_codes_annuels[code] / freq_codes_annuels["total"]):2.1f}% + + """ + ) + H.append("""""") + H.append("""
""") # Légende H.append( """ @@ -272,12 +277,12 @@ def _formsemestre_recapcomplet_to_html( filename: str = "", mode_jury=False, # saisie décisions jury selected_etudid=None, -) -> tuple[str, TableRecap]: +) -> tuple[str, TableRecap, collections.Counter]: """Le tableau recap en html""" if tabformat not in ("html", "evals"): raise ScoValueError("invalid table format") res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) - table_html, table = gen_formsemestre_recapcomplet_html_table( + table_html, table, freq_codes_annuels = gen_formsemestre_recapcomplet_html_table( formsemestre, res, include_evaluations=(tabformat == "evals"), @@ -285,7 +290,7 @@ def _formsemestre_recapcomplet_to_html( filename=filename, selected_etudid=selected_etudid, ) - return table_html, table + return table_html, table, freq_codes_annuels def _formsemestre_recapcomplet_to_file( @@ -447,9 +452,9 @@ def gen_formsemestre_recapcomplet_html_table( mode_jury=False, filename="", selected_etudid=None, -) -> tuple[str, TableRecap]: +) -> tuple[str, TableRecap, collections.Counter]: """Construit table recap pour le BUT - Cache le résultat pour le semestre (sauf en mode jury). + Cache le résultat pour le semestre. Note: on cache le HTML et non l'objet Table. Si mode_jury, occultera colonnes modules (en js) @@ -461,6 +466,7 @@ def gen_formsemestre_recapcomplet_html_table( """ table = None table_html = None + table_html_cached = None cache_class = { (True, True): sco_cache.TableJuryWithEvalsCache, (True, False): sco_cache.TableJuryCache, @@ -468,8 +474,8 @@ def gen_formsemestre_recapcomplet_html_table( (False, False): sco_cache.TableRecapCache, }[(bool(mode_jury), bool(include_evaluations))] if not selected_etudid: - table_html = cache_class.get(formsemestre.id) - if table_html is None: + table_html_cached = cache_class.get(formsemestre.id) + if table_html_cached is None: table = _gen_formsemestre_recapcomplet_table( res, include_evaluations, @@ -478,9 +484,14 @@ def gen_formsemestre_recapcomplet_html_table( selected_etudid=selected_etudid, ) table_html = table.html() - cache_class.set(formsemestre.id, table_html) + freq_codes_annuels = ( + table.freq_codes_annuels if hasattr(table, "freq_codes_annuels") else None + ) + cache_class.set(formsemestre.id, (table_html, freq_codes_annuels)) + else: + table_html, freq_codes_annuels = table_html_cached - return table_html, table + return table_html, table, freq_codes_annuels def _gen_formsemestre_recapcomplet_table( diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css index 4f922c9d..172e9008 100644 --- a/app/static/css/scodoc.css +++ b/app/static/css/scodoc.css @@ -2773,6 +2773,8 @@ table.notes_recapcomplet a:hover { div.table_recap_caption { width: fit-content; + margin-top: 8px; + margin-bottom: 8px; padding: 8px; border-radius: 8px; background-color: rgb(202, 255, 180); diff --git a/app/tables/jury_recap.py b/app/tables/jury_recap.py index 8d02065c..3e6f5d24 100644 --- a/app/tables/jury_recap.py +++ b/app/tables/jury_recap.py @@ -78,6 +78,7 @@ class TableJury(TableRecap): dec_rcue = deca.dec_rcue_by_ue.get(rcue.ue_1.id) if dec_rcue is not None: # None si l'UE n'est pas associée à un niveau row.add_rcue_cols(dec_rcue) + self.freq_codes_annuels["total"] = len(self.rows) def add_jury(self): """Ajoute la colonne code jury et le lien.