diff --git a/app/models/assiduites.py b/app/models/assiduites.py index 620b2758d..5d59c07f2 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -5,7 +5,6 @@ from datetime import datetime from flask_login import current_user from flask_sqlalchemy.query import Query -from psycopg2.errors import InvalidTextRepresentation # c'est ok from sqlalchemy.exc import DataError from app import db, log, g, set_sco_dept @@ -256,43 +255,19 @@ class Assiduite(ScoDocModel): def set_moduleimpl(self, moduleimpl_id: int | str): """Mise à jour du moduleimpl_id - Les valeurs du champs "moduleimpl_id" possibles sont : + Les valeurs du champ "moduleimpl_id" possibles sont : - (un id classique) - ("autre" ou "") - - None (pas de moduleimpl_id) + - "" (pas de moduleimpl_id) Si la valeur est "autre" il faut: - mettre à None assiduité.moduleimpl_id - mettre à jour assiduite.external_data["module"] = "autre" - En fonction de la configuration du semestre la valeur `None` peut-être considérée comme invalide. + En fonction de la configuration du semestre (option force_module) la valeur "" peut-être + considérée comme invalide. - Il faudra donc vérifier que ce n'est pas le cas avant de mettre à jour l'assiduité """ moduleimpl: ModuleImpl = None - try: - # ne lève une erreur que si moduleimpl_id est une chaine de caractère non parsable (parseInt) - moduleimpl: ModuleImpl = ModuleImpl.query.get(moduleimpl_id) - # moduleImpl est soit : - # - None si moduleimpl_id==None - # - None si moduleimpl_id== non reconnu - # - ModuleImpl si valide - - # Vérification ModuleImpl not None (raise ScoValueError) - if moduleimpl is None and self._check_force_module(moduleimpl): - # Ici uniquement si on est autorisé à ne pas avoir de module - self.moduleimpl_id = None - return - - # Vérification Inscription ModuleImpl (raise ScoValueError) - if moduleimpl.est_inscrit(self.etudiant): - self.moduleimpl_id = moduleimpl.id - else: - raise ScoValueError("L'étudiant n'est pas inscrit au module") - - except (DataError, InvalidTextRepresentation) as exc: - # On arrive ici si moduleimpl_id == "autre" ou moduleimpl_id == non parsé - - if moduleimpl_id != "autre": - raise ScoValueError("Module non reconnu") from exc - + if moduleimpl_id == "autre": # Configuration de external_data pour Module Autre # Si self.external_data None alors on créé un dictionnaire {"module": "autre"} # Sinon on met à jour external_data["module"] à "autre" @@ -306,6 +281,29 @@ class Assiduite(ScoDocModel): self.moduleimpl_id = None # Ici pas de vérification du force module car on l'a mis dans "external_data" + return + + if moduleimpl_id != "": + try: + moduleimpl_id = int(moduleimpl_id) + except ValueError as exc: + raise ScoValueError("Module non reconnu") from exc + moduleimpl: ModuleImpl = ModuleImpl.query.get(moduleimpl_id) + + # ici moduleimpl est None si non spécifié + + # Vérification ModuleImpl not None (raise ScoValueError) + if moduleimpl is None: + self._check_force_module() + # Ici uniquement si on est autorisé à ne pas avoir de module + self.moduleimpl_id = None + return + + # Vérification Inscription ModuleImpl (raise ScoValueError) + if moduleimpl.est_inscrit(self.etudiant): + self.moduleimpl_id = moduleimpl.id + else: + raise ScoValueError("L'étudiant n'est pas inscrit au module") def supprime(self): "Supprime l'assiduité. Log et commit." @@ -335,7 +333,7 @@ class Assiduite(ScoDocModel): return get_formsemestre_from_data(self.to_dict()) def get_module(self, traduire: bool = False) -> int | str: - "TODO" + "TODO documenter" if self.moduleimpl_id is not None: if traduire: modimpl: ModuleImpl = ModuleImpl.query.get(self.moduleimpl_id) @@ -364,8 +362,12 @@ class Assiduite(ScoDocModel): return f"saisie le {date} {utilisateur}" - def _check_force_module(self, moduleimpl: ModuleImpl) -> bool: - # Vérification si module forcé + def _check_force_module(self): + """Vérification si module forcé: + Si le module est requis, raise ScoValueError + sinon ne fait rien. + """ + # cherche le formsemestre affecté pour utiliser ses préférences formsemestre: FormSemestre = get_formsemestre_from_data( { "etudid": self.etudid, @@ -373,18 +375,15 @@ class Assiduite(ScoDocModel): "date_fin": self.date_fin, } ) - force: bool - - if formsemestre: - force = is_assiduites_module_forced(formsemestre_id=formsemestre.id) - else: - force = is_assiduites_module_forced(dept_id=self.etudiant.dept_id) - + formsemestre_id = formsemestre.id if formsemestre else None + # si pas de formsemestre, utilisera les prefs globales du département + dept_id = self.etudiant.dept_id + force = is_assiduites_module_forced( + formsemestre_id=formsemestre_id, dept_id=dept_id + ) if force: raise ScoValueError("Module non renseigné") - return True - class Justificatif(ScoDocModel): """ diff --git a/app/scodoc/sco_moduleimpl_inscriptions.py b/app/scodoc/sco_moduleimpl_inscriptions.py index c110dacfa..e12ff28dd 100644 --- a/app/scodoc/sco_moduleimpl_inscriptions.py +++ b/app/scodoc/sco_moduleimpl_inscriptions.py @@ -419,7 +419,9 @@ def moduleimpl_inscriptions_stats(formsemestre_id): for info in ues_cap_info[ue["ue_id"]]: etud = sco_etud.get_etud_info(etudid=info["etudid"], filled=True)[0] H.append( - f"""
  • bool: + """Vrai si préférence "imposer la saisie du module" sur les assiduités est vraie.""" from app.scodoc import sco_preferences - retour: bool - - if dept_id is None: - dept_id = g.scodoc_dept_id - - try: - retour = sco_preferences.get_preference( - "forcer_module", formsemestre_id=int(formsemestre_id) - ) - except (TypeError, ValueError): - retour = sco_preferences.get_preference("forcer_module", dept_id=dept_id) - return retour + return sco_preferences.get_preference( + "forcer_module", formsemestre_id=formsemestre_id, dept_id=dept_id + ) def get_assiduites_time_config(config_type: str) -> str | int: diff --git a/app/templates/assiduites/pages/ajout_assiduites.j2 b/app/templates/assiduites/pages/ajout_assiduites.j2 deleted file mode 100644 index 85b7697ad..000000000 --- a/app/templates/assiduites/pages/ajout_assiduites.j2 +++ /dev/null @@ -1,235 +0,0 @@ -{% include "assiduites/widgets/toast.j2" %} -{% include "assiduites/widgets/alert.j2" %} - -{% block pageContent %} -
    -

    Signaler une absence, présence ou retard pour {{etud.html_link_fiche()|safe}}

    - {% if saisie_eval %} -
    - {% endif %} -
    -
    -
    -
    - Date de début - - - Journée entière -
    -
    - Date de fin - -
    -
    - -
    -
    - État de l'assiduité - -
    -
    -
    -
    - Module - {% with moduleid="ajout_assiduite_module_impl",label=false %} - {% include "assiduites/widgets/moduleimpl_dynamic_selector.j2" %} - {% endwith %} -
    -
    - -
    -
    - Raison - -
    -
    - -
    - - -
    - - -
    - -
    -
    - {{tableau | safe }} -
    - -
    - - -{% include "sco_timepicker.j2" %} - -{% endblock pageContent %} diff --git a/app/templates/assiduites/pages/liste_semestre.j2 b/app/templates/assiduites/pages/liste_semestre.j2 deleted file mode 100644 index 90c996da4..000000000 --- a/app/templates/assiduites/pages/liste_semestre.j2 +++ /dev/null @@ -1,94 +0,0 @@ -{% block pageContent %} -
    -

    Assiduites et justificatifs de {{sem}}

    - {% include "assiduites/widgets/tableau_base.j2" %} - -

    Assiduité :

    - - - - - {% include "assiduites/widgets/tableau_assi.j2" %} -

    Justificatifs :

    - - - - - {% include "assiduites/widgets/tableau_justi.j2" %} - -
    - -{% endblock pageContent %} \ No newline at end of file diff --git a/app/templates/assiduites/pages/signal_assiduites_etud.j2 b/app/templates/assiduites/pages/signal_assiduites_etud.j2 deleted file mode 100644 index ea4530952..000000000 --- a/app/templates/assiduites/pages/signal_assiduites_etud.j2 +++ /dev/null @@ -1,160 +0,0 @@ -{# -*- mode: jinja-html -*- #} -{% include "assiduites/widgets/toast.j2" %} -{% include "assiduites/widgets/alert.j2" %} -{% include "assiduites/widgets/prompt.j2" %} -{% include "assiduites/widgets/conflict.j2" %} -
    - {% block content %} -

    Signalement de l'assiduité de {{sco.etud.nomprenom}}

    - -
    - Date: - -
    - - {{timeline|safe}} - - -
    - {% include "assiduites/widgets/moduleimpl_dynamic_selector.j2" %} - -
    - -
    - - - -
    - -
    -
    -
    -
    -
    -
    - - {% if saisie_eval %} -
    -
    -

    - La saisie de l'assiduité a été préconfigurée en fonction de l'évaluation.
    - Une fois la saisie finie, cliquez sur le lien si dessous pour revenir sur la gestion de l'évaluation -

    - retourner sur la page de l'évaluation -
    - {% endif %} - - {{diff | safe}} - -
    -

    Explication de la timeline

    -

    - Si la période indiquée par la timeline provoque un conflit d'assiduité pour un étudiant sa ligne deviendra - rouge. -
    - Dans ce cas il faut résoudre manuellement le conflit : cliquez sur un des boutons d'assiduités pour ouvrir - le - résolveur de conflit. -
    - Correspondance des couleurs : -

    -
      - {% include "assiduites/widgets/legende_couleur.j2" %} -
    - -

    Vous pouvez justifier rapidement une assiduité en saisisant l'assiduité puis en appuyant sur "Justifier"

    - -

    Explication de la saisie différée

    -

    Si la colonne n'est pas valide elle sera affichée en rouge, passez le curseur sur la colonne pour afficher - le message d'erreur

    -

    Sélectionner la date de début de la colonne mettra automatiquement la date de fin à la durée d'une séance - (préférence de département)

    -

    Modifier le module alors que des informations sont déjà enregistrées pour la période changera leur - module.

    -

    Il y a 4 boutons sur la colonne permettant d'enregistrer l'information pour tous les étudiants

    -

    Le dernier des boutons retire l'information présente.

    -

    Vous pouvez ajouter des colonnes en appuyant sur le bouton +

    -

    Vous pouvez supprimer une colonne en appuyant sur la croix qui se situe dans le coin haut droit de la - colonne. -

    -
    - - - -
    -
    -
    - - - - - - - - - {% endblock %} - -
    \ No newline at end of file diff --git a/app/templates/assiduites/widgets/moduleimpl_dynamic_selector.j2 b/app/templates/assiduites/widgets/moduleimpl_dynamic_selector.j2 deleted file mode 100644 index 80712eed9..000000000 --- a/app/templates/assiduites/widgets/moduleimpl_dynamic_selector.j2 +++ /dev/null @@ -1,156 +0,0 @@ -
    - {% if label != false%} - - {% else %} - {% endif %} - {% if moduleid %} - - {% else %} - - {% endif %} - - -
    - - - - - \ No newline at end of file diff --git a/app/templates/assiduites/widgets/simplemoduleimpl_select.j2 b/app/templates/assiduites/widgets/simplemoduleimpl_select.j2 index f41dce597..03c4c2052 100644 --- a/app/templates/assiduites/widgets/simplemoduleimpl_select.j2 +++ b/app/templates/assiduites/widgets/simplemoduleimpl_select.j2 @@ -1,10 +1,7 @@ -{% if scu.is_assiduites_module_forced(request.args.get('formsemestre_id', None))%} - +{% if scu.is_assiduites_module_forced(formsemestre_id)%} + {% else %} - + {% endif %} -{% if moduleimpl_id == "autre" %} - -{% else %} - -{% endif %} \ No newline at end of file + + diff --git a/app/templates/assiduites/widgets/tableau_assi.j2 b/app/templates/assiduites/widgets/tableau_assi.j2 deleted file mode 100644 index c273c6c6e..000000000 --- a/app/templates/assiduites/widgets/tableau_assi.j2 +++ /dev/null @@ -1,465 +0,0 @@ - - - - - - - - - - - - -
    -
    - Début - -
    -
    -
    - Fin - -
    -
    -
    - État - -
    -
    -
    - Module - -
    -
    -
    - Justifiée - -
    -
    -
    -
    - - - - diff --git a/app/views/assiduites.py b/app/views/assiduites.py index 07d8a6919..b44ea0d49 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -2101,15 +2101,19 @@ def _module_selector(formsemestre: FormSemestre, moduleimpl_id: int = None) -> s return render_template( "assiduites/widgets/moduleimpl_selector.j2", - selected=selected, + formsemestre_id=formsemestre.id, modules=modules, moduleimpl_id=moduleimpl_id, + selected=selected, ) def _module_selector_multiple( etud: Identite, moduleimpl_id: int = None, only_form: FormSemestre = None ) -> str: + """menu HTML