diff --git a/app/api/assiduites.py b/app/api/assiduites.py index d3f216c04..ec47f518a 100644 --- a/app/api/assiduites.py +++ b/app/api/assiduites.py @@ -587,16 +587,6 @@ def _create_singular( if fin is None: errors.append("param 'date_fin': format invalide") - # cas 4 : moduleimpl_id - - moduleimpl_id = data.get("moduleimpl_id", False) - moduleimpl: ModuleImpl = None - - if moduleimpl_id not in [False, None]: - moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first() - if moduleimpl is None: - errors.append("param 'moduleimpl_id': invalide") - # cas 5 : desc desc: str = data.get("desc", None) @@ -606,6 +596,21 @@ def _create_singular( if not isinstance(external_data, dict): errors.append("param 'external_data' : n'est pas un objet JSON") + # cas 4 : moduleimpl_id + + moduleimpl_id = data.get("moduleimpl_id", False) + moduleimpl: ModuleImpl = None + + if moduleimpl_id not in [False, None]: + if moduleimpl_id != "autre": + moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first() + if moduleimpl is None: + errors.append("param 'moduleimpl_id': invalide") + else: + moduleimpl_id = None + external_data = external_data if external_data is not None else {} + external_data["module"] = "Autre" + if errors: err: str = ", ".join(errors) return (404, err) @@ -709,58 +714,10 @@ def assiduite_edit(assiduite_id: int): errors: list[str] = [] data = request.get_json(force=True) - # Vérifications de data + code, obj = _edit_singular(assiduite_unique, data) - # Cas 1 : Etat - if data.get("etat") is not None: - etat = scu.EtatAssiduite.get(data.get("etat")) - if etat is None: - errors.append("param 'etat': invalide") - else: - assiduite_unique.etat = etat - - # Cas 2 : Moduleimpl_id - moduleimpl_id = data.get("moduleimpl_id", False) - moduleimpl: ModuleImpl = None - - if moduleimpl_id is not False: - if moduleimpl_id is not None and moduleimpl_id != "": - moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first() - if moduleimpl is None: - errors.append("param 'moduleimpl_id': invalide") - else: - if not moduleimpl.est_inscrit( - Identite.query.filter_by(id=assiduite_unique.etudid).first() - ): - errors.append("param 'moduleimpl_id': etud non inscrit") - else: - assiduite_unique.moduleimpl_id = moduleimpl_id - else: - assiduite_unique.moduleimpl_id = None - - # Cas 3 : desc - desc = data.get("desc", False) - if desc is not False: - assiduite_unique.description = desc - - # Cas 4 : est_just - est_just = data.get("est_just") - if est_just is not None: - if not isinstance(est_just, bool): - errors.append("param 'est_just' : booléen non reconnu") - else: - assiduite_unique.est_just = est_just - - external_data = data.get("external_data") - if external_data is not None: - if not isinstance(external_data, dict): - errors.append("param 'external_data' : n'est pas un objet JSON") - else: - assiduite_unique.external_data = external_data - - if errors: - err: str = ", ".join(errors) - return json_error(404, err) + if code == 404: + return json_error(404, obj) log(f"assiduite_edit: {assiduite_unique.etudiant.id} {assiduite_unique}") Scolog.logdb( @@ -841,22 +798,41 @@ def _edit_singular(assiduite_unique, data): else: assiduite_unique.etat = etat + external_data = data.get("external_data") + if external_data is not None: + if not isinstance(external_data, dict): + errors.append("param 'external_data' : n'est pas un objet JSON") + else: + assiduite_unique.external_data = external_data + # Cas 2 : Moduleimpl_id moduleimpl_id = data.get("moduleimpl_id", False) moduleimpl: ModuleImpl = None if moduleimpl_id is not False: if moduleimpl_id is not None: - moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first() - if moduleimpl is None: - errors.append("param 'moduleimpl_id': invalide") + if moduleimpl_id == "autre": + assiduite_unique.moduleimpl_id = None + external_data = ( + external_data + if external_data is not None and isinstance(external_data, dict) + else assiduite_unique.external_data + ) + external_data = external_data if external_data is not None else {} + external_data["module"] = "Autre" + assiduite_unique.external_data = external_data + else: - if not moduleimpl.est_inscrit( - Identite.query.filter_by(id=assiduite_unique.etudid).first() - ): - errors.append("param 'moduleimpl_id': etud non inscrit") + moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first() + if moduleimpl is None: + errors.append("param 'moduleimpl_id': invalide") else: - assiduite_unique.moduleimpl_id = moduleimpl_id + if not moduleimpl.est_inscrit( + Identite.query.filter_by(id=assiduite_unique.etudid).first() + ): + errors.append("param 'moduleimpl_id': etud non inscrit") + else: + assiduite_unique.moduleimpl_id = moduleimpl_id else: assiduite_unique.moduleimpl_id = moduleimpl_id @@ -946,8 +922,8 @@ def _count_manager(requested) -> tuple[str, dict]: est_just: str = requested.args.get("est_just") if est_just is not None: - trues: tuple[str] = ("v", "t", "vrai", "true") - falses: tuple[str] = ("f", "faux", "false") + trues: tuple[str] = ("v", "t", "vrai", "true", "1") + falses: tuple[str] = ("f", "faux", "false", "0") if est_just.lower() in trues: filtered["est_just"] = True @@ -960,6 +936,12 @@ def _count_manager(requested) -> tuple[str, dict]: if user_id is not False: filtered["user_id"] = user_id + # cas 9 : split + + split = requested.args.get("split", False) + if split is not False: + filtered["split"] = True + return (metric, filtered) @@ -1015,8 +997,8 @@ def _filter_manager(requested, assiduites_query: Query) -> Query: est_just: str = requested.args.get("est_just") if est_just is not None: - trues: tuple[str] = ("v", "t", "vrai", "true") - falses: tuple[str] = ("f", "faux", "false") + trues: tuple[str] = ("v", "t", "vrai", "true", "1") + falses: tuple[str] = ("f", "faux", "false", "0") if est_just.lower() in trues: assiduites_query: Query = scass.filter_assiduites_by_est_just( diff --git a/app/scodoc/sco_assiduites.py b/app/scodoc/sco_assiduites.py index bd683033f..2a478843b 100644 --- a/app/scodoc/sco_assiduites.py +++ b/app/scodoc/sco_assiduites.py @@ -152,7 +152,6 @@ class CountCalculator: delta: timedelta = assi.date_fin - assi.date_debut if delta.days > 0: - # raise Exception(self.hours) self.compute_long_assiduite(assi) continue @@ -186,37 +185,78 @@ def get_assiduites_stats( if filtered is not None: deb, fin = None, None for key in filtered: - if key == "etat": - assiduites = filter_assiduites_by_etat(assiduites, filtered[key]) - elif key == "date_fin": - fin = filtered[key] - elif key == "date_debut": - deb = filtered[key] - elif key == "moduleimpl_id": - assiduites = filter_by_module_impl(assiduites, filtered[key]) - elif key == "formsemestre": - assiduites = filter_by_formsemestre( - assiduites, Assiduite, filtered[key] - ) - elif key == "est_just": - assiduites = filter_assiduites_by_est_just(assiduites, filtered[key]) - elif key == "user_id": - assiduites = filter_by_user_id(assiduites, filtered[key]) + match key: + case "etat": + assiduites = filter_assiduites_by_etat(assiduites, filtered[key]) + case "date_fin": + fin = filtered[key] + case "date_debut": + deb = filtered[key] + case "moduleimpl_id": + assiduites = filter_by_module_impl(assiduites, filtered[key]) + case "formsemestre": + assiduites = filter_by_formsemestre( + assiduites, Assiduite, filtered[key] + ) + case "est_just": + assiduites = filter_assiduites_by_est_just( + assiduites, filtered[key] + ) + case "user_id": + assiduites = filter_by_user_id(assiduites, filtered[key]) + if (deb, fin) != (None, None): assiduites = filter_by_date(assiduites, Assiduite, deb, fin) - calculator: CountCalculator = CountCalculator() - calculator.compute_assiduites(assiduites) - count: dict = calculator.to_dict() - metrics: list[str] = metric.split(",") - output: dict = {} + calculator: CountCalculator = CountCalculator() - for key, val in count.items(): + if "split" not in filtered: + calculator.compute_assiduites(assiduites) + count: dict = calculator.to_dict() + + for key, val in count.items(): + if key in metrics: + output[key] = val + return output if output else count + + etats: list[str] = ( + filtered["etat"].split(",") + if "etat" in filtered + else ["absent", "present", "retard"] + ) + + for etat in etats: + output[etat] = _count_assiduites_etat(etat, assiduites, calculator, metrics) + if "est_just" not in filtered: + output[etat]["justifie"] = _count_assiduites_etat( + etat, assiduites, calculator, metrics, justifie=True + ) + + return output + + +def _count_assiduites_etat( + etat: str, + assiduites: Query, + calculator: CountCalculator, + metrics: list[str], + justifie: bool = False, +): + calculator.reset() + etat_num: int = scu.EtatAssiduite.get(etat, -1) + assiduites_etat: Query = assiduites.filter(Assiduite.etat == etat_num) + if justifie: + assiduites_etat = assiduites_etat.filter(Assiduite.est_just == True) + + calculator.compute_assiduites(assiduites_etat) + count_etat: dict = calculator.to_dict() + output_etat: dict = {} + for key, val in count_etat.items(): if key in metrics: - output[key] = val - return output if output else count + output_etat[key] = val + return output_etat if output_etat else count_etat def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Query: @@ -232,7 +272,7 @@ def filter_assiduites_by_est_just(assiduites: Assiduite, est_just: bool) -> Quer """ Filtrage d'une collection d'assiduites en fonction de s'ils sont justifiés """ - return assiduites.filter_by(est_just=est_just) + return assiduites.filter(Assiduite.est_just == est_just) def filter_by_user_id( diff --git a/app/scodoc/sco_bulletins_legacy.py b/app/scodoc/sco_bulletins_legacy.py index 95e3846af..5ba649f9a 100644 --- a/app/scodoc/sco_bulletins_legacy.py +++ b/app/scodoc/sco_bulletins_legacy.py @@ -314,16 +314,13 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator): authuser = self.authuser H = [] # --- Absences - # XXX TODO-ASSIDUITE - # au passage, utiliser url_for... H.append( - """
- XXX
- Absences : %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
+ f"""
+
+ Absences :{I['nbabs']} demi-journées, dont {I['nbabsjust']} justifiées
(pendant ce semestre).
-
- XXX
- Absences : %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
+ f"""
"""
- % self.infos
)
story.append(
Paragraph(
diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py
index a11ee2289..286bcf113 100755
--- a/app/scodoc/sco_formsemestre_status.py
+++ b/app/scodoc/sco_formsemestre_status.py
@@ -881,14 +881,13 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
if n_members == 0:
continue # skip empty groups
partition_is_empty = False
- # XXX TODO-ASSIDUITE
- group["url_etat"] = "non disponible" # url_for(
- # "absences.EtatAbsencesGr",
- # group_ids=group["group_id"],
- # debut=formsemestre.date_debut.strftime("%d/%m/%Y"),
- # fin=formsemestre.date_fin.strftime("%d/%m/%Y"),
- # scodoc_dept=g.scodoc_dept,
- # )
+ group["url_etat"] = url_for(
+ "assiduites.visu_assi_group",
+ scodoc_dept=g.scodoc_dept,
+ group_ids=group["id"],
+ date_debut=formsemestre.date_debut.isoformat(),
+ date_fin=formsemestre.date_fin.isoformat(),
+ )
if group["group_name"]:
group["label"] = "groupe %(group_name)s" % group
else:
diff --git a/app/scodoc/sco_groups_view.py b/app/scodoc/sco_groups_view.py
index 5f12735db..b27098ef2 100644
--- a/app/scodoc/sco_groups_view.py
+++ b/app/scodoc/sco_groups_view.py
@@ -819,9 +819,13 @@ def tab_absences_html(groups_infos, etat=None):
H = ['Aucun étudiant !
Absences
",
+ "Assiduités
",
'',
"
",
"Feuilles
",
'',
diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py
index c45c72c53..43b66230b 100644
--- a/app/scodoc/sco_moduleimpl_status.py
+++ b/app/scodoc/sco_moduleimpl_status.py
@@ -29,6 +29,7 @@
"""
import math
import time
+import datetime
from flask import g, url_for
from flask_login import current_user
@@ -332,20 +333,19 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
current_user.has_permission(Permission.ScoAbsChange)
and formsemestre.est_courant()
):
- datelundi = sco_cal.ddmmyyyy(time.strftime("%d/%m/%Y")).prev_monday()
group_id = sco_groups.get_default_group(formsemestre_id)
H.append(
f"""
- Saisie Absences hebdo. (INDISPONIBLE)
+ Saisie Absences hebdo
"""
)
- # TODO-ASSIDUITE
- # href="{
- # url_for("absences.SignaleAbsenceGrHebdo",
- # scodoc_dept=g.scodoc_dept,formsemestre_id=formsemestre_id,
- # moduleimpl_id=moduleimpl_id, datelundi=datelundi, group_ids=group_id)
- # }"
H.append("")
#
diff --git a/app/templates/assiduites/pages/ajout_justificatif.j2 b/app/templates/assiduites/pages/ajout_justificatif.j2
index 9aaf83e28..4cbc8f590 100644
--- a/app/templates/assiduites/pages/ajout_justificatif.j2
+++ b/app/templates/assiduites/pages/ajout_justificatif.j2
@@ -1,5 +1,5 @@
+{% include "assiduites/widgets/toast.j2" %}
{% block pageContent %}
-
Justifier des assiduités
{% include "assiduites/widgets/tableau_base.j2" %}
@@ -12,7 +12,7 @@