Table jury: affichage stats codes annuels octroyés sous la table

This commit is contained in:
Emmanuel Viennet 2023-06-20 12:14:16 +02:00
parent d1d83e0327
commit 47cf5962f9
4 changed files with 44 additions and 30 deletions

View File

@ -344,7 +344,7 @@ def do_formsemestre_archive(
if data: if data:
PVArchive.store(archive_id, "Tableau_moyennes" + scu.XLSX_SUFFIX, 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) # 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 formsemestre, res, include_evaluations=True
) )
if table_html: if table_html:

View File

@ -27,6 +27,7 @@
"""Tableau récapitulatif des notes d'un semestre """Tableau récapitulatif des notes d'un semestre
""" """
import collections
import datetime import datetime
import time import time
from xml.etree import ElementTree from xml.etree import ElementTree
@ -109,7 +110,7 @@ def formsemestre_recapcomplet(
force_publishing=force_publishing, force_publishing=force_publishing,
) )
table_html, table = _formsemestre_recapcomplet_to_html( table_html, table, freq_codes_annuels = _formsemestre_recapcomplet_to_html(
formsemestre, formsemestre,
filename=filename, filename=filename,
mode_jury=mode_jury, 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( H.append(
f""" f"""
<div class="jury_stats"> <div class="jury_stats">
<div>Nb d'étudiants avec décision annuelle: <div><b>Nb d'étudiants avec décision annuelle:</b>
{sum(table.freq_codes_annuels.values())} / {len(table)} {nb_etud_avec_decision_annuelle} / {freq_codes_annuels["total"]}
</div> </div>
<div><b>Codes annuels octroyés:</b></div>
<table class="jury_stats_codes">
""" """
) )
for code in sorted(table.freq_codes_annuels.keys()): if nb_etud_avec_decision_annuelle > 0:
H.append( H.append(
f"""<tr> """<div><b>Codes annuels octroyés:</b></div>
<td>{code}</td> <table class="jury_stats_codes">
<td style="text-align:right">{table.freq_codes_annuels[code]}</td> """
<td style="text-align:right">{
(100*table.freq_codes_annuels[code] / len(table)):2.1f}%
</td>
</tr>"""
) )
H.append( for code in sorted(freq_codes_annuels.keys()):
""" if code != "total":
</table> H.append(
</div> f"""<tr>
""" <td>{code}</td>
) <td style="text-align:right">{freq_codes_annuels[code]}</td>
<td style="text-align:right">{
(100*freq_codes_annuels[code] / freq_codes_annuels["total"]):2.1f}%
</td>
</tr>"""
)
H.append("""</table>""")
H.append("""</div>""")
# Légende # Légende
H.append( H.append(
""" """
@ -272,12 +277,12 @@ def _formsemestre_recapcomplet_to_html(
filename: str = "", filename: str = "",
mode_jury=False, # saisie décisions jury mode_jury=False, # saisie décisions jury
selected_etudid=None, selected_etudid=None,
) -> tuple[str, TableRecap]: ) -> tuple[str, TableRecap, collections.Counter]:
"""Le tableau recap en html""" """Le tableau recap en html"""
if tabformat not in ("html", "evals"): if tabformat not in ("html", "evals"):
raise ScoValueError("invalid table format") raise ScoValueError("invalid table format")
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) 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, formsemestre,
res, res,
include_evaluations=(tabformat == "evals"), include_evaluations=(tabformat == "evals"),
@ -285,7 +290,7 @@ def _formsemestre_recapcomplet_to_html(
filename=filename, filename=filename,
selected_etudid=selected_etudid, selected_etudid=selected_etudid,
) )
return table_html, table return table_html, table, freq_codes_annuels
def _formsemestre_recapcomplet_to_file( def _formsemestre_recapcomplet_to_file(
@ -447,9 +452,9 @@ def gen_formsemestre_recapcomplet_html_table(
mode_jury=False, mode_jury=False,
filename="", filename="",
selected_etudid=None, selected_etudid=None,
) -> tuple[str, TableRecap]: ) -> tuple[str, TableRecap, collections.Counter]:
"""Construit table recap pour le BUT """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. Note: on cache le HTML et non l'objet Table.
Si mode_jury, occultera colonnes modules (en js) Si mode_jury, occultera colonnes modules (en js)
@ -461,6 +466,7 @@ def gen_formsemestre_recapcomplet_html_table(
""" """
table = None table = None
table_html = None table_html = None
table_html_cached = None
cache_class = { cache_class = {
(True, True): sco_cache.TableJuryWithEvalsCache, (True, True): sco_cache.TableJuryWithEvalsCache,
(True, False): sco_cache.TableJuryCache, (True, False): sco_cache.TableJuryCache,
@ -468,8 +474,8 @@ def gen_formsemestre_recapcomplet_html_table(
(False, False): sco_cache.TableRecapCache, (False, False): sco_cache.TableRecapCache,
}[(bool(mode_jury), bool(include_evaluations))] }[(bool(mode_jury), bool(include_evaluations))]
if not selected_etudid: if not selected_etudid:
table_html = cache_class.get(formsemestre.id) table_html_cached = cache_class.get(formsemestre.id)
if table_html is None: if table_html_cached is None:
table = _gen_formsemestre_recapcomplet_table( table = _gen_formsemestre_recapcomplet_table(
res, res,
include_evaluations, include_evaluations,
@ -478,9 +484,14 @@ def gen_formsemestre_recapcomplet_html_table(
selected_etudid=selected_etudid, selected_etudid=selected_etudid,
) )
table_html = table.html() 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( def _gen_formsemestre_recapcomplet_table(

View File

@ -2773,6 +2773,8 @@ table.notes_recapcomplet a:hover {
div.table_recap_caption { div.table_recap_caption {
width: fit-content; width: fit-content;
margin-top: 8px;
margin-bottom: 8px;
padding: 8px; padding: 8px;
border-radius: 8px; border-radius: 8px;
background-color: rgb(202, 255, 180); background-color: rgb(202, 255, 180);

View File

@ -78,6 +78,7 @@ class TableJury(TableRecap):
dec_rcue = deca.dec_rcue_by_ue.get(rcue.ue_1.id) 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 if dec_rcue is not None: # None si l'UE n'est pas associée à un niveau
row.add_rcue_cols(dec_rcue) row.add_rcue_cols(dec_rcue)
self.freq_codes_annuels["total"] = len(self.rows)
def add_jury(self): def add_jury(self):
"""Ajoute la colonne code jury et le lien. """Ajoute la colonne code jury et le lien.