Modernise code en-tete evaluation et 'absences ce jour'

This commit is contained in:
Emmanuel Viennet 2023-08-29 19:30:56 +02:00
parent 98f6ba2dd7
commit 4f40fbd028
3 changed files with 87 additions and 74 deletions

View File

@ -118,6 +118,32 @@ class ModuleImpl(db.Model):
return False return False
def can_edit_notes(self, user: "User", allow_ens=True) -> bool:
"""True if authuser can enter or edit notes in this module.
If allow_ens, grant access to all ens in this module
Si des décisions de jury ont déjà été saisies dans ce semestre,
seul le directeur des études peut saisir des notes (et il ne devrait pas).
"""
# was sco_permissions_check.can_edit_notes
from app.scodoc import sco_cursus_dut
if not self.formsemestre.etat:
return False # semestre verrouillé
is_dir_etud = user.id in (u.id for u in self.formsemestre.responsables)
can_edit_all_notes = user.has_permission(Permission.ScoEditAllNotes)
if sco_cursus_dut.formsemestre_has_decisions(self.formsemestre_id):
# il y a des décisions de jury dans ce semestre !
return can_edit_all_notes or is_dir_etud
if (
not can_edit_all_notes
and user.id != self.responsable_id
and not is_dir_etud
):
# enseignant (chargé de TD) ?
return allow_ens and user.id in (ens.id for ens in self.enseignants)
return True
def can_change_ens_by(self, user: User, raise_exc=False) -> bool: def can_change_ens_by(self, user: User, raise_exc=False) -> bool:
"""Check if user can modify module resp. """Check if user can modify module resp.
If raise_exc, raises exception (AccessDenied or ScoLockedSemError) if not. If raise_exc, raises exception (AccessDenied or ScoLockedSemError) if not.

View File

