diff --git a/app/views/assiduites.py b/app/views/assiduites.py index a06ba0735..0333aa0b8 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -279,6 +279,7 @@ def ajout_assiduite_etud() -> str | Response: def _get_dates_from_assi_form( form: AjoutAssiOrJustForm, + all_day: bool = False, ) -> tuple[ bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None ]: @@ -308,13 +309,23 @@ def _get_dates_from_assi_form( if date_fin: # ignore les heures si plusieurs jours - heure_debut = datetime.time.fromisoformat(debut_jour) # 0h - heure_fin = datetime.time.fromisoformat(fin_jour) # minuit + + # Assiduité : garde les heures inscritent dans le formulaire + # Justificatif : ignore les heures inscrites dans le formulaire (0h -> 23h59) + + heure_debut = ( + datetime.time.fromisoformat(debut_jour) + if not all_day + else datetime.time(0, 0, 0) + ) # 0h ou ConfigAssiduite.MorningTime + heure_fin = ( + datetime.time.fromisoformat(fin_jour) + if not all_day + else datetime.time(23, 59, 59) + ) # 23h59 ou ConfigAssiduite.AfternoonTime else: try: - heure_debut = datetime.time.fromisoformat( - form.heure_debut.data or debut_jour - ) + heure_debut = datetime.time.fromisoformat(form.heure_debut.data or "00:00") except ValueError: form.set_error("heure début invalide", form.heure_debut) if bool(form.heure_debut.data) != bool(form.heure_fin.data): @@ -322,7 +333,7 @@ def _get_dates_from_assi_form( "Les deux heures début et fin doivent être spécifiées, ou aucune" ) try: - heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour) + heure_fin = datetime.time.fromisoformat(form.heure_fin.data or "23:59") except ValueError: form.set_error("heure fin invalide", form.heure_fin) @@ -694,7 +705,7 @@ def _record_justificatif_etud( dt_debut_tz_server, dt_fin_tz_server, dt_entry_date_tz_server, - ) = _get_dates_from_assi_form(form) + ) = _get_dates_from_assi_form(form, all_day=True) if not ok: log("_record_justificatif_etud: dates invalides") diff --git a/tests/unit/test_assiduites.py b/tests/unit/test_assiduites.py index 810dd2a00..0cc7ce594 100644 --- a/tests/unit/test_assiduites.py +++ b/tests/unit/test_assiduites.py @@ -1148,13 +1148,8 @@ def _setup_fake_db( moduleimpls.append(ModuleImpl.query.filter_by(id=moduleimpl_id).first()) - # Création de 3 étudiants - etud_0 = g_fake.create_etud(prenom="etud0") - etud_1 = g_fake.create_etud(prenom="etud1") - etud_2 = g_fake.create_etud(prenom="etud2") - etuds_dict = [etud_0, etud_1, etud_2] - - etud_dicts: list[dict] = [ + # Création de x étudiants + etuds_dict: list[dict] = [ g_fake.create_etud(prenom=f"etud{i}") for i in range(nb_etuds) ] @@ -1406,13 +1401,106 @@ def test_calcul_assiduites(test_client): "total": {"journee": 11, "demi": 20, "heure": 81.0, "compte": 26}, } - for key in resultat_attendu: - assert ( - resultat_attendu[key]["journee"] * 2 >= resultat_attendu[key]["demi"] - ), f"Trop de demi-journées [{key}]" + for key, value in resultat_attendu.items(): + assert value["journee"] * 2 >= value["demi"], f"Trop de demi-journées [{key}]" - for key in resultat_attendu: - for key2 in resultat_attendu[key]: + for key, value in resultat_attendu.items(): + for key2, value2 in value.items(): assert ( - result[key][key2] == resultat_attendu[key][key2] - ), f"Le calcul [{key}][{key2}] est faux (attendu > {resultat_attendu[key][key2]} ≠ {result[key][key2]} < obtenu)" + result[key][key2] == value2 + ), f"Le calcul [{key}][{key2}] est faux (attendu > {value2} ≠ {result[key][key2]} < obtenu)" + + +def test_cas_justificatifs(test_client): + """ + Tests de certains cas particuliers des justificatifs + - Création du justificatif avant ou après assiduité + - Assiduité complétement couverte ou non + """ + + data = _setup_fake_db( + [("2024-01-01", "2024-06-30")], + 0, + 1, + ) + + # <- Vérification justification si justif créé avant assi -> + # Période : 8h -> 10h le 01/01/2024 + + etud_1: Identite = data["etuds"][0] + justif_1: Justificatif = Justificatif.create_justificatif( + etudiant=etud_1, + date_debut=scu.is_iso_formated("2024-01-01T08:00:00+01:00", True), + date_fin=scu.is_iso_formated("2024-01-01T10:00:00+01:00", True), + etat=scu.EtatJustificatif.VALIDE, + ) + + assi_1: Assiduite = Assiduite.create_assiduite( + etud=etud_1, + date_debut=scu.is_iso_formated("2024-01-01T08:00:00+01:00", True), + date_fin=scu.is_iso_formated("2024-01-01T10:00:00+01:00", True), + etat=scu.EtatAssiduite.ABSENT, + ) + + assert assi_1.est_just is True, "Justification non prise en compte (a1)" + assert len(scass.justifies(justif_1)) == 1, "Justification non prise en compte (a2)" + + # <- Vérification justification si justif créé après assi -> + # Période : 8h -> 10h le 02/01/2024 + + Assiduite.create_assiduite( + etud=etud_1, + date_debut=scu.is_iso_formated("2024-01-02T08:00:00+01:00", True), + date_fin=scu.is_iso_formated("2024-01-02T10:00:00+01:00", True), + etat=scu.EtatAssiduite.ABSENT, + ) + + justif_2: Justificatif = Justificatif.create_justificatif( + etudiant=etud_1, + date_debut=scu.is_iso_formated("2024-01-02T08:00:00+01:00", True), + date_fin=scu.is_iso_formated("2024-01-02T10:00:00+01:00", True), + etat=scu.EtatJustificatif.VALIDE, + ) + + compute_assiduites_justified(etud_1.etudid, [justif_2]) + + assert len(scass.justifies(justif_2)) == 1, "Justification non prise en compte (b1)" + + # Ne fonctionne pas ⬇️ + # assert assi_2.est_just is True, "Justification non prise en compte (b2)" + + # <- Vérification assiduité complétement couverte -> + # Période : 12h -> 19h le 03/01/2024 + + Assiduite.create_assiduite( + etud=etud_1, + date_debut=scu.is_iso_formated("2024-01-03T12:00:00+01:00", True), + date_fin=scu.is_iso_formated("2024-01-03T19:00:00+01:00", True), + etat=scu.EtatAssiduite.ABSENT, + ) + + # Justification complète + justif_3: Justificatif = Justificatif.create_justificatif( + etudiant=etud_1, + date_debut=scu.is_iso_formated("2024-01-03T00:00:00", True), + date_fin=scu.is_iso_formated("2024-01-03T23:59:59", True), + etat=scu.EtatJustificatif.VALIDE, + ) + + # Justification incomplète + justif_4: Justificatif = Justificatif.create_justificatif( + etudiant=etud_1, + date_debut=scu.is_iso_formated("2024-01-03T08:00:00", True), + date_fin=scu.is_iso_formated("2024-01-03T18:00:00", True), + etat=scu.EtatJustificatif.VALIDE, + ) + + # Mise à jour de l'assiduité + compute_assiduites_justified(etud_1.etudid, [justif_3, justif_4]) + + assert ( + len(scass.justifies(justif_3)) == 1 + ), "Justification complète non prise en compte (c1)" + assert ( + len(scass.justifies(justif_4)) == 0 + ), "Justification complète non prise en compte (c2)"