diff --git a/app/auth/models.py b/app/auth/models.py index c38590ea..1278d9c0 100644 --- a/app/auth/models.py +++ b/app/auth/models.py @@ -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): diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index 4f4d5993..73c6180f 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -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"], diff --git a/app/scodoc/sco_moduleimpl.py b/app/scodoc/sco_moduleimpl.py index 5a785b8a..9e3f48cb 100644 --- a/app/scodoc/sco_moduleimpl.py +++ b/app/scodoc/sco_moduleimpl.py @@ -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 diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index 698e212a..ca14145d 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -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) diff --git a/app/scodoc/sco_permissions_check.py b/app/scodoc/sco_permissions_check.py index 2d9e39c6..e12e32ce 100644 --- a/app/scodoc/sco_permissions_check.py +++ b/app/scodoc/sco_permissions_check.py @@ -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): diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index db508098..a9e25344 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -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""" diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py index 1cf207d5..b902a88a 100644 --- a/app/scodoc/sco_saisie_notes.py +++ b/app/scodoc/sco_saisie_notes.py @@ -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("""
Pour ajouter un enseignant, choisissez un nom dans le menu
' ) 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"""Enseignant {ens_id} déjà dans la liste !
""" + f"""Enseignant {ens.user_name} déjà dans la liste !
""" ) 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( diff --git a/tests/unit/test_formations.py b/tests/unit/test_formations.py index 4e5a5e69..ee017b53 100644 --- a/tests/unit/test_formations.py +++ b/tests/unit/test_formations.py @@ -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