@ -30,16 +30,17 @@
import collections import collections
import datetime import datetime
import operator import operator
import time
from flask import url_for from flask import url_for
from flask import g from flask import g
from flask_login import current_user from flask_login import current_user
from flask import request from flask import request
from app import db
from app.auth.models import User
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre from app.models import Evaluation, FormSemestre
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType from app.scodoc.sco_utils import ModuleType
@ -645,78 +646,64 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True):
"""HTML description of evaluation, for page headers """HTML description of evaluation, for page headers
edit_in_place: allow in-place editing when permitted (not implemented) edit_in_place: allow in-place editing when permitted (not implemented)
""" """
E = sco_evaluation_db.get_evaluation_dict({"evaluation_id": evaluation_id})[0] evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
moduleimpl_id = E["moduleimpl_id"] modimpl = evaluation.moduleimpl
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] responsable: User = db.session.get(User, modimpl.responsable_id)
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0] resp_nomprenom = responsable.get_prenomnom()
formsemestre_id = M["formsemestre_id"] resp_nomcomplet = responsable.get_nomcomplet()
u = sco_users.user_info(M["responsable_id"]) can_edit = modimpl.can_edit_notes(current_user, allow_ens=False)
resp = u["prenomnom"]
nomcomplet = u["nomcomplet"]
can_edit = sco_permissions_check.can_edit_notes(
current_user, moduleimpl_id, allow_ens=False
)
link = ( mod_descr = f"""<a href="{url_for("notes.moduleimpl_status",
'<span class="evallink"><a class="stdlink" href="evaluation_listenotes?moduleimpl_id=%s">voir toutes les notes du module</a></span>' scodoc_dept=g.scodoc_dept,
% moduleimpl_id moduleimpl_id=modimpl.id,
) )}">{modimpl.module.code or ""} {modimpl.module.abbrev or modimpl.module.titre or "?"}</a>
mod_descr = ( <span class="resp">(resp. <a title="{resp_nomcomplet}">{resp_nomprenom}</a>)</span>
'<a href="moduleimpl_status?moduleimpl_id=%s">%s %s</a> <span class="resp">(resp. <a title="%s">%s</a>)</span> %s' <span class="evallink"><a class="stdlink"
% ( href="{url_for(
moduleimpl_id, "notes.evaluation_listenotes",
Mod["code"] or "", scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
Mod["titre"] or "?", }">voir toutes les notes du module</a></span>
nomcomplet, """
resp,
link,
)
)
etit = E["description"] or "" eval_titre = f' "{evaluation.description}"' if evaluation.description else ""
if etit: if modimpl.module.module_type == ModuleType.MALUS:
etit = ' "' + etit + '"' eval_titre += ' <span class="eval_malus">(points de malus)</span>'
if Mod["module_type"] == ModuleType.MALUS:
etit += ' <span class="eval_malus">(points de malus)</span>'
H = [ H = [
'<span class="eval_title">Évaluation%s</span><p><b>Module : %s</b></p>' f"""<span class="eval_title">Évaluation{eval_titre}</span>
% (etit, mod_descr) <p><b>Module : {mod_descr}</b>
</p>"""
] ]
if Mod["module_type"] == ModuleType.MALUS: if modimpl.module.module_type == ModuleType.MALUS:
# Indique l'UE # Indique l'UE
ue = sco_edit_ue.ue_list(args={"ue_id": Mod["ue_id"]})[0] ue = modimpl.module.ue
H.append("<p><b>UE : %(acronyme)s</b></p>" % ue) H.append(f"<p><b>UE : {ue.acronyme}</b></p>")
# store min/max values used by JS client-side checks: # store min/max values used by JS client-side checks:
H.append( H.append(
'<span id="eval_note_min" class="sco-hidden">-20.</span><span id="eval_note_max" class="sco-hidden">20.</span>' """<span id="eval_note_min" class="sco-hidden">-20.</span>
<span id="eval_note_max" class="sco-hidden">20.</span>"""
) )
else: else:
# date et absences (pas pour evals de malus) # date et absences (pas pour evals de malus)
if E["jour"]: if evaluation.date_debut is not None:
jour = E["jour"] H.append(f"<p>Réalisée le <b>{evaluation.descr_date()}</b> ")
H.append("<p>Réalisée le <b>%s</b> " % (jour)) group_id = sco_groups.get_default_group(modimpl.formsemestre_id)
if E["heure_debut"] != E["heure_fin"]:
H.append("de %s à %s " % (E["heure_debut"], E["heure_fin"]))
group_id = sco_groups.get_default_group(formsemestre_id)
H.append( H.append(
f"""<span class="noprint"><a href="{url_for( f"""<span class="noprint"><a class="stdlink" href="{url_for(
'assiduites.get_etat_abs_date', 'assiduites.get_etat_abs_date',
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
group_ids=group_id, group_ids=group_id,
desc=E["description"], desc=evaluation.description or "",
jour=E["jour"], date_debut=evaluation.date_debut.isoformat(),
heure_debut=E["heure_debut"], date_fin=evaluation.date_fin.isoformat(),
heure_fin=E["heure_fin"],
) )
}">(absences ce jour)</a></span>""" }">(absences ce jour)</a></span>"""
) )
else: else:
jour = "<em>pas de date</em>" H.append("<p><em>sans date</em> ")
H.append("<p>Réalisée le <b>%s</b> " % (jour))
H.append( H.append(
'</p><p>Coefficient dans le module: <b>%s</b>, notes sur <span id="eval_note_max">%g</span> ' f"""</p><p>Coefficient dans le module: <b>{evaluation.coefficient or "0"}</b>,
% (E["coefficient"], E["note_max"]) notes sur <span id="eval_note_max">{(evaluation.note_max or 0):g}</span> """
) )
H.append('<span id="eval_note_min" class="sco-hidden">0.</span>') H.append('<span id="eval_note_min" class="sco-hidden">0.</span>')
if can_edit: if can_edit:
@ -730,7 +717,7 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True):
if link_saisie: if link_saisie:
H.append( H.append(
f""" f"""
<a class="stdlink" href="{url_for( <a style="margin-left: 12px;" class="stdlink" href="{url_for(
"notes.saisie_notes", scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id) "notes.saisie_notes", scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)
}">saisie des notes</a> }">saisie des notes</a>
""" """

View File

@ -1,8 +1,8 @@
import datetime import datetime
from flask import g, request, render_template from flask import g, request, render_template
from flask import abort, url_for from flask import abort, url_for
from flask_login import current_user
from app import db from app import db
from app.comp import res_sem from app.comp import res_sem
@ -25,14 +25,16 @@ from app.views import ScoData
# --------------- # ---------------
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import safehtml
from app.scodoc import sco_moduleimpl from app.scodoc import sco_moduleimpl
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_groups_view from app.scodoc import sco_groups_view
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_find_etud from app.scodoc import sco_find_etud
from flask_login import current_user
from app.scodoc import sco_utils as scu
from app.scodoc import sco_assiduites as scass from app.scodoc import sco_assiduites as scass
from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import ScoValueError
from app.tables.visu_assiduites import TableAssi, etuds_sorted_from_ids from app.tables.visu_assiduites import TableAssi, etuds_sorted_from_ids
@ -735,13 +737,19 @@ def visu_assiduites_group():
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
def get_etat_abs_date(): def get_etat_abs_date():
infos_date = { """date_debut, date_fin en ISO"""
"jour": request.args.get("jour"), date_debut_str = request.args.get("date_debut")
"heure_debut": request.args.get("heure_debut"), date_fin_str = request.args.get("date_fin")
"heure_fin": request.args.get("heure_fin"), title = request.args.get("desc")
"title": request.args.get("desc"),
}
group_ids: list[int] = request.args.get("group_ids", None) group_ids: list[int] = request.args.get("group_ids", None)
try:
date_debut = datetime.datetime.fromisoformat(date_debut_str)
except ValueError as exc:
raise ScoValueError("date_debut invalide") from exc
try:
date_fin = datetime.datetime.fromisoformat(date_fin_str)
except ValueError as exc:
raise ScoValueError("date_fin invalide") from exc
if group_ids is None: if group_ids is None:
group_ids = [] group_ids = []
else: else:
@ -754,14 +762,6 @@ def get_etat_abs_date():
sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0] sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
for m in groups_infos.members for m in groups_infos.members
] ]
date_debut = scu.is_iso_formated(
f"{infos_date['jour']}T{infos_date['heure_debut'].replace('h',':')}", True
)
date_fin = scu.is_iso_formated(
f"{infos_date['jour']}T{infos_date['heure_fin'].replace('h',':')}", True
)
assiduites: Assiduite = Assiduite.query.filter( assiduites: Assiduite = Assiduite.query.filter(
Assiduite.etudid.in_([e["etudid"] for e in etuds]) Assiduite.etudid.in_([e["etudid"] for e in etuds])
) )
@ -791,7 +791,7 @@ def get_etat_abs_date():
etudiants = list(sorted(etudiants, key=lambda x: x["nom"])) etudiants = list(sorted(etudiants, key=lambda x: x["nom"]))
header: str = html_sco_header.sco_header( header: str = html_sco_header.sco_header(
page_title=infos_date["title"], page_title=safehtml.html_to_safe_html(title),
init_qtip=True, init_qtip=True,
) )