Merge pull request 'dates antipodiques: ajout get_periode, tests et intégration' (#527) from jmplace/ScoDoc-Lille:improve_periode_management into master

Reviewed-on: https://scodoc.org/git/ScoDoc/ScoDoc/pulls/527
This commit is contained in:
Emmanuel Viennet 2022-11-11 09:40:02 +01:00
commit 51d7dff649
4 changed files with 211 additions and 54 deletions

View File

@ -586,7 +586,16 @@ class ApoEtud(dict):
(sem["semestre_id"] == apo_data.cur_semestre_id) (sem["semestre_id"] == apo_data.cur_semestre_id)
and (apo_data.etape in sem["etapes"]) and (apo_data.etape in sem["etapes"])
and ( and (
sco_formsemestre.sem_in_annee_scolaire(sem, apo_data.annee_scolaire) # sco_formsemestre.sem_in_annee_scolaire(sem, apo_data.annee_scolaire) # TODO à remplacer par ?
sco_formsemestre.sem_in_semestre_scolaire(
sem,
apo_data.annee_scolaire,
0,
# jour_pivot_annee,
# mois_pivot_annee,
# jour_pivot_periode,
# mois_pivot_periode
)
) )
) )
] ]

View File

@ -422,67 +422,97 @@ def sem_set_responsable_name(sem):
) )
def debut_in_semestre_scolaire( def get_periode(
date_debut: datetime.date, year: int = False, saison: int = 0 debut: datetime,
) -> bool: jour_pivot_annee=1,
"""Vrai si date_debut est dans l'année scolaire ou le semestre mois_pivot_annee=8,
indiquée par year et periode jour_pivot_periode=1,
(par défaut, l'année scolaire en cours). mois_pivot_periode=12,
periode: ):
1 = sept, """Calcule la session associée à un formsemestre sous la forme (année, période)
0 = janvier année: première année de l'année scolaire
None = année complète période = 1 (première période de l'année scolaire anciennement automne)
ou 2 (deuxième période de l'année scolaire - anciennement printemps)
les quatre derniers paramètres forment les dates pivots pour l'année (1er août par défaut)
et pour la période (1er décembre par défaut).
Tous les calculs se font à partir de la date de début du formsemestre.
Exemples dans tests/unit/test_periode
""" """
if not year: """Implementation
year = scu.AnneeScolaire() Cas à considérer pour le calcul de la période
# XXX WIP à voir selon ce que fait réellement sem_in_semestre_scolaire
pa < pp -----------------|-------------------|---------------->
def sem_in_semestre_scolaire(sem, year=False, saison=0): (A-1, P:2) pa (A, P:1) pp (A, P:2)
"""n'utilise que la date de debut, pivot au 1er aout pp < pa -----------------|-------------------|---------------->
si annee non specifiée, année scolaire courante (A-1, P:1) pp (A-1, P:2) pa (A, P:1)
Patch Jmp: ajout du parametre optionnel saison
1 = sept, 0 = janvier, None = année complète
si saison non spécifiée: année complète
pivot de saison au 1er décembre
XXX TODO: la période (ici appelée "saison" devrait être éditable
manuellement dans le formsemestre_edit afin de couvrir les cas particulier
comme un semestre S2 qui commencerait en décembre... voire novembre.
)
""" """
if not year: pa = 100 * mois_pivot_annee + jour_pivot_annee
year = scu.AnneeScolaire() pp = 100 * mois_pivot_periode + jour_pivot_periode
# est-on dans la même année universitaire ? ps = 100 * debut.month + debut.day
if sem["mois_debut_ord"] > 7: # XXX if ps < pa:
if sem["annee_debut"] != str(year): annee = debut.year - 1
return False
else: else:
if sem["annee_debut"] != str(year + 1): annee = debut.year
return False if pa < pp:
# raffinement éventuel sur le semestre if ps < pa or ps > pp:
# saison is None => pas de rafinement => True periode = 2
if saison == 0: else:
return True periode = 1
elif saison == 1: # calcul en fonction de la saison else:
return sem["mois_debut_ord"] > 7 and sem["mois_debut_ord"] < 12 if ps < pp or ps > pa:
else: # saison == 0 periode = 1
return sem["mois_debut_ord"] <= 7 or sem["mois_debut_ord"] == 12 else:
periode = 2
return annee, periode
def sem_in_annee_scolaire(sem, year=False): def sem_in_semestre_scolaire(
"""Test si sem appartient à l'année scolaire year (int). sem,
N'utilise que la date de début, pivot au 1er août. year=False,
Si année non specifiée, année scolaire courante periode=None,
jour_pivot_annee=1,
mois_pivot_annee=8,
jour_pivot_periode=1,
mois_pivot_periode=12,
):
"""n'utilise que la date de debut,
si annee non specifiée, année scolaire courante
la période garde les même convention que semset["sem_id"];
* 1 : premère période
* 2 : deuxième période
* 0 ou periode non précisée: annualisé (donc inclut toutes les périodes)
)
""" """
if not year: if not year:
year = scu.AnneeScolaire() year = scu.AnneeScolaire()
return ( # calcule l'année universitaire et la periode
(sem["annee_debut"] == str(year)) sem_annee, sem_periode = get_periode(
and (sem["mois_debut_ord"] > scu.MONTH_FIN_ANNEE_SCOLAIRE) datetime.datetime.fromisoformat(sem["date_debut_iso"]),
) or ( jour_pivot_annee,
(sem["annee_debut"] == str(year + 1)) mois_pivot_annee,
and (sem["mois_debut_ord"] <= scu.MONTH_FIN_ANNEE_SCOLAIRE) jour_pivot_periode,
mois_pivot_periode,
) )
if periode is None or periode == 0:
return sem_annee == year
else:
return sem_annee == year and sem_periode == periode
# def sem_in_annee_scolaire(sem, year=False):
# """Test si sem appartient à l'année scolaire year (int).
# N'utilise que la date de début, pivot au 1er août.
# Si année non specifiée, année scolaire courante
# """
# if not year:
# year = scu.AnneeScolaire()
# return (
# (sem["annee_debut"] == str(year))
# and (sem["mois_debut_ord"] > scu.MONTH_FIN_ANNEE_SCOLAIRE)
# ) or (
# (sem["annee_debut"] == str(year + 1))
# and (sem["mois_debut_ord"] <= scu.MONTH_FIN_ANNEE_SCOLAIRE)
# )
def sem_est_courant(sem): # -> FormSemestre.est_courant def sem_est_courant(sem): # -> FormSemestre.est_courant

View File

@ -233,7 +233,8 @@ class SemSet(dict):
if sco_formsemestre.sem_in_semestre_scolaire( if sco_formsemestre.sem_in_semestre_scolaire(
sem, sem,
year=self["annee_scolaire"], year=self["annee_scolaire"],
saison=self["sem_id"], # Indiquer ici les valeur des dates pivots année et période
periode=self["sem_id"],
) )
] ]
return sems return sems

117
tests/unit/test_periode.py Normal file
View File

@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
"""Test Periodes
Utiliser comme:
pytest tests/unit/test_periode.py
"""
import datetime
from app.scodoc.sco_formsemestre import get_periode, sem_in_semestre_scolaire
""" Calcule la session associée à un formsemestre sous la forme (année, période)
année: première année de l'année scolaire
période = 1 (première période de l'année scolaire) ou 2 (deuxième période de l'année scolaire)
les quatre derniers paramètres forment les dates pivots pour l'année (1er août par défaut)
et pour la période (1er décembre par défaut).
Tous les calculs se font à partir de la date de début du formsemestre.
Exemples:
Début FormSemestre pivot_année pivot_periode Résultat
01/01/2022 ( 1, 8) ( 1,12) (2021,2) # A: printemps nord
01/09/2022 ( 1, 8) ( 1,12) (2022,1) # B: automne nord
15/12/2022 ( 1, 8) ( 1,12) (2022,2)
30/07/2023 ( 1, 8) ( 1,12) (2022,2)
01/01/2022 ( 1, 1) ( 1, 8) (2022,1) # antipodes
30/07/2022 ( 1, 1) ( 1, 8) (2022,1) # antipodes
02/08/2022 ( 1, 1) ( 1, 8) (2022,2) # antipodes
30/12/2022 ( 1, 1) ( 1, 8) (2022,2) # antipodes
01/01/2022 ( 3, 1) ( 1, 8) (2021,2) # antipodes l'année scolaire démarre le 3 janvier
10/01/2024 ( 1, 8) ( 1, 2) (2023,2) # pivot période < pivot année
01/06/2024 ( 1, 8) ( 1, 2) (2023,2) # pivot période < pivot année
20/09/2024 ( 1, 8) ( 1, 2) (2024,1) # pivot période < pivot année
"""
def test_default():
# with default
assert (2021, 2) == get_periode(datetime.datetime(2022, 1, 1))
assert (2021, 2) == get_periode(datetime.datetime(2022, 1, 1), 1, 8, 1, 12)
def test_automne_nord():
assert (2022, 1) == get_periode(datetime.datetime(2022, 9, 1))
def test_noel_nord():
assert (2022, 2) == get_periode(datetime.datetime(2022, 12, 15))
def test_étét_nord():
assert (2021, 2) == get_periode(datetime.datetime(2022, 7, 30))
def test_printemps_sud():
assert (2022, 1) == get_periode(datetime.datetime(2022, 1, 1), 1, 1, 1, 8)
def test_automne_sud():
assert (2022, 2) == get_periode(datetime.datetime(2022, 8, 2), 1, 1, 1, 8)
def test_noel_sud():
assert (2022, 2) == get_periode(datetime.datetime(2022, 12, 30), 1, 1, 1, 8)
def test_été_sud():
assert (2022, 1) == get_periode(datetime.datetime(2022, 7, 30), 1, 1, 1, 8)
def test_nouvel_an_sud():
assert (2021, 2) == get_periode(datetime.datetime(2022, 1, 1), 3, 1, 1, 8)
def test_nouvel_an_special_pp_before_pa():
assert (2023, 1) == get_periode(datetime.datetime(2024, 1, 10), 1, 8, 1, 2)
def test_nouvel_été_pp_before_pa():
assert (2023, 2) == get_periode(datetime.datetime(2024, 6, 1), 1, 8, 1, 2)
def test_automne_special_pp_before_pa():
assert (2024, 1) == get_periode(datetime.datetime(2024, 9, 20), 1, 8, 1, 2)
sem_automne = {"date_debut_iso": "2022-09-24"}
sem_nouvel_an = {"date_debut_iso": "2023-01-01"}
sem_printemps = {"date_debut_iso": "2023-03-14"}
sem_été = {"date_debut_iso": "2023-07-11"}
sem_next_year = {"date_debut_iso": "2023-08-16"}
sem_prev_year = {"date_debut_iso": "2022-07-31"}
def test_sem_in_periode1_default():
assert True == sem_in_semestre_scolaire(sem_automne, 2022, 1)
assert False == sem_in_semestre_scolaire(sem_nouvel_an, 2022, 1)
assert False == sem_in_semestre_scolaire(sem_printemps, 2022, 1)
assert False == sem_in_semestre_scolaire(sem_été, 2022, 1)
assert False == sem_in_semestre_scolaire(sem_next_year, 2022, 1)
assert False == sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
def test_sem_in_periode2_default():
assert False == sem_in_semestre_scolaire(sem_automne, 2022, 2)
assert True == sem_in_semestre_scolaire(sem_nouvel_an, 2022, 2)
assert True == sem_in_semestre_scolaire(sem_printemps, 2022, 2)
assert True == sem_in_semestre_scolaire(sem_été, 2022, 2)
assert False == sem_in_semestre_scolaire(sem_next_year, 2022, 1)
assert False == sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
def test_sem_in_annee_default():
assert True == sem_in_semestre_scolaire(sem_automne, 2022, 0)
assert True == sem_in_semestre_scolaire(sem_nouvel_an, 2022)
assert True == sem_in_semestre_scolaire(sem_printemps, 2022, 0)
assert True == sem_in_semestre_scolaire(sem_été, 2022, 0)
assert False == sem_in_semestre_scolaire(sem_next_year, 2022)
assert False == sem_in_semestre_scolaire(sem_prev_year, 2022, 0)