diff --git a/app/api/assiduites.py b/app/api/assiduites.py index cc55f092..d3f216c0 100644 --- a/app/api/assiduites.py +++ b/app/api/assiduites.py @@ -14,6 +14,7 @@ from flask_login import current_user, login_required from app import db, log import app.scodoc.sco_assiduites as scass import app.scodoc.sco_utils as scu +from app.scodoc import sco_preferences from app.api import api_bp as bp from app.api import api_web_bp, get_model_api_object, tools from app.decorators import permission_required, scodoc @@ -25,6 +26,7 @@ from app.models import ( Scolog, Justificatif, ) +from flask_sqlalchemy.query import Query from app.models.assiduites import get_assiduites_justif from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_permissions import Permission @@ -256,7 +258,7 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False) 404, message="étudiant inconnu", ) - assiduites_query = etud.assiduites + assiduites_query: Query = etud.assiduites if with_query: assiduites_query = _filter_manager(request, assiduites_query) @@ -961,7 +963,7 @@ def _count_manager(requested) -> tuple[str, dict]: return (metric, filtered) -def _filter_manager(requested, assiduites_query: Assiduite): +def _filter_manager(requested, assiduites_query: Query) -> Query: """ Retourne les assiduites entrées filtrées en fonction de la request """ @@ -979,7 +981,7 @@ def _filter_manager(requested, assiduites_query: Assiduite): fin = scu.is_iso_formated(fin, True) if (deb, fin) != (None, None): - assiduites_query: Assiduite = scass.filter_by_date( + assiduites_query: Query = scass.filter_by_date( assiduites_query, Assiduite, deb, fin ) @@ -1017,11 +1019,11 @@ def _filter_manager(requested, assiduites_query: Assiduite): falses: tuple[str] = ("f", "faux", "false") if est_just.lower() in trues: - assiduites_query: Assiduite = scass.filter_assiduites_by_est_just( + assiduites_query: Query = scass.filter_assiduites_by_est_just( assiduites_query, True ) elif est_just.lower() in falses: - assiduites_query: Assiduite = scass.filter_assiduites_by_est_just( + assiduites_query: Query = scass.filter_assiduites_by_est_just( assiduites_query, False ) @@ -1029,7 +1031,7 @@ def _filter_manager(requested, assiduites_query: Assiduite): user_id = requested.args.get("user_id", False) if user_id is not False: - assiduites_query: Assiduite = scass.filter_by_user_id(assiduites_query, user_id) + assiduites_query: Query = scass.filter_by_user_id(assiduites_query, user_id) return assiduites_query diff --git a/app/api/justificatifs.py b/app/api/justificatifs.py index 30357d81..0fd59b97 100644 --- a/app/api/justificatifs.py +++ b/app/api/justificatifs.py @@ -26,6 +26,7 @@ from app.scodoc.sco_archives_justificatifs import JustificatifArchiver from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_permissions import Permission from app.scodoc.sco_utils import json_error +from flask_sqlalchemy.query import Query # Partie Modèle @@ -261,7 +262,7 @@ def _create_singular( # TOUT EST OK try: - nouv_justificatif: Justificatif = Justificatif.create_justificatif( + nouv_justificatif: Query = Justificatif.create_justificatif( date_debut=deb, date_fin=fin, etat=etat, @@ -307,7 +308,7 @@ def justif_edit(justif_id: int): "date_fin"?: str } """ - justificatif_unique: Justificatif = Justificatif.query.filter_by( + justificatif_unique: Query = Justificatif.query.filter_by( id=justif_id ).first_or_404() @@ -426,9 +427,7 @@ def justif_delete(): def _delete_singular(justif_id: int, database): - justificatif_unique: Justificatif = Justificatif.query.filter_by( - id=justif_id - ).first() + justificatif_unique: Query = Justificatif.query.filter_by(id=justif_id).first() if justificatif_unique is None: return (404, "Justificatif non existant") @@ -470,7 +469,7 @@ def justif_import(justif_id: int = None): if file.filename == "": return json_error(404, "Il n'y a pas de fichier joint") - query = Justificatif.query.filter_by(id=justif_id) + query: Query = Justificatif.query.filter_by(id=justif_id) if g.scodoc_dept: query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id) @@ -509,11 +508,11 @@ def justif_export(justif_id: int = None, filename: str = None): Retourne un fichier d'une archive d'un justificatif """ - query = Justificatif.query.filter_by(id=justif_id) + query: Query = Justificatif.query.filter_by(id=justif_id) if g.scodoc_dept: query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id) - justificatif_unique: Justificatif = query.first_or_404() + justificatif_unique: Justificaitf = query.first_or_404() archive_name: str = justificatif_unique.fichier if archive_name is None: @@ -551,7 +550,7 @@ def justif_remove(justif_id: int = None): data: dict = request.get_json(force=True) - query = Justificatif.query.filter_by(id=justif_id) + query: Query = Justificatif.query.filter_by(id=justif_id) if g.scodoc_dept: query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id) @@ -604,7 +603,7 @@ def justif_list(justif_id: int = None): Liste les fichiers du justificatif """ - query = Justificatif.query.filter_by(id=justif_id) + query: Query = Justificatif.query.filter_by(id=justif_id) if g.scodoc_dept: query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id) @@ -642,7 +641,7 @@ def justif_justifies(justif_id: int = None): Liste assiduite_id justifiées par le justificatif """ - query = Justificatif.query.filter_by(id=justif_id) + query: Query = Justificatif.query.filter_by(id=justif_id) if g.scodoc_dept: query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id) @@ -676,13 +675,13 @@ def _filter_manager(requested, justificatifs_query): fin = scu.is_iso_formated(fin, True) if (deb, fin) != (None, None): - justificatifs_query: Justificatif = scass.filter_by_date( + justificatifs_query: Query = scass.filter_by_date( justificatifs_query, Justificatif, deb, fin ) user_id = requested.args.get("user_id", False) if user_id is not False: - justificatifs_query: Justificatif = scass.filter_by_user_id( + justificatifs_query: Query = scass.filter_by_user_id( justificatifs_query, user_id ) diff --git a/app/models/assiduites.py b/app/models/assiduites.py index 0cea4781..7f5520df 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -14,6 +14,8 @@ from app.scodoc.sco_utils import ( localize_datetime, ) +from flask_sqlalchemy.query import Query + class Assiduite(db.Model): """ @@ -124,7 +126,7 @@ class Assiduite(db.Model): ) -> object or int: """Créer une nouvelle assiduité pour l'étudiant""" # Vérification de non duplication des périodes - assiduites: list[Assiduite] = etud.assiduites + assiduites: Query = etud.assiduites if is_period_conflicting(date_debut, date_fin, assiduites, Assiduite): raise ScoValueError( "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)" @@ -307,7 +309,7 @@ class Justificatif(db.Model): def is_period_conflicting( date_debut: datetime, date_fin: datetime, - collection: list[Assiduite or Justificatif], + collection: Query, collection_cls: Assiduite or Justificatif, ) -> bool: """ diff --git a/app/scodoc/sco_assiduites.py b/app/scodoc/sco_assiduites.py index c78d1b8f..98e9af5f 100644 --- a/app/scodoc/sco_assiduites.py +++ b/app/scodoc/sco_assiduites.py @@ -13,6 +13,7 @@ from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_preferences from app.scodoc import sco_cache from app.scodoc import sco_etud +from flask_sqlalchemy.query import Query class CountCalculator: @@ -167,7 +168,7 @@ class CountCalculator: self.hours += delta.total_seconds() / 3600 - def to_dict(self) -> dict[str, object]: + def to_dict(self) -> dict[str, int or float]: """Retourne les métriques sous la forme d'un dictionnaire""" return { "compte": self.count, @@ -178,8 +179,8 @@ class CountCalculator: def get_assiduites_stats( - assiduites: Assiduite, metric: str = "all", filtered: dict[str, object] = None -) -> Assiduite: + assiduites: Query, metric: str = "all", filtered: dict[str, object] = None +) -> dict[str, int or float]: """Compte les assiduités en fonction des filtres""" if filtered is not None: @@ -218,7 +219,7 @@ def get_assiduites_stats( return output if output else count -def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite: +def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Query: """ Filtrage d'une collection d'assiduites en fonction de leur état """ @@ -227,9 +228,7 @@ def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite: return assiduites.filter(Assiduite.etat.in_(etats)) -def filter_assiduites_by_est_just( - assiduites: Assiduite, est_just: bool -) -> Justificatif: +def filter_assiduites_by_est_just(assiduites: Assiduite, est_just: bool) -> Query: """ Filtrage d'une collection d'assiduites en fonction de s'ils sont justifiés """ @@ -239,7 +238,7 @@ def filter_assiduites_by_est_just( def filter_by_user_id( collection: Assiduite or Justificatif, user_id: int, -) -> Justificatif: +) -> Query: """ Filtrage d'une collection en fonction de l'user_id """ @@ -252,7 +251,7 @@ def filter_by_date( date_deb: datetime = None, date_fin: datetime = None, strict: bool = False, -): +) -> Query: """ Filtrage d'une collection d'assiduites en fonction d'une date """ @@ -272,9 +271,7 @@ def filter_by_date( ) -def filter_justificatifs_by_etat( - justificatifs: Justificatif, etat: str -) -> Justificatif: +def filter_justificatifs_by_etat(justificatifs: Justificatif, etat: str) -> Query: """ Filtrage d'une collection de justificatifs en fonction de leur état """ @@ -283,9 +280,7 @@ def filter_justificatifs_by_etat( return justificatifs.filter(Justificatif.etat.in_(etats)) -def filter_by_module_impl( - assiduites: Assiduite, module_impl_id: int or None -) -> Assiduite: +def filter_by_module_impl(assiduites: Assiduite, module_impl_id: int or None) -> Query: """ Filtrage d'une collection d'assiduites en fonction de l'ID du module_impl """ @@ -296,7 +291,7 @@ def filter_by_formsemestre( collection_query: Assiduite or Justificatif, collection_class: Assiduite or Justificatif, formsemestre: FormSemestre, -): +) -> Query: """ Filtrage d'une collection en fonction d'un formsemestre """ @@ -323,7 +318,7 @@ def filter_by_formsemestre( return collection_result.filter(collection_class.date_fin <= form_date_fin) -def justifies(justi: Justificatif, obj: bool = False) -> list[int]: +def justifies(justi: Justificatif, obj: bool = False) -> list[int] or Query: """ Retourne la liste des assiduite_id qui sont justifié par la justification Une assiduité est justifiée si elle est COMPLETEMENT ou PARTIELLEMENT comprise dans la plage du justificatif @@ -347,7 +342,7 @@ def justifies(justi: Justificatif, obj: bool = False) -> list[int]: def get_all_justified( etudid: int, date_deb: datetime = None, date_fin: datetime = None -) -> list[Assiduite]: +) -> Query: """Retourne toutes les assiduités justifiées sur une période""" if date_deb is None: @@ -432,7 +427,7 @@ def invalidate_assiduites_count(etudid, sem): """Invalidate (clear) cached counts""" date_debut = sem["date_debut_iso"] date_fin = sem["date_fin_iso"] - for met in ["demi", "journee", "compte", "heure"]: + for met in sco_preferences.ASSIDUITES_METRIC_LABEL.values(): key = str(etudid) + "_" + date_debut + "_" + date_fin + f"{met}_assiduites" sco_cache.AbsSemEtudCache.delete(key) diff --git a/app/scodoc/sco_preferences.py b/app/scodoc/sco_preferences.py index e4b322c6..c97c4c48 100644 --- a/app/scodoc/sco_preferences.py +++ b/app/scodoc/sco_preferences.py @@ -200,7 +200,7 @@ _INSTALLED_FONTS = ", ".join(sco_pdf.get_available_font_names()) ASSIDUITES_METRIC_LABEL = { # l'ordre est important, c'est celui-du menu. Le defaut en 1er donc. - "1/2 J.": "demi-journée", + "1/2 J.": "demi", "J.": "journee", "H.": "heure", } @@ -636,6 +636,7 @@ class BasePreferences(object): "type": "float", "category": "assi", "only_global": True, + "explanation": "Durée d'un créneau en heure. Utilisé dans les pages de saisie", }, ), ( @@ -665,7 +666,7 @@ class BasePreferences(object): { "initvalue": "1/2 J.", "input_type": "menu", - "labels": list(ASSIDUITES_METRIC_LABEL.values()), + "labels": list(ASSIDUITES_METRIC_LABEL.keys()), "allowed_values": list(ASSIDUITES_METRIC_LABEL.keys()), "title": "Métrique de l'assiduité", "explanation": "Unité utilisée dans la fiche étudiante, les bilans et les calculs", diff --git a/app/views/assiduites.py b/app/views/assiduites.py index 7855b3a0..4d26a8ef 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -327,11 +327,9 @@ def bilan_etud(): date_debut: str = f"{scu.annee_scolaire()}-09-01" date_fin: str = f"{scu.annee_scolaire()+1}-06-30" - assi_metric = { - "H.": "heure", - "J.": "journee", - "1/2 J.": "demi", - }.get(sco_preferences.get_preference("assi_metrique", dept_id=g.scodoc_dept_id)) + assi_metric = sco_preferences.ASSIDUITES_METRIC_LABEL.get( + sco_preferences.get_preference("assi_metrique", dept_id=g.scodoc_dept_id) + ) return HTMLBuilder( header,