Modernise code evaluations/enseignants

This commit is contained in:
Emmanuel Viennet 2024-02-04 23:08:08 +01:00
parent d5fdd5b8b8
commit 57d36927ac
9 changed files with 38 additions and 120 deletions

View File

@ -477,8 +477,8 @@ class User(UserMixin, ScoDocModel):
return f"{nom} {scu.format_prenom(self.prenom)} ({self.user_name})"
@staticmethod
def get_user_id_from_nomplogin(nomplogin: str) -> Optional[int]:
"""Returns id from the string "Dupont Pierre (dupont)"
def get_user_from_nomplogin(nomplogin: str) -> Optional["User"]:
"""Returns User instance from the string "Dupont Pierre (dupont)"
or None if user does not exist
"""
match = re.match(r".*\((.*)\)", nomplogin.strip())
@ -486,7 +486,7 @@ class User(UserMixin, ScoDocModel):
user_name = match.group(1)
u = User.query.filter_by(user_name=user_name).first()
if u:
return u.id
return u
return None
def get_nom_fmt(self):

View File

@ -857,17 +857,20 @@ def do_formsemestre_createwithmodules(edit=False, formsemestre: FormSemestre = N
tf[2]["bul_hide_xml"] = True
# remap les identifiants de responsables:
for field in resp_fields:
tf[2][field] = User.get_user_id_from_nomplogin(tf[2][field])
resp = User.get_user_from_nomplogin(tf[2][field])
tf[2][field] = resp.id if resp else -1
tf[2]["responsables"] = []
for field in resp_fields:
if tf[2][field]:
tf[2]["responsables"].append(tf[2][field])
for module_id in tf[2]["tf-checked"]:
mod_resp_id = User.get_user_id_from_nomplogin(tf[2][module_id])
if mod_resp_id is None:
mod_resp = User.get_user_from_nomplogin(tf[2][module_id])
if mod_resp is None:
# Si un module n'a pas de responsable (ou inconnu),
# l'affecte au 1er directeur des etudes:
mod_resp_id = tf[2]["responsable_id"]
else:
mod_resp_id = mod_resp.id
tf[2][module_id] = mod_resp_id
# etapes:
@ -1227,9 +1230,12 @@ def formsemestre_clone(formsemestre_id):
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
)
else:
resp = User.get_user_from_nomplogin(tf[2]["responsable_id"])
if not resp:
raise ScoValueError("id responsable invalide")
new_formsemestre_id = do_formsemestre_clone(
formsemestre_id,
User.get_user_id_from_nomplogin(tf[2]["responsable_id"]),
resp.id,
tf[2]["date_debut"],
tf[2]["date_fin"],
clone_evaluations=tf[2]["clone_evaluations"],

View File

@ -25,21 +25,18 @@
#
##############################################################################
"""Fonctions sur les moduleimpl
"""Fonctions sur les moduleimpl (legacy: use models.moduleimpls instead)
"""
from flask_login import current_user
import psycopg2
from app import db
from app.models import Formation
from app.scodoc import scolog
from app.scodoc import sco_formsemestre
from app.scodoc import sco_cache
import app.scodoc.notesdb as ndb
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import ScoValueError, AccessDenied
from app.scodoc.sco_exceptions import ScoValueError
# --- Gestion des "Implémentations de Modules"
# Un "moduleimpl" correspond a la mise en oeuvre d'un module
@ -56,15 +53,6 @@ _moduleimplEditor = ndb.EditableTable(
),
)
_modules_enseignantsEditor = ndb.EditableTable(
"notes_modules_enseignants",
None, # pas d'id dans cette Table d'association
(
"moduleimpl_id", # associe moduleimpl
"ens_id", # a l'id de l'enseignant (User.id)
),
)
def do_moduleimpl_create(args):
"create a moduleimpl"
@ -107,9 +95,6 @@ def moduleimpl_list(moduleimpl_id=None, formsemestre_id=None, module_id=None):
args = locals()
cnx = ndb.GetDBConnexion()
modimpls = _moduleimplEditor.list(cnx, args)
# Ajoute la liste des enseignants
for mo in modimpls:
mo["ens"] = do_ens_list(args={"moduleimpl_id": mo["moduleimpl_id"]})
return modimpls
@ -341,23 +326,3 @@ def do_moduleimpl_inscrit_etuds(moduleimpl_id, formsemestre_id, etudids, reset=F
sco_cache.invalidate_formsemestre(
formsemestre_id=formsemestre_id
) # > moduleimpl_inscrit_etuds
def do_ens_list(*args, **kw):
"liste les enseignants d'un moduleimpl (pas le responsable)"
cnx = ndb.GetDBConnexion()
ens = _modules_enseignantsEditor.list(cnx, *args, **kw)
return ens
def do_ens_edit(*args, **kw):
"edit ens"
cnx = ndb.GetDBConnexion()
_modules_enseignantsEditor.edit(cnx, *args, **kw)
def do_ens_create(args):
"create ens"
cnx = ndb.GetDBConnexion()
r = _modules_enseignantsEditor.create(cnx, args)
return r

View File

@ -209,15 +209,10 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
#
sem_locked = not formsemestre.etat
can_edit_evals = (
sco_permissions_check.can_edit_notes(
current_user, moduleimpl_id, allow_ens=formsemestre.ens_can_edit_eval
)
and not sem_locked
)
can_edit_notes = (
sco_permissions_check.can_edit_notes(current_user, moduleimpl_id)
modimpl.can_edit_notes(current_user, allow_ens=formsemestre.ens_can_edit_eval)
and not sem_locked
)
can_edit_notes = modimpl.can_edit_notes(current_user) and not sem_locked
arrow_up, arrow_down, arrow_none = sco_groups.get_arrow_icons_tags()
#
module_resp = db.session.get(User, modimpl.responsable_id)

View File

@ -8,50 +8,11 @@ from flask_login import current_user
from app import db
from app.auth.models import User
from app.models import FormSemestre
import app.scodoc.notesdb as ndb
from app.scodoc.sco_permissions import Permission
from app.scodoc import html_sco_header
from app.scodoc import sco_etud
from app.scodoc import sco_exceptions
from app.scodoc import sco_moduleimpl
def can_edit_notes(authuser, moduleimpl_id, allow_ens=True):
"""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).
"""
from app.scodoc import sco_formsemestre
from app.scodoc import sco_cursus_dut
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
if not sem["etat"]:
return False # semestre verrouillé
if sco_cursus_dut.formsemestre_has_decisions(sem["formsemestre_id"]):
# il y a des décisions de jury dans ce semestre !
return (
authuser.has_permission(Permission.EditAllNotes)
or authuser.id in sem["responsables"]
)
else:
if (
(not authuser.has_permission(Permission.EditAllNotes))
and authuser.id != M["responsable_id"]
and authuser.id not in sem["responsables"]
):
# enseignant (chargé de TD) ?
if allow_ens:
for ens in M["ens"]:
if ens["ens_id"] == authuser.id:
return True
return False
else:
return True
def can_suppress_annotation(annotation_id):

View File

@ -48,6 +48,7 @@ from wtforms import (
HiddenField,
SelectMultipleField,
)
from app.models import ModuleImpl
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app import ScoValueError
@ -58,7 +59,6 @@ from app.scodoc import sco_evaluation_db
from app.scodoc import sco_excel
from app.scodoc.sco_excel import ScoExcelBook, COLORS
from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_groups
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_permissions_check
@ -247,6 +247,8 @@ class PlacementRunner:
# gr_title = sco_groups.listgroups_abbrev(d['groups'])
self.current_user = current_user
self.moduleimpl_id = self.eval_data["moduleimpl_id"]
self.moduleimpl: ModuleImpl = ModuleImpl.query.get_or_404(self.moduleimpl_id)
# TODO: à revoir pour utiliser modèle ModuleImpl
self.moduleimpl_data = sco_moduleimpl.moduleimpl_list(
moduleimpl_id=self.moduleimpl_id
)[0]
@ -280,9 +282,7 @@ class PlacementRunner:
def check_placement(self):
"""Vérifie que l'utilisateur courant a le droit d'édition sur les notes"""
# Check access (admin, respformation, and responsable_id)
return sco_permissions_check.can_edit_notes(
self.current_user, self.moduleimpl_id
)
return self.moduleimpl.can_edit_notes(self.current_user)
def exec_placement(self):
"""Excéute l'action liée au formulaire"""

View File

@ -198,8 +198,8 @@ def do_evaluation_upload_xls():
evaluation_id = int(vals["evaluation_id"])
comment = vals["comment"]
evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
# Check access (admin, respformation, and responsable_id)
if not sco_permissions_check.can_edit_notes(current_user, evaluation.moduleimpl_id):
# Check access (admin, respformation, responsable_id, ens)
if not evaluation.moduleimpl.can_edit_notes(current_user):
raise AccessDenied(f"Modification des notes impossible pour {current_user}")
#
diag, lines = sco_excel.excel_file_to_list(vals["notefile"])
@ -315,7 +315,7 @@ def do_evaluation_set_etud_note(evaluation: Evaluation, etud: Identite, value) -
"""Enregistre la note d'un seul étudiant
value: valeur externe (float ou str)
"""
if not sco_permissions_check.can_edit_notes(current_user, evaluation.moduleimpl.id):
if not evaluation.moduleimpl.can_edit_notes(current_user):
raise AccessDenied(f"Modification des notes impossible pour {current_user}")
# Convert and check value
L, invalids, _, _, _ = _check_notes([(etud.id, value)], evaluation)
@ -336,7 +336,7 @@ def do_evaluation_set_missing(
modimpl = evaluation.moduleimpl
# Check access
# (admin, respformation, and responsable_id)
if not sco_permissions_check.can_edit_notes(current_user, modimpl.id):
if not modimpl.can_edit_notes(current_user):
raise AccessDenied(f"Modification des notes impossible pour {current_user}")
#
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
@ -433,15 +433,11 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
"suppress all notes in this eval"
evaluation = Evaluation.query.get_or_404(evaluation_id)
if sco_permissions_check.can_edit_notes(
current_user, evaluation.moduleimpl_id, allow_ens=False
):
if evaluation.moduleimpl.can_edit_notes(current_user, allow_ens=False):
# On a le droit de modifier toutes les notes
# recupere les etuds ayant une note
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
elif sco_permissions_check.can_edit_notes(
current_user, evaluation.moduleimpl_id, allow_ens=True
):
elif evaluation.moduleimpl.can_edit_notes(current_user, allow_ens=True):
# Enseignant associé au module: ne peut supprimer que les notes qu'il a saisi
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
evaluation_id, by_uid=current_user.id
@ -682,7 +678,7 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
evaluation = Evaluation.query.get_or_404(evaluation_id)
moduleimpl_id = evaluation.moduleimpl.id
formsemestre_id = evaluation.moduleimpl.formsemestre_id
if not sco_permissions_check.can_edit_notes(current_user, moduleimpl_id):
if not evaluation.moduleimpl.can_edit_notes(current_user):
return (
html_sco_header.sco_header()
+ f"""
@ -813,9 +809,7 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
#
H.append("""</div><h3>Autres opérations</h3><ul>""")
if sco_permissions_check.can_edit_notes(
current_user, moduleimpl_id, allow_ens=False
):
if evaluation.moduleimpl.can_edit_notes(current_user, allow_ens=False):
H.append(
f"""
<li>
@ -967,7 +961,7 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
)
# Check access
# (admin, respformation, and responsable_id)
if not sco_permissions_check.can_edit_notes(current_user, evaluation.moduleimpl_id):
if not evaluation.moduleimpl.can_edit_notes(current_user):
return f"""
{html_sco_header.sco_header()}
<h2>Modification des notes impossible pour {current_user.user_name}</h2>
@ -1361,7 +1355,7 @@ def save_notes(
_external=True,
)
# Check access: admin, respformation, or responsable_id
if not sco_permissions_check.can_edit_notes(current_user, evaluation.moduleimpl_id):
if not evaluation.moduleimpl.can_edit_notes(current_user):
return json_error(403, "modification notes non autorisee pour cet utilisateur")
#
valid_notes, _, _, _, _ = _check_notes(notes, evaluation)

View File

@ -1053,24 +1053,22 @@ def edit_enseignants_form(moduleimpl_id):
)
)
else:
ens_id = User.get_user_id_from_nomplogin(tf[2]["ens_id"])
if not ens_id:
ens = User.get_user_from_nomplogin(tf[2]["ens_id"])
if ens is None:
H.append(
'<p class="help">Pour ajouter un enseignant, choisissez un nom dans le menu</p>'
)
else:
# et qu'il n'est pas deja:
if (
ens_id in (x.id for x in modimpl.enseignants)
or ens_id == modimpl.responsable_id
ens.id in (x.id for x in modimpl.enseignants)
or ens.id == modimpl.responsable_id
):
H.append(
f"""<p class="help">Enseignant {ens_id} déjà dans la liste !</p>"""
f"""<p class="help">Enseignant {ens.user_name} déjà dans la liste !</p>"""
)
else:
sco_moduleimpl.do_ens_create(
{"moduleimpl_id": moduleimpl_id, "ens_id": ens_id}
)
modimpl.enseignants.append(ens)
return flask.redirect(
url_for(
"notes.edit_enseignants_form",
@ -1156,7 +1154,7 @@ def edit_moduleimpl_resp(moduleimpl_id: int):
)
)
else:
responsable_id = User.get_user_id_from_nomplogin(tf[2]["responsable_id"])
responsable_id = User.get_user_from_nomplogin(tf[2]["responsable_id"])
if not responsable_id:
# presque impossible: tf verifie les valeurs (mais qui peuvent changer entre temps)
return flask.redirect(

View File

@ -375,7 +375,6 @@ def test_import_formation(test_client, filename="formation-exemple-1.xml"):
formsemestre_id=formsemestre_ids[mod["semestre_id"] - 1],
)
mi = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
assert mi["ens"] == []
assert mi["module_id"] == mod["module_id"]
# --- Export formation en XML