Compare commits

...

3 Commits

3 changed files with 92 additions and 71 deletions

View File

@ -58,12 +58,13 @@ from app.scodoc.sco_permissions import Permission
import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType
from app.scodoc import codes_cursus
from app.scodoc import html_sco_header
from app.scodoc import htmlutils
from app.scodoc import sco_archives_formsemestre
from app.scodoc import sco_assiduites as scass
from app.scodoc import sco_bulletins
from app.scodoc import codes_cursus
from app.scodoc import sco_cache
from app.scodoc import sco_evaluations
from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre
@ -74,6 +75,7 @@ from app.scodoc import sco_users
from app.scodoc.gen_tables import GenTable
from app.scodoc.html_sidebar import retreive_formsemestre_from_request
from app.scodoc.sco_formsemestre_custommenu import formsemestre_custommenu_html
import sco_version
@ -1066,9 +1068,6 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True):
use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id)
H = [
html_sco_header.sco_header(
page_title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}"
),
'<div class="formsemestre_status">',
formsemestre_status_head(
formsemestre_id=formsemestre_id, page_title="Tableau de bord"
@ -1191,7 +1190,11 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True):
len(adrlist)} enseignants du semestre</a>
</p>"""
)
return "".join(H) + html_sco_header.sco_footer()
return render_template(
"sco_page.j2",
content="".join(H),
title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}",
)
_TABLEAU_MODULES_HEAD = """
@ -1452,7 +1455,10 @@ def formsemestre_note_etuds_sans_notes(
):
"""Affichage et saisie des étudiants sans notes
Si etudid est spécifié, traite un seul étudiant."""
Si etudid est spécifié, traite un seul étudiant.
"""
from app.views import ScoData
formsemestre: FormSemestre = FormSemestre.query.filter_by(
id=formsemestre_id, dept_id=g.scodoc_dept_id
).first_or_404()
@ -1467,8 +1473,9 @@ def formsemestre_note_etuds_sans_notes(
if request.method == "POST":
if not code in ("ATT", "EXC", "ABS"):
raise ScoValueError("code invalide: doit être ATT, ABS ou EXC")
for etud in etuds:
formsemestre.etud_set_all_missing_notes(etud, code)
with sco_cache.DeferredSemCacheManager():
for etud in etuds:
formsemestre.etud_set_all_missing_notes(etud, code)
flash(f"Notes de {len(etuds)} étudiants affectées à {code}")
return redirect(
url_for(
@ -1477,61 +1484,19 @@ def formsemestre_note_etuds_sans_notes(
formsemestre_id=formsemestre.id,
)
)
if not etuds:
if etudid is None:
message = """<h3>aucun étudiant sans notes</h3>"""
else:
flash(
f"""{Identite.get_etud(etudid).nomprenom}
if not etuds and etudid is not None:
flash(
f"""{Identite.get_etud(etudid).nomprenom}
a déjà des notes"""
)
return redirect(
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
)
else:
noms = "</li><li>".join(
[
f"""<a href="{
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
}" class="discretelink">{etud.nomprenom}</a>"""
for etud in etuds
]
)
message = f"""
<h3>Étudiants sans notes:</h3>
<ul>
<li>{noms}</li>
</ul>
"""
return f"""
{html_sco_header.sco_header(
page_title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}"
)}
<div class="formsemestre_status">
{formsemestre_status_head(
formsemestre_id=formsemestre_id, page_title="Étudiants sans notes"
)}
</div>
{message}
<style>
.sco-std-form select, .sco-std-form input[type="submit"] {{
height: 24px;
}}
</style>
<form class="sco-std-form" method="post">
<input type="hidden" name="formsemestre_id" value="{formsemestre.id}">
<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">
<option value="ABS">ABS (absent, compte zéro)</option>
<option value="ATT" selected>ATT (en attente)</option>
<option value="EXC">EXC (neutralisée)</option>
</select>
<input type="submit" value="Enregistrer">
</form>
{html_sco_header.sco_footer()}
"""
return redirect(
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
)
etud = Identite.get_etud(etudid) if etudid is not None else None
return render_template(
"formsemestre/etuds_sans_notes.j2",
etudid=etudid,
etuds=etuds,
sco=ScoData(formsemestre=formsemestre, etud=etud),
title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}",
)

View File

