diff --git a/app/tables/visu_assiduites.py b/app/tables/visu_assiduites.py index 11fa4896..0a4e9cc9 100644 --- a/app/tables/visu_assiduites.py +++ b/app/tables/visu_assiduites.py @@ -8,6 +8,7 @@ import datetime from flask import g, url_for +from flask_login import current_user from app import log from app.models import FormSemestre, Identite, Justificatif from app.tables import table_builder as tb @@ -15,6 +16,7 @@ from app.scodoc import sco_preferences from app.scodoc import sco_utils as scu import app.scodoc.sco_assiduites as scass from app.scodoc.sco_exceptions import ScoValueError +from app.scodoc.sco_permissions import Permission class TableAssi(tb.Table): @@ -171,6 +173,20 @@ class RowAssi(tb.Row): "justificatifs", "Justificatifs", fmt_num(compte_justificatifs.count()) ) + if current_user.has_permission(Permission.AbsChange): + ajout_url: str = url_for( + "assiduites.ajout_assiduite_etud", + scodoc_dept=g.scodoc_dept, + etudid=etud.id, + formsemestre_id=self.table.formsemestre.id, + ) + self.add_cell( + "lien_ajout", + "", + f"signaler assiduité", + no_excel=True, + ) + def _get_etud_stats(self, etud: Identite) -> dict[str, list[str, float, float]]: """ Renvoie le comptage (dans la métrique du département) des différents états diff --git a/app/views/assiduites.py b/app/views/assiduites.py index dda822cb..3ab858f3 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -225,6 +225,18 @@ def ajout_assiduite_etud() -> str | Response: etudid: int = request.args.get("etudid", -1) etud = Identite.get_etud(etudid) + formsemestre_id = request.args.get("formsemestre_id", None) + + # Gestion du semestre + formsemestre: FormSemestre | None = None + sems_etud: list[FormSemestre] = etud.get_formsemestres() + if formsemestre_id: + formsemestre = FormSemestre.get_formsemestre(formsemestre_id) + formsemestre = formsemestre if formsemestre in sems_etud else None + else: + formsemestre = [sem for sem in sems_etud if sem.est_courant()] + formsemestre = formsemestre[0] if formsemestre else None + # Gestion évaluations (appel à la page depuis les évaluations) evaluation_id: int | None = request.args.get("evaluation_id") saisie_eval = evaluation_id is not None @@ -246,26 +258,22 @@ def ajout_assiduite_etud() -> str | Response: modimpls_by_formsemestre = etud.get_modimpls_by_formsemestre(scu.annee_scolaire()) choices: OrderedDict = OrderedDict() choices[""] = [("", "Non spécifié"), ("autre", "Autre module (pas dans la liste)")] - for formsemestre_id in modimpls_by_formsemestre: - formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id) - # indique le nom du semestre dans le menu (optgroup) - group_name: str = formsemestre.titre_annee() - choices[group_name] = [ - (m.id, f"{m.module.code} {m.module.abbrev or m.module.titre or ''}") - for m in modimpls_by_formsemestre[formsemestre_id] - if m.module.ue.type == UE_STANDARD - ] + # indique le nom du semestre dans le menu (optgroup) + group_name: str = formsemestre.titre_annee() + choices[group_name] = [ + (m.id, f"{m.module.code} {m.module.abbrev or m.module.titre or ''}") + for m in modimpls_by_formsemestre[formsemestre.id] + if m.module.ue.type == UE_STANDARD + ] - if formsemestre.est_courant(): - choices.move_to_end(group_name, last=False) choices.move_to_end("", last=False) form.modimpl.choices = choices force_options: dict = None if form.validate_on_submit(): if form.cancel.data: # cancel button return redirect(redirect_url) - ok = _record_assiduite_etud(etud, form) + ok = _record_assiduite_etud(etud, form, formsemestre=formsemestre) if ok: flash("enregistré") return redirect(redirect_url) @@ -293,7 +301,7 @@ def ajout_assiduite_etud() -> str | Response: form=form, moduleimpl_id=moduleimpl_id, redirect_url=redirect_url, - sco=ScoData(etud), + sco=ScoData(etud, formsemestre=formsemestre), tableau=tableau, scu=scu, ) @@ -303,6 +311,7 @@ def _get_dates_from_assi_form( form: AjoutAssiOrJustForm, etud: Identite, from_justif: bool = False, + formsemestre: FormSemestre | None = None, ) -> tuple[ bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None ]: @@ -395,9 +404,11 @@ def _get_dates_from_assi_form( dt_fin_tz_server = dt_fin_tz_server.replace(hour=23, minute=59) # Vérification dates contenu dans un semestre de l'étudiant - dates_semestres: list[tuple[datetime.date, datetime.date]] = [ - (sem.date_debut, sem.date_fin) for sem in etud.get_formsemestres() - ] + dates_semestres: list[tuple[datetime.date, datetime.date]] = ( + [(sem.date_debut, sem.date_fin) for sem in etud.get_formsemestres()] + if formsemestre is None + else [(formsemestre.date_debut, formsemestre.date_fin)] + ) # Vérification date début if not any( @@ -407,7 +418,9 @@ def _get_dates_from_assi_form( ] ): form.set_error( - "La date de début n'appartient à aucun semestre de l'étudiant", + "La date de début n'appartient à aucun semestre de l'étudiant" + if formsemestre is None + else "La date de début n'appartient pas au semestre", form.date_debut, ) @@ -419,7 +432,10 @@ def _get_dates_from_assi_form( ] ): form.set_error( - "La date de fin n'appartient à aucun semestre de l'étudiant", form.date_fin + "La date de fin n'appartient à aucun semestre de l'étudiant" + if not formsemestre + else "La date de fin n'appartient pas au semestre", + form.date_fin, ) dt_entry_date_tz_server = ( @@ -431,6 +447,7 @@ def _get_dates_from_assi_form( def _record_assiduite_etud( etud: Identite, form: AjoutAssiduiteEtudForm, + formsemestre: FormSemestre | None = None, ) -> bool: """Enregistre les données du formulaire de saisie assiduité. Returns ok if successfully recorded, else put error info in the form. @@ -444,7 +461,7 @@ def _record_assiduite_etud( dt_debut_tz_server, dt_fin_tz_server, dt_entry_date_tz_server, - ) = _get_dates_from_assi_form(form, etud) + ) = _get_dates_from_assi_form(form, etud, formsemestre=formsemestre) # Le module (avec "autre") mod_data = form.modimpl.data if mod_data: