diff --git a/app/models/__init__.py b/app/models/__init__.py index d5b88d12..24261547 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -52,7 +52,7 @@ class ScoDocModel(db.Model): def create_from_dict(cls, data: dict) -> "ScoDocModel": """Create a new instance of the model with attributes given in dict. The instance is added to the session (but not flushed nor committed). - Use only relevant arributes for the given model and ignore others. + Use only relevant attributes for the given model and ignore others. """ if data: args = cls.convert_dict_fields(cls.filter_model_attributes(data)) diff --git a/app/models/etudiants.py b/app/models/etudiants.py index d7eb0312..8502ff5d 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -742,6 +742,7 @@ def check_etud_duplicate_code(args, code_name, edit=True): Raises ScoGenError si problème. """ etudid = args.get("etudid", None) + assert (not edit) or (etudid is not None) # si edit, etudid doit être spécifié if not args.get(code_name, None): return etuds = Identite.query.filter_by( @@ -749,9 +750,7 @@ def check_etud_duplicate_code(args, code_name, edit=True): ).all() duplicate = False if edit: - duplicate = (len(etuds) > 1) or ( - (len(etuds) == 1) and etuds[0].id != args["etudid"] - ) + duplicate = (len(etuds) > 1) or ((len(etuds) == 1) and etuds[0].id != etudid) else: duplicate = len(etuds) > 0 if duplicate: diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py index 9cb168eb..9d2c2b2c 100644 --- a/app/models/moduleimpls.py +++ b/app/models/moduleimpls.py @@ -3,12 +3,13 @@ """ import pandas as pd from flask import abort, g +from flask_login import current_user from flask_sqlalchemy.query import Query from app import db from app.auth.models import User from app.comp import df_cache -from app.models import APO_CODE_STR_LEN +from app.models import APO_CODE_STR_LEN, ScoDocModel from app.models.etudiants import Identite from app.models.evaluations import Evaluation from app.models.modules import Module @@ -17,7 +18,7 @@ from app.scodoc.sco_permissions import Permission from app.scodoc import sco_utils as scu -class ModuleImpl(db.Model): +class ModuleImpl(ScoDocModel): """Mise en oeuvre d'un module pour une annee/semestre""" __tablename__ = "notes_moduleimpl" @@ -52,7 +53,6 @@ class ModuleImpl(db.Model): secondary="notes_modules_enseignants", lazy="dynamic", backref="moduleimpl", - viewonly=True, ) def __repr__(self): @@ -85,7 +85,7 @@ class ModuleImpl(db.Model): @classmethod def get_modimpl(cls, moduleimpl_id: int | str, dept_id: int = None) -> "ModuleImpl": - """FormSemestre ou 404, cherche uniquement dans le département spécifié ou le courant.""" + """ModuleImpl ou 404, cherche uniquement dans le département spécifié ou le courant.""" from app.models.formsemestre import FormSemestre if not isinstance(moduleimpl_id, int): @@ -187,7 +187,7 @@ class ModuleImpl(db.Model): 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_responsable(self, user: User, raise_exc=False) -> bool: """Check if user can modify module resp. If raise_exc, raises exception (AccessDenied or ScoLockedSemError) if not. = Admin, et dir des etud. (si option l'y autorise) @@ -208,6 +208,27 @@ class ModuleImpl(db.Model): raise AccessDenied(f"Modification impossible pour {user}") return False + def can_change_ens(self, user: User | None = None, raise_exc=True) -> bool: + """check if user can modify ens list (raise exception if not)" + if user is None, current user. + """ + user = current_user if user is None else user + if not self.formsemestre.etat: + if raise_exc: + raise ScoLockedSemError("Modification impossible: semestre verrouille") + return False + # -- check access + # admin, resp. module ou resp. semestre + if ( + user.id != self.responsable_id + and not user.has_permission(Permission.EditFormSemestre) + and user.id not in (u.id for u in self.formsemestre.responsables) + ): + if raise_exc: + raise AccessDenied(f"Modification impossible pour {user}") + return False + return True + def est_inscrit(self, etud: Identite) -> bool: """ Vérifie si l'étudiant est bien inscrit au moduleimpl (même si DEM ou DEF au semestre). diff --git a/app/scodoc/html_sidebar.py b/app/scodoc/html_sidebar.py index b64cefc6..af645445 100755 --- a/app/scodoc/html_sidebar.py +++ b/app/scodoc/html_sidebar.py @@ -33,7 +33,7 @@ from flask import g, request from flask_login import current_user from app import db -from app.models import Evaluation, GroupDescr, ModuleImpl, Partition +from app.models import Evaluation, GroupDescr, Identite, ModuleImpl, Partition import app.scodoc.sco_utils as scu from app.scodoc import sco_preferences from app.scodoc.sco_permissions import Permission @@ -160,27 +160,32 @@ def sidebar(etudid: int = None): etudid = request.form.get("etudid", None) if etudid is not None: - etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0] - params.update(etud) - params["fiche_url"] = url_for( - "scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid - ) + etud = Identite.get_etud(etudid) # compte les absences du semestre en cours H.append( - """

- %(civilite_str)s %(nom_disp)s -

- Absences""" - % params + f"""

+ {etud.civilite_str} {etud.nom_disp()} +

+ Absences""" ) - if etud["cursem"]: - cur_sem = etud["cursem"] - nbabs, nbabsjust = sco_assiduites.get_assiduites_count(etudid, cur_sem) + inscription = etud.inscription_courante() + if inscription: + formsemestre = inscription.formsemestre + nbabs, nbabsjust = sco_assiduites.formsemestre_get_assiduites_count( + etudid, formsemestre + ) nbabsnj = nbabs - nbabsjust H.append( - f"""({ - sco_preferences.get_preference("assi_metrique", None)}) + f"""({ + sco_preferences.get_preference("assi_metrique", None)})
{ nbabsjust } J., { nbabsnj } N.J.
""" ) H.append("