1
0
forked from ScoDoc/ScoDoc

Amélioration tableau bord semestre / saisie notes manquantes

This commit is contained in:
Emmanuel Viennet 2022-10-06 14:06:02 +02:00
parent 1847250bab
commit 066e03dae8
6 changed files with 88 additions and 53 deletions

View File

@ -1014,24 +1014,24 @@ def formsemestre_status_head(formsemestre_id=None, page_title=None):
% evals["last_modif"].strftime("%d/%m/%Y à %Hh%M") % evals["last_modif"].strftime("%d/%m/%Y à %Hh%M")
) )
H.append("</td></tr>") H.append("</td></tr>")
if evals["attente"]:
H.append(
"""<tr><td class="fichetitre2"></td><td class="redboldtext">
Il y a des notes en attente ! Le classement des étudiants n'a qu'une valeur indicative.
</td></tr>"""
)
H.append("</table>") H.append("</table>")
sem_warning = "" warnings = []
if sem.bul_hide_xml: if evals["attente"]:
sem_warning += "Bulletins non publiés sur le portail. " warnings.append(
if sem.block_moyennes: """<span class="fontred">Il y a des notes en attente !</span>
sem_warning += "Calcul des moyennes bloqué !" Le classement des étudiants n'a qu'une valeur indicative."""
if sem_warning:
H.append('<p class="fontorange"><em>' + sem_warning + "</em></p>")
if sem.semestre_id >= 0 and not sem.est_sur_une_annee():
H.append(
'<p class="fontorange"><em>Attention: ce semestre couvre plusieurs années scolaires !</em></p>'
) )
if sem.bul_hide_xml:
warnings.append("""Bulletins non publiés sur le portail. """)
if sem.block_moyennes:
warnings.append("Calcul des moyennes bloqué !")
if sem.semestre_id >= 0 and not sem.est_sur_une_annee():
warnings.append("""<em>Ce semestre couvre plusieurs années scolaires !</em>""")
if warnings:
H += [
f"""<div class="formsemestre_status_warning">{warning}</div>"""
for warning in warnings
]
return "".join(H) return "".join(H)
@ -1058,6 +1058,9 @@ def formsemestre_status(formsemestre_id=None):
) )
can_edit = formsemestre.can_be_edited_by(current_user) can_edit = formsemestre.can_be_edited_by(current_user)
can_change_all_notes = current_user.has_permission(Permission.ScoEditAllNotes) or (
current_user.id in [resp.id for resp in formsemestre.responsables]
)
use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id) use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id)
H = [ H = [
@ -1068,7 +1071,9 @@ def formsemestre_status(formsemestre_id=None):
formsemestre_status_head( formsemestre_status_head(
formsemestre_id=formsemestre_id, page_title="Tableau de bord" formsemestre_id=formsemestre_id, page_title="Tableau de bord"
), ),
formsemestre_warning_etuds_sans_note(formsemestre, nt), formsemestre_warning_etuds_sans_note(formsemestre, nt)
if can_change_all_notes
else "",
"""<p><b style="font-size: 130%">Tableau de bord: </b> """<p><b style="font-size: 130%">Tableau de bord: </b>
<span class="help">cliquez sur un module pour saisir des notes</span> <span class="help">cliquez sur un module pour saisir des notes</span>
</p>""", </p>""",
@ -1338,7 +1343,7 @@ def formsemestre_tableau_modules(
def get_formsemestre_etudids_sans_notes( def get_formsemestre_etudids_sans_notes(
formsemestre: FormSemestre, res: ResultatsSemestre formsemestre: FormSemestre, res: ResultatsSemestre
) -> set[int]: ) -> set[int]:
"""Les étudis d'étudiants de ce semestre n'ayant aucune note """Les étudids d'étudiants de ce semestre n'ayant aucune note
alors que d'autres en ont. alors que d'autres en ont.
""" """
# Il y a-t-il des notes déjà saisies ? # Il y a-t-il des notes déjà saisies ?
@ -1398,7 +1403,7 @@ def formsemestre_warning_etuds_sans_note(
else: else:
msg_etuds = f"""{nb_sans_notes} étudiants n'ont aucune note&nbsp;:""" msg_etuds = f"""{nb_sans_notes} étudiants n'ont aucune note&nbsp;:"""
return f"""<div class="warning_inscriptions_notes">Attention: {msg_etuds} return f"""<div class="formsemestre_status_warning">{msg_etuds}
<a class="stdlink" href="{url_for( <a class="stdlink" href="{url_for(
"notes.formsemestre_note_etuds_sans_notes", "notes.formsemestre_note_etuds_sans_notes",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
@ -1410,15 +1415,21 @@ def formsemestre_warning_etuds_sans_note(
""" """
def formsemestre_note_etuds_sans_notes(formsemestre_id: int, code: str = None): def formsemestre_note_etuds_sans_notes(
"""Vue affichant les étudiants sans notes""" formsemestre_id: int, code: str = None, etudid: int = None
):
"""Affichage et saisie des étudiants sans notes
Si etudid est spécifié, traite un seul étudiant."""
formsemestre: FormSemestre = FormSemestre.query.filter_by( formsemestre: FormSemestre = FormSemestre.query.filter_by(
id=formsemestre_id, dept_id=g.scodoc_dept_id id=formsemestre_id, dept_id=g.scodoc_dept_id
).first_or_404() ).first_or_404()
res: ResultatsSemestre = res_sem.load_formsemestre_results(formsemestre) res: ResultatsSemestre = res_sem.load_formsemestre_results(formsemestre)
etudids_sans_notes = get_formsemestre_etudids_sans_notes(formsemestre, res) etudids_sans_notes = get_formsemestre_etudids_sans_notes(formsemestre, res)
if etudid:
etudids_sans_notes = etudids_sans_notes.intersection({etudid})
etuds: list[Identite] = sorted( etuds: list[Identite] = sorted(
[Identite.query.get(etudid) for etudid in etudids_sans_notes], [Identite.query.get_or_404(eid) for eid in etudids_sans_notes],
key=lambda e: e.sort_key, key=lambda e: e.sort_key,
) )
if request.method == "POST": if request.method == "POST":
@ -1434,6 +1445,18 @@ def formsemestre_note_etuds_sans_notes(formsemestre_id: int, code: str = None):
formsemestre_id=formsemestre.id, formsemestre_id=formsemestre.id,
) )
) )
if not etuds:
if etudid is None:
message = """<h3>aucun étudiant sans notes</h3>"""
else:
flash(
f"""{Identite.query.get_or_404(etudid).nomprenom}
a déjà des notes"""
)
return redirect(
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid)
)
else:
noms = "</li><li>".join( noms = "</li><li>".join(
[ [
f"""<a href="{ f"""<a href="{
@ -1442,6 +1465,13 @@ def formsemestre_note_etuds_sans_notes(formsemestre_id: int, code: str = None):
for etud in etuds for etud in etuds
] ]
) )
message = f"""
<h3>Étudiants sans notes:</h3>
<ul>
<li>{noms}</li>
</ul>
"""
return f""" return f"""
{html_sco_header.sco_header( {html_sco_header.sco_header(
page_title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}" page_title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}"
@ -1451,14 +1481,14 @@ def formsemestre_note_etuds_sans_notes(formsemestre_id: int, code: str = None):
formsemestre_id=formsemestre_id, page_title="Étudiants sans notes" formsemestre_id=formsemestre_id, page_title="Étudiants sans notes"
)} )}
</div> </div>
<h3>Étudiants sans notes:</h3> {message}
<ul>
<li>{noms}</li>
</ul>
<form method="post"> <form method="post">
<input type="hidden" name="formsemestre_id" value="{formsemestre.id}"> <input type="hidden" name="formsemestre_id" value="{formsemestre.id}">
Mettre toutes les notes de ces étudiants à&nbsp;: <input type="hidden" name="etudid" value="{etudid or ""}">
Mettre toutes les notes de {"ces étudiants" if len(etuds)> 1 else "cet étudiant"}
à&nbsp;:
<select name="code"> <select name="code">
<option value="ABS">ABS (absent, compte zéro)</option> <option value="ABS">ABS (absent, compte zéro)</option>
<option value="ATT" selected>ATT (en attente)</option> <option value="ATT" selected>ATT (en attente)</option>

View File

@ -789,7 +789,7 @@ def groups_table(
filename = title filename = title
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE) return scu.send_file(xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
else: else:
raise ValueError("unsupported format") raise ScoValueError("unsupported format")
def tab_absences_html(groups_infos, etat=None): def tab_absences_html(groups_infos, etat=None):

View File

@ -58,7 +58,7 @@ from app.scodoc.sco_formsemestre_validation import formsemestre_recap_parcours_t
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
def _menuScolarite(authuser, sem, etudid): def _menu_scolarite(authuser, sem: dict, etudid: int):
"""HTML pour menu "scolarite" pour un etudiant dans un semestre. """HTML pour menu "scolarite" pour un etudiant dans un semestre.
Le contenu du menu depend des droits de l'utilisateur et de l'état de l'étudiant. Le contenu du menu depend des droits de l'utilisateur et de l'état de l'étudiant.
""" """
@ -139,6 +139,12 @@ def _menuScolarite(authuser, sem, etudid):
"args": args, "args": args,
"enabled": authuser.has_permission(Permission.ScoImplement), "enabled": authuser.has_permission(Permission.ScoImplement),
}, },
{
"title": "Affecter les notes manquantes",
"endpoint": "notes.formsemestre_note_etuds_sans_notes",
"args": args,
"enabled": authuser.has_permission(Permission.ScoEditAllNotes),
},
] ]
return htmlutils.make_menu( return htmlutils.make_menu(
@ -262,7 +268,7 @@ def ficheEtud(etudid=None):
) )
grlink = ", ".join(grlinks) grlink = ", ".join(grlinks)
# infos ajoutées au semestre dans le parcours (groupe, menu) # infos ajoutées au semestre dans le parcours (groupe, menu)
menu = _menuScolarite(authuser, sem, etudid) menu = _menu_scolarite(authuser, sem, etudid)
if menu: if menu:
sem_info[sem["formsemestre_id"]] = ( sem_info[sem["formsemestre_id"]] = (
"<table><tr><td>" + grlink + "</td><td>" + menu + "</td></tr></table>" "<table><tr><td>" + grlink + "</td><td>" + menu + "</td></tr></table>"
@ -423,23 +429,12 @@ def ficheEtud(etudid=None):
else: else:
info["tit_anno"] = "" info["tit_anno"] = ""
# Inscriptions # Inscriptions
# if info["sems"]: # XXX rcl unused ? à voir
# rcl = (
# """(<a href="%(ScoURL)s/Notes/formsemestre_validation_etud_form?check=1&etudid=%(etudid)s&formsemestre_id=%(last_formsemestre_id)s&desturl=ficheEtud?etudid=%(etudid)s">récapitulatif parcours</a>)"""
# % info
# )
# else:
# rcl = ""
info[ info[
"inscriptions_mkup" "inscriptions_mkup"
] = """<div class="ficheinscriptions" id="ficheinscriptions"> ] = f"""<div class="ficheinscriptions" id="ficheinscriptions">
<div class="fichetitre">Parcours</div>%s <div class="fichetitre">Parcours</div>{info["liste_inscriptions"]}
%s %s {info["link_bul_pdf"]} {info["link_inscrire_ailleurs"]}
</div>""" % ( </div>"""
info["liste_inscriptions"],
info["link_bul_pdf"],
info["link_inscrire_ailleurs"],
)
# #
if info["groupes"].strip(): if info["groupes"].strip():

View File

@ -1572,6 +1572,16 @@ div.formsemestre_status {
margin-right: 10px; margin-right: 10px;
} }
.formsemestre_status_warning,
.formsemestre_status_warning a {
color: rgb(215, 90, 0);
}
div.formsemestre_status_warning::before {
content: "\26a0 \fe0f \00a0";
/* EMO_WARNING, "&#9888;&#65039;" */
}
table.formsemestre_status { table.formsemestre_status {
border-collapse: collapse; border-collapse: collapse;
} }

View File

@ -204,7 +204,7 @@ sco_publish(
methods=["GET", "POST"], methods=["GET", "POST"],
) )
sco_publish( sco_publish(
"/formsemestre_view_etuds_sans_note", "/formsemestre_note_etuds_sans_note",
sco_formsemestre_status.formsemestre_note_etuds_sans_notes, sco_formsemestre_status.formsemestre_note_etuds_sans_notes,
Permission.ScoView, Permission.ScoView,
methods=["GET", "POST"], methods=["GET", "POST"],

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "9.3.55" SCOVERSION = "9.3.56"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"