diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py index e84fe82b3..a44a4b5fc 100644 --- a/app/models/moduleimpls.py +++ b/app/models/moduleimpls.py @@ -118,6 +118,32 @@ class ModuleImpl(db.Model): 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: """Check if user can modify module resp. If raise_exc, raises exception (AccessDenied or ScoLockedSemError) if not. diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py index 43959272b..900145c29 100644 --- a/app/scodoc/sco_evaluations.py +++ b/app/scodoc/sco_evaluations.py @@ -30,16 +30,17 @@ import collections import datetime import operator -import time from flask import url_for from flask import g from flask_login import current_user from flask import request +from app import db +from app.auth.models import User from app.comp import res_sem 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 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 edit_in_place: allow in-place editing when permitted (not implemented) """ - E = sco_evaluation_db.get_evaluation_dict({"evaluation_id": evaluation_id})[0] - moduleimpl_id = E["moduleimpl_id"] - M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] - Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0] - formsemestre_id = M["formsemestre_id"] - u = sco_users.user_info(M["responsable_id"]) - resp = u["prenomnom"] - nomcomplet = u["nomcomplet"] - can_edit = sco_permissions_check.can_edit_notes( - current_user, moduleimpl_id, allow_ens=False - ) + evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id) + modimpl = evaluation.moduleimpl + responsable: User = db.session.get(User, modimpl.responsable_id) + resp_nomprenom = responsable.get_prenomnom() + resp_nomcomplet = responsable.get_nomcomplet() + can_edit = modimpl.can_edit_notes(current_user, allow_ens=False) - link = ( - 'voir toutes les notes du module' - % moduleimpl_id - ) - mod_descr = ( - '%s %s (resp. %s) %s' - % ( - moduleimpl_id, - Mod["code"] or "", - Mod["titre"] or "?", - nomcomplet, - resp, - link, - ) - ) + mod_descr = f"""{modimpl.module.code or ""} {modimpl.module.abbrev or modimpl.module.titre or "?"} + (resp. {resp_nomprenom}) + voir toutes les notes du module + """ - etit = E["description"] or "" - if etit: - etit = ' "' + etit + '"' - if Mod["module_type"] == ModuleType.MALUS: - etit += ' (points de malus)' + eval_titre = f' "{evaluation.description}"' if evaluation.description else "" + if modimpl.module.module_type == ModuleType.MALUS: + eval_titre += ' (points de malus)' H = [ - 'Évaluation%s

Module : %s

' - % (etit, mod_descr) + f"""Évaluation{eval_titre} +

Module : {mod_descr} +

""" ] - if Mod["module_type"] == ModuleType.MALUS: + if modimpl.module.module_type == ModuleType.MALUS: # Indique l'UE - ue = sco_edit_ue.ue_list(args={"ue_id": Mod["ue_id"]})[0] - H.append("

UE : %(acronyme)s

" % ue) + ue = modimpl.module.ue + H.append(f"

UE : {ue.acronyme}

") # store min/max values used by JS client-side checks: H.append( - '-20.20.' + """-20. + 20.""" ) else: # date et absences (pas pour evals de malus) - if E["jour"]: - jour = E["jour"] - H.append("

Réalisée le %s " % (jour)) - 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) + if evaluation.date_debut is not None: + H.append(f"

Réalisée le {evaluation.descr_date()} ") + group_id = sco_groups.get_default_group(modimpl.formsemestre_id) H.append( - f"""(absences ce jour)""" ) else: - jour = "pas de date" - H.append("

Réalisée le %s " % (jour)) + H.append("

sans date ") H.append( - '

Coefficient dans le module: %s, notes sur %g ' - % (E["coefficient"], E["note_max"]) + f"""

Coefficient dans le module: {evaluation.coefficient or "0"}, + notes sur {(evaluation.note_max or 0):g} """ ) H.append('0.') if can_edit: @@ -730,7 +717,7 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True): if link_saisie: H.append( f""" - saisie des notes """ diff --git a/app/views/assiduites.py b/app/views/assiduites.py index d4608dc55..a944d2ca0 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -1,8 +1,8 @@ import datetime from flask import g, request, render_template - from flask import abort, url_for +from flask_login import current_user from app import db 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 import html_sco_header +from app.scodoc import safehtml from app.scodoc import sco_moduleimpl from app.scodoc import sco_preferences from app.scodoc import sco_groups_view from app.scodoc import sco_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_utils as scu +from app.scodoc.sco_exceptions import ScoValueError + from app.tables.visu_assiduites import TableAssi, etuds_sorted_from_ids @@ -735,13 +737,19 @@ def visu_assiduites_group(): @scodoc @permission_required(Permission.ScoView) def get_etat_abs_date(): - infos_date = { - "jour": request.args.get("jour"), - "heure_debut": request.args.get("heure_debut"), - "heure_fin": request.args.get("heure_fin"), - "title": request.args.get("desc"), - } + """date_debut, date_fin en ISO""" + date_debut_str = request.args.get("date_debut") + date_fin_str = request.args.get("date_fin") + title = request.args.get("desc") 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: group_ids = [] else: @@ -754,14 +762,6 @@ def get_etat_abs_date(): sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0] 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( 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"])) header: str = html_sco_header.sco_header( - page_title=infos_date["title"], + page_title=safehtml.html_to_safe_html(title), init_qtip=True, )