@ -603,14 +603,20 @@ def do_evaluations_upload_xls(
# -- Enregistre les notes de chaque évaluation
with sco_cache.DeferredSemCacheManager():
messages_by_eval, etudids_with_decisions = _record_notes_evaluations(
evaluations, notes_by_eval, comment, diag, rows=rows
messages_by_eval, etudids_with_decisions, modimpl_ids_changed = (
_record_notes_evaluations(
evaluations, notes_by_eval, comment, diag, rows=rows
)
)
# -- News
if len(evaluations) > 1:
modules_str = ", ".join(
[evaluation.moduleimpl.module.code for evaluation in evaluations]
{
evaluation.moduleimpl.module.code
for evaluation in evaluations
if evaluation.moduleimpl_id in modimpl_ids_changed
}
)
status_url = (
url_for(
@ -647,7 +653,7 @@ def do_evaluations_upload_xls(
obj=obj_id,
text=f"""Chargement notes dans <a href="{status_url}">{modules_str}</a>""",
url=status_url,
max_frequency=30 * 60, # 30 minutes
max_frequency=10 * 60, # 10 minutes
)
msg = "<div>" + "\n".join(messages_by_eval.values()) + "</div>"
@ -709,9 +715,12 @@ def _read_notes_from_rows(
def _record_notes_evaluations(
evaluations, notes_by_eval, comment, diag, rows: list[list[str]] | None = None
) -> tuple[dict[int, str], set[int]]:
) -> tuple[dict[int, str], set[int], set[int]]:
"""Enregistre les notes dans les évaluations
Return: messages_by_eval, etudids_with_decisions
Return:
messages_by_eval : dict { evaluation_id : message }
etudids_with_decisions : set of etudids with decision and mark changed
modimpl_ids_changed : set of ModuleImplId where at least one mark changed
"""
# -- Check values de chaque évaluation
valid_notes_by_eval, etudids_without_notes_by_eval, etudids_absents_by_eval = (
@ -720,6 +729,7 @@ def _record_notes_evaluations(
messages_by_eval: dict[int, str] = {}
etudids_with_decisions = set()
modimpl_ids_changed = set()
for evaluation in evaluations:
valid_notes = valid_notes_by_eval.get(evaluation.id)
if not valid_notes:
@ -730,6 +740,8 @@ def _record_notes_evaluations(
)
)
etudids_with_decisions |= set(etudids_with_decisions_eval)
if etudids_changed:
modimpl_ids_changed.add(evaluation.moduleimpl_id)
msg = f"""<div class="diag-evaluation">
<ul>
<li><div class="{'diag-change' if etudids_changed else 'diag-nochange'}">
@ -761,7 +773,7 @@ def _record_notes_evaluations(
</div>"""
msg += """</div>"""
messages_by_eval[evaluation.id] = msg
return messages_by_eval, etudids_with_decisions
return messages_by_eval, etudids_with_decisions, modimpl_ids_changed
def _check_notes_evaluations(

View File

@ -0,0 +1,44 @@
{% extends "sco_page.j2" %}
{% block styles %}
{{super()}}
<style>
.sco-std-form select, .sco-std-form input[type="submit"] {
height: 24px;
}
</style>
{% endblock %}
{% block app_content %}
{% if not etuds %}
<h3>aucun étudiant sans notes</h3>
{% else %}
<h3>Étudiants sans notes:</h3>
<ul>
{% for etud in etuds %}
<li>
<a href="{{
url_for('scolar.fiche_etud', scodoc_dept=g.scodoc_dept, etudid=etud.id)
}}" class="discretelink">{{etud.nom_prenom()}}</a>
</li>
{% endfor %}
</ul>
<form class="sco-std-form" method="post">
<input type="hidden" name="formsemestre_id" value="{{sco.formsemestre.id}}">
<input type="hidden" name="etudid" value="{{etudid or ''}}">
Mettre toutes les notes de
{{"ces étudiants" if etuds|length > 1 else "cet étudiant"}}
à&nbsp;:
<select name="code">
<option value="ABS">ABS (absent, compte zéro)</option>
<option value="ATT" selected>ATT (en attente)</option>
<option value="EXC">EXC (neutralisée)</option>
</select>
<input type="submit" value="Enregistrer">
</form>
{% endif %}
{% endblock %}