Paramétrage dates annees scolaires (pivots) + tous test unitaires OK
This commit is contained in:
parent
a2ea7d7a02
commit
d7f1114a42
@ -54,6 +54,22 @@ class BonusConfigurationForm(FlaskForm):
|
|||||||
class ScoDocConfigurationForm(FlaskForm):
|
class ScoDocConfigurationForm(FlaskForm):
|
||||||
"Panneau de configuration avancée"
|
"Panneau de configuration avancée"
|
||||||
enable_entreprises = BooleanField("activer le module <em>entreprises</em>")
|
enable_entreprises = BooleanField("activer le module <em>entreprises</em>")
|
||||||
|
month_debut_annee_scolaire = SelectField(
|
||||||
|
label="Mois de début des années scolaires",
|
||||||
|
description="""Date pivot. En France métropolitaine, août.
|
||||||
|
S'applique à tous les départements.""",
|
||||||
|
choices=[
|
||||||
|
(i, name.capitalize()) for (i, name) in enumerate(scu.MONTH_NAMES, start=1)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
month_debut_periode2 = SelectField(
|
||||||
|
label="Mois de début deuxième période de l'année",
|
||||||
|
description="""Date pivot. En France métropolitaine, décembre.
|
||||||
|
S'applique à tous les départements.""",
|
||||||
|
choices=[
|
||||||
|
(i, name.capitalize()) for (i, name) in enumerate(scu.MONTH_NAMES, start=1)
|
||||||
|
],
|
||||||
|
)
|
||||||
submit_scodoc = SubmitField("Valider")
|
submit_scodoc = SubmitField("Valider")
|
||||||
cancel_scodoc = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
cancel_scodoc = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
||||||
|
|
||||||
@ -67,7 +83,11 @@ def configuration():
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
form_scodoc = ScoDocConfigurationForm(
|
form_scodoc = ScoDocConfigurationForm(
|
||||||
data={"enable_entreprises": ScoDocSiteConfig.is_entreprises_enabled()}
|
data={
|
||||||
|
"enable_entreprises": ScoDocSiteConfig.is_entreprises_enabled(),
|
||||||
|
"month_debut_annee_scolaire": ScoDocSiteConfig.get_month_debut_annee_scolaire(),
|
||||||
|
"month_debut_periode2": ScoDocSiteConfig.get_month_debut_periode2(),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
if request.method == "POST" and (
|
if request.method == "POST" and (
|
||||||
form_bonus.cancel_bonus.data or form_scodoc.cancel_scodoc.data
|
form_bonus.cancel_bonus.data or form_scodoc.cancel_scodoc.data
|
||||||
@ -94,6 +114,22 @@ def configuration():
|
|||||||
"Module entreprise "
|
"Module entreprise "
|
||||||
+ ("activé" if form_scodoc.data["enable_entreprises"] else "désactivé")
|
+ ("activé" if form_scodoc.data["enable_entreprises"] else "désactivé")
|
||||||
)
|
)
|
||||||
|
if ScoDocSiteConfig.set_month_debut_annee_scolaire(
|
||||||
|
int(form_scodoc.data["month_debut_annee_scolaire"])
|
||||||
|
):
|
||||||
|
flash(
|
||||||
|
f"""Début des années scolaires fixé au mois de {
|
||||||
|
scu.MONTH_NAMES[ScoDocSiteConfig.get_month_debut_annee_scolaire()-1]
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
if ScoDocSiteConfig.set_month_debut_periode2(
|
||||||
|
int(form_scodoc.data["month_debut_periode2"])
|
||||||
|
):
|
||||||
|
flash(
|
||||||
|
f"""Début des années scolaires fixé au mois de {
|
||||||
|
scu.MONTH_NAMES[ScoDocSiteConfig.get_month_debut_periode2()-1]
|
||||||
|
}"""
|
||||||
|
)
|
||||||
return redirect(url_for("scodoc.index"))
|
return redirect(url_for("scodoc.index"))
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
from flask import flash
|
from flask import flash
|
||||||
from app import db, log
|
from app import db, log
|
||||||
from app.comp import bonus_spo
|
from app.comp import bonus_spo
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
from app.scodoc.sco_codes_parcours import (
|
from app.scodoc.sco_codes_parcours import (
|
||||||
ABAN,
|
ABAN,
|
||||||
@ -83,6 +83,8 @@ class ScoDocSiteConfig(db.Model):
|
|||||||
"INSTITUTION_CITY": str,
|
"INSTITUTION_CITY": str,
|
||||||
"DEFAULT_PDF_FOOTER_TEMPLATE": str,
|
"DEFAULT_PDF_FOOTER_TEMPLATE": str,
|
||||||
"enable_entreprises": bool,
|
"enable_entreprises": bool,
|
||||||
|
"month_debut_annee_scolaire": int,
|
||||||
|
"month_debut_periode2": int,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
@ -223,3 +225,73 @@ class ScoDocSiteConfig(db.Model):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_int_field(cls, name: str, default=None) -> int:
|
||||||
|
"""Valeur d'un champs integer"""
|
||||||
|
cfg = ScoDocSiteConfig.query.filter_by(name=name).first()
|
||||||
|
if (cfg is None) or cfg.value is None:
|
||||||
|
return default
|
||||||
|
return int(cfg.value)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _set_int_field(
|
||||||
|
cls,
|
||||||
|
name: str,
|
||||||
|
value: int,
|
||||||
|
default=None,
|
||||||
|
range_values: tuple = (),
|
||||||
|
) -> bool:
|
||||||
|
"""Set champs integer. True si changement."""
|
||||||
|
if value != cls._get_int_field(name, default=default):
|
||||||
|
if not isinstance(value, int) or (
|
||||||
|
range_values and (value < range_values[0]) or (value > range_values[1])
|
||||||
|
):
|
||||||
|
raise ValueError("invalid value")
|
||||||
|
cfg = ScoDocSiteConfig.query.filter_by(name=name).first()
|
||||||
|
if cfg is None:
|
||||||
|
cfg = ScoDocSiteConfig(name=name, value=str(value))
|
||||||
|
else:
|
||||||
|
cfg.value = str(value)
|
||||||
|
db.session.add(cfg)
|
||||||
|
db.session.commit()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_month_debut_annee_scolaire(cls) -> int:
|
||||||
|
"""Mois de début de l'année scolaire."""
|
||||||
|
return cls._get_int_field(
|
||||||
|
"month_debut_annee_scolaire", scu.MONTH_DEBUT_ANNEE_SCOLAIRE
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_month_debut_periode2(cls) -> int:
|
||||||
|
"""Mois de début de l'année scolaire."""
|
||||||
|
return cls._get_int_field("month_debut_periode2", scu.MONTH_DEBUT_PERIODE2)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_month_debut_annee_scolaire(
|
||||||
|
cls, month: int = scu.MONTH_DEBUT_ANNEE_SCOLAIRE
|
||||||
|
) -> bool:
|
||||||
|
"""Fixe le mois de début des années scolaires.
|
||||||
|
True si changement.
|
||||||
|
"""
|
||||||
|
if cls._set_int_field(
|
||||||
|
"month_debut_annee_scolaire", month, scu.MONTH_DEBUT_ANNEE_SCOLAIRE, (1, 12)
|
||||||
|
):
|
||||||
|
log(f"set_month_debut_annee_scolaire({month})")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_month_debut_periode2(cls, month: int = scu.MONTH_DEBUT_PERIODE2) -> bool:
|
||||||
|
"""Fixe le mois de début des années scolaires.
|
||||||
|
True si changement.
|
||||||
|
"""
|
||||||
|
if cls._set_int_field(
|
||||||
|
"month_debut_periode2", month, scu.MONTH_DEBUT_PERIODE2, (1, 12)
|
||||||
|
):
|
||||||
|
log(f"set_month_debut_periode2({month})")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
@ -5,44 +5,42 @@
|
|||||||
# See LICENSE
|
# See LICENSE
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
# pylint génère trop de faux positifs avec les colonnes date:
|
||||||
|
# pylint: disable=no-member,not-an-iterable
|
||||||
|
|
||||||
"""ScoDoc models: formsemestre
|
"""ScoDoc models: formsemestre
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
from flask import flash, g
|
|
||||||
import flask_sqlalchemy
|
import flask_sqlalchemy
|
||||||
|
from flask import flash, g
|
||||||
from sqlalchemy.sql import text
|
from sqlalchemy.sql import text
|
||||||
|
|
||||||
from app import db
|
import app.scodoc.sco_utils as scu
|
||||||
from app import log
|
from app import db, log
|
||||||
from app.models import APO_CODE_STR_LEN
|
from app.models import APO_CODE_STR_LEN, CODE_STR_LEN, SHORT_STR_LEN
|
||||||
from app.models import SHORT_STR_LEN
|
|
||||||
from app.models import CODE_STR_LEN
|
|
||||||
from app.models.but_refcomp import (
|
from app.models.but_refcomp import (
|
||||||
ApcAnneeParcours,
|
ApcAnneeParcours,
|
||||||
ApcNiveau,
|
ApcNiveau,
|
||||||
ApcParcours,
|
ApcParcours,
|
||||||
ApcParcoursNiveauCompetence,
|
ApcParcoursNiveauCompetence,
|
||||||
ApcReferentielCompetences,
|
ApcReferentielCompetences,
|
||||||
|
parcours_formsemestre,
|
||||||
)
|
)
|
||||||
from app.models.groups import GroupDescr, Partition
|
from app.models.config import ScoDocSiteConfig
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
|
||||||
from app.models.but_refcomp import parcours_formsemestre
|
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.models.formations import Formation
|
from app.models.formations import Formation
|
||||||
from app.models.modules import Module
|
from app.models.groups import GroupDescr, Partition
|
||||||
from app.models.moduleimpls import ModuleImpl, ModuleImplInscription
|
from app.models.moduleimpls import ModuleImpl, ModuleImplInscription
|
||||||
|
from app.models.modules import Module
|
||||||
from app.models.ues import UniteEns
|
from app.models.ues import UniteEns
|
||||||
from app.models.validations import ScolarFormSemestreValidation
|
from app.models.validations import ScolarFormSemestreValidation
|
||||||
|
from app.scodoc import sco_codes_parcours, sco_preferences
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc import sco_preferences
|
|
||||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.sco_utils import MONTH_NAMES_ABBREV
|
from app.scodoc.sco_utils import MONTH_NAMES_ABBREV
|
||||||
|
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||||
|
|
||||||
|
|
||||||
class FormSemestre(db.Model):
|
class FormSemestre(db.Model):
|
||||||
@ -226,7 +224,8 @@ class FormSemestre(db.Model):
|
|||||||
d["mois_debut_ord"] = self.date_debut.month
|
d["mois_debut_ord"] = self.date_debut.month
|
||||||
d["mois_fin_ord"] = self.date_fin.month
|
d["mois_fin_ord"] = self.date_fin.month
|
||||||
# La période: considère comme "S1" (ou S3) les débuts en aout-sept-octobre
|
# La période: considère comme "S1" (ou S3) les débuts en aout-sept-octobre
|
||||||
# devrait sans doute pouvoir etre changé...
|
# devrait sans doute pouvoir etre changé... XXX PIVOT
|
||||||
|
d["periode"] = self.periode()
|
||||||
if self.date_debut.month >= 8 and self.date_debut.month <= 10:
|
if self.date_debut.month >= 8 and self.date_debut.month <= 10:
|
||||||
d["periode"] = 1 # typiquement, début en septembre: S1, S3...
|
d["periode"] = 1 # typiquement, début en septembre: S1, S3...
|
||||||
else:
|
else:
|
||||||
@ -345,7 +344,7 @@ class FormSemestre(db.Model):
|
|||||||
(les dates de début et fin sont incluses)
|
(les dates de début et fin sont incluses)
|
||||||
"""
|
"""
|
||||||
today = datetime.date.today()
|
today = datetime.date.today()
|
||||||
return (self.date_debut <= today) and (today <= self.date_fin)
|
return self.date_debut <= today <= self.date_fin
|
||||||
|
|
||||||
def contient_periode(self, date_debut, date_fin) -> bool:
|
def contient_periode(self, date_debut, date_fin) -> bool:
|
||||||
"""Vrai si l'intervalle [date_debut, date_fin] est
|
"""Vrai si l'intervalle [date_debut, date_fin] est
|
||||||
@ -361,14 +360,16 @@ class FormSemestre(db.Model):
|
|||||||
Pivot au 1er août par défaut.
|
Pivot au 1er août par défaut.
|
||||||
"""
|
"""
|
||||||
if self.date_debut > self.date_fin:
|
if self.date_debut > self.date_fin:
|
||||||
|
flash(f"Dates début/fin inversées pour le semestre {self.titre_annee()}")
|
||||||
log(f"Warning: semestre {self.id} begins after ending !")
|
log(f"Warning: semestre {self.id} begins after ending !")
|
||||||
annee_debut = self.date_debut.year
|
annee_debut = self.date_debut.year
|
||||||
if self.date_debut.month <= scu.MONTH_FIN_ANNEE_SCOLAIRE: # juillet
|
month_debut_annee = ScoDocSiteConfig.get_month_debut_annee_scolaire()
|
||||||
# considere que debut sur l'anne scolaire precedente
|
if self.date_debut.month < month_debut_annee:
|
||||||
|
# début sur l'année scolaire précédente (juillet inclus par défaut)
|
||||||
annee_debut -= 1
|
annee_debut -= 1
|
||||||
annee_fin = self.date_fin.year
|
annee_fin = self.date_fin.year
|
||||||
if self.date_fin.month <= (scu.MONTH_FIN_ANNEE_SCOLAIRE + 1):
|
if self.date_fin.month < (month_debut_annee + 1):
|
||||||
# 9 (sept) pour autoriser un début en sept et une fin en aout
|
# 9 (sept) pour autoriser un début en sept et une fin en août
|
||||||
annee_fin -= 1
|
annee_fin -= 1
|
||||||
return annee_debut == annee_fin
|
return annee_debut == annee_fin
|
||||||
|
|
||||||
@ -383,16 +384,74 @@ class FormSemestre(db.Model):
|
|||||||
# impair
|
# impair
|
||||||
(
|
(
|
||||||
self.semestre_id % 2
|
self.semestre_id % 2
|
||||||
and self.date_debut.month < scu.MONTH_FIN_ANNEE_SCOLAIRE
|
and self.date_debut.month < scu.MONTH_DEBUT_ANNEE_SCOLAIRE
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
# pair
|
# pair
|
||||||
(
|
(
|
||||||
(not self.semestre_id % 2)
|
(not self.semestre_id % 2)
|
||||||
and self.date_debut.month >= scu.MONTH_FIN_ANNEE_SCOLAIRE
|
and self.date_debut.month >= scu.MONTH_DEBUT_ANNEE_SCOLAIRE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def comp_periode(
|
||||||
|
cls,
|
||||||
|
date_debut: datetime,
|
||||||
|
mois_pivot_annee=scu.MONTH_DEBUT_ANNEE_SCOLAIRE,
|
||||||
|
mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
|
||||||
|
jour_pivot_annee=1,
|
||||||
|
jour_pivot_periode=1,
|
||||||
|
):
|
||||||
|
"""Calcule la session associée à un formsemestre commençant en date_debut
|
||||||
|
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, souvent automne)
|
||||||
|
ou 2 (deuxième période de l'année scolaire, souvent 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).
|
||||||
|
|
||||||
|
Les calculs se font à partir de la date de début indiquée.
|
||||||
|
Exemples dans tests/unit/test_periode
|
||||||
|
|
||||||
|
Implémentation:
|
||||||
|
Cas à considérer pour le calcul de la période
|
||||||
|
|
||||||
|
pa < pp -----------------|-------------------|---------------->
|
||||||
|
(A-1, P:2) pa (A, P:1) pp (A, P:2)
|
||||||
|
pp < pa -----------------|-------------------|---------------->
|
||||||
|
(A-1, P:1) pp (A-1, P:2) pa (A, P:1)
|
||||||
|
"""
|
||||||
|
pivot_annee = 100 * mois_pivot_annee + jour_pivot_annee
|
||||||
|
pivot_periode = 100 * mois_pivot_periode + jour_pivot_periode
|
||||||
|
pivot_sem = 100 * date_debut.month + date_debut.day
|
||||||
|
if pivot_sem < pivot_annee:
|
||||||
|
annee = date_debut.year - 1
|
||||||
|
else:
|
||||||
|
annee = date_debut.year
|
||||||
|
if pivot_annee < pivot_periode:
|
||||||
|
if pivot_sem < pivot_annee or pivot_sem >= pivot_periode:
|
||||||
|
periode = 2
|
||||||
|
else:
|
||||||
|
periode = 1
|
||||||
|
else:
|
||||||
|
if pivot_sem < pivot_periode or pivot_sem >= pivot_annee:
|
||||||
|
periode = 1
|
||||||
|
else:
|
||||||
|
periode = 2
|
||||||
|
return annee, periode
|
||||||
|
|
||||||
|
def periode(self) -> int:
|
||||||
|
"""La période:
|
||||||
|
* 1 : première période: automne à Paris
|
||||||
|
* 2 : deuxième période, printemps à Paris
|
||||||
|
"""
|
||||||
|
return FormSemestre.comp_periode(
|
||||||
|
self.date_debut,
|
||||||
|
mois_pivot_annee=ScoDocSiteConfig.get_month_debut_annee_scolaire(),
|
||||||
|
mois_pivot_periode=ScoDocSiteConfig.get_month_debut_periode2(),
|
||||||
|
)
|
||||||
|
|
||||||
def etapes_apo_vdi(self) -> list[ApoEtapeVDI]:
|
def etapes_apo_vdi(self) -> list[ApoEtapeVDI]:
|
||||||
"Liste des vdis"
|
"Liste des vdis"
|
||||||
# was read_formsemestre_etapes
|
# was read_formsemestre_etapes
|
||||||
@ -443,7 +502,7 @@ class FormSemestre(db.Model):
|
|||||||
|
|
||||||
def annee_scolaire(self) -> int:
|
def annee_scolaire(self) -> int:
|
||||||
"""L'année de début de l'année scolaire.
|
"""L'année de début de l'année scolaire.
|
||||||
Par exemple, 2022 si le semestre va de septebre 2022 à février 2023."""
|
Par exemple, 2022 si le semestre va de septembre 2022 à février 2023."""
|
||||||
return scu.annee_scolaire_debut(self.date_debut.year, self.date_debut.month)
|
return scu.annee_scolaire_debut(self.date_debut.year, self.date_debut.month)
|
||||||
|
|
||||||
def annee_scolaire_str(self):
|
def annee_scolaire_str(self):
|
||||||
@ -493,7 +552,9 @@ class FormSemestre(db.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def titre_annee(self) -> str:
|
def titre_annee(self) -> str:
|
||||||
""" """
|
"""Le titre avec l'année
|
||||||
|
'DUT Réseaux et Télécommunications semestre 3 FAP 2020-2021'
|
||||||
|
"""
|
||||||
titre_annee = (
|
titre_annee = (
|
||||||
f"{self.titre_num()} {self.modalite or ''} {self.date_debut.year}"
|
f"{self.titre_num()} {self.modalite or ''} {self.date_debut.year}"
|
||||||
)
|
)
|
||||||
@ -685,7 +746,7 @@ class FormSemestre(db.Model):
|
|||||||
|
|
||||||
def etud_validations_description_html(self, etudid: int) -> str:
|
def etud_validations_description_html(self, etudid: int) -> str:
|
||||||
"""Description textuelle des validations de jury de cet étudiant dans ce semestre"""
|
"""Description textuelle des validations de jury de cet étudiant dans ce semestre"""
|
||||||
from app.models.but_validations import ApcValidationRCUE, ApcValidationAnnee
|
from app.models.but_validations import ApcValidationAnnee, ApcValidationRCUE
|
||||||
|
|
||||||
vals_sem = ScolarFormSemestreValidation.query.filter_by(
|
vals_sem = ScolarFormSemestreValidation.query.filter_by(
|
||||||
etudid=etudid, formsemestre_id=self.id, ue_id=None
|
etudid=etudid, formsemestre_id=self.id, ue_id=None
|
||||||
|
@ -685,7 +685,7 @@ def EtatAbsences():
|
|||||||
|
|
||||||
</td></tr></table>
|
</td></tr></table>
|
||||||
</form>"""
|
</form>"""
|
||||||
% (scu.AnneeScolaire(), datetime.datetime.now().strftime("%d/%m/%Y")),
|
% (scu.annee_scolaire(), datetime.datetime.now().strftime("%d/%m/%Y")),
|
||||||
html_sco_header.sco_footer(),
|
html_sco_header.sco_footer(),
|
||||||
]
|
]
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
@ -719,15 +719,27 @@ def formChoixSemestreGroupe(all=False):
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_sco_year(year) -> int:
|
||||||
|
try:
|
||||||
|
year = int(year)
|
||||||
|
if year > 1900 and year < 2999:
|
||||||
|
return year
|
||||||
|
except:
|
||||||
|
raise ScoValueError("année scolaire invalide")
|
||||||
|
|
||||||
|
|
||||||
def CalAbs(etudid, sco_year=None):
|
def CalAbs(etudid, sco_year=None):
|
||||||
"""Calendrier des absences d'un etudiant"""
|
"""Calendrier des absences d'un etudiant"""
|
||||||
# crude portage from 1999 DTML
|
# crude portage from 1999 DTML
|
||||||
etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0]
|
etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0]
|
||||||
etudid = etud["etudid"]
|
etudid = etud["etudid"]
|
||||||
anneescolaire = int(scu.AnneeScolaire(sco_year))
|
if sco_year:
|
||||||
datedebut = str(anneescolaire) + "-08-01"
|
annee_scolaire = _convert_sco_year(sco_year)
|
||||||
datefin = str(anneescolaire + 1) + "-07-31"
|
else:
|
||||||
annee_courante = scu.AnneeScolaire()
|
annee_scolaire = scu.annee_scolaire()
|
||||||
|
datedebut = str(annee_scolaire) + "-08-01"
|
||||||
|
datefin = str(annee_scolaire + 1) + "-07-31"
|
||||||
|
annee_courante = scu.annee_scolaire()
|
||||||
nbabs = sco_abs.count_abs(etudid=etudid, debut=datedebut, fin=datefin)
|
nbabs = sco_abs.count_abs(etudid=etudid, debut=datedebut, fin=datefin)
|
||||||
nbabsjust = sco_abs.count_abs_just(etudid=etudid, debut=datedebut, fin=datefin)
|
nbabsjust = sco_abs.count_abs_just(etudid=etudid, debut=datedebut, fin=datefin)
|
||||||
events = []
|
events = []
|
||||||
@ -746,7 +758,7 @@ def CalAbs(etudid, sco_year=None):
|
|||||||
events.append(
|
events.append(
|
||||||
(str(a["jour"]), "X", "#8EA2C6", "", a["matin"], a["description"])
|
(str(a["jour"]), "X", "#8EA2C6", "", a["matin"], a["description"])
|
||||||
)
|
)
|
||||||
CalHTML = sco_abs.YearTable(anneescolaire, events=events, halfday=1)
|
CalHTML = sco_abs.YearTable(annee_scolaire, events=events, halfday=1)
|
||||||
|
|
||||||
#
|
#
|
||||||
H = [
|
H = [
|
||||||
@ -777,12 +789,12 @@ def CalAbs(etudid, sco_year=None):
|
|||||||
CalHTML,
|
CalHTML,
|
||||||
"""<form method="GET" action="CalAbs" name="f">""",
|
"""<form method="GET" action="CalAbs" name="f">""",
|
||||||
"""<input type="hidden" name="etudid" value="%s"/>""" % etudid,
|
"""<input type="hidden" name="etudid" value="%s"/>""" % etudid,
|
||||||
"""Année scolaire %s-%s""" % (anneescolaire, anneescolaire + 1),
|
"""Année scolaire %s-%s""" % (annee_scolaire, annee_scolaire + 1),
|
||||||
""" Changer année: <select name="sco_year" onchange="document.f.submit()">""",
|
""" Changer année: <select name="sco_year" onchange="document.f.submit()">""",
|
||||||
]
|
]
|
||||||
for y in range(annee_courante, min(annee_courante - 6, anneescolaire - 6), -1):
|
for y in range(annee_courante, min(annee_courante - 6, annee_scolaire - 6), -1):
|
||||||
H.append("""<option value="%s" """ % y)
|
H.append("""<option value="%s" """ % y)
|
||||||
if y == anneescolaire:
|
if y == annee_scolaire:
|
||||||
H.append("selected")
|
H.append("selected")
|
||||||
H.append(""">%s</option>""" % y)
|
H.append(""">%s</option>""" % y)
|
||||||
H.append("""</select></form>""")
|
H.append("""</select></form>""")
|
||||||
@ -811,7 +823,11 @@ def ListeAbsEtud(
|
|||||||
"""
|
"""
|
||||||
# si absjust_only, table absjust seule (export xls ou pdf)
|
# si absjust_only, table absjust seule (export xls ou pdf)
|
||||||
absjust_only = scu.to_bool(absjust_only)
|
absjust_only = scu.to_bool(absjust_only)
|
||||||
datedebut = "%s-08-01" % scu.AnneeScolaire(sco_year=sco_year)
|
if sco_year:
|
||||||
|
annee_scolaire = _convert_sco_year(sco_year)
|
||||||
|
else:
|
||||||
|
annee_scolaire = scu.annee_scolaire()
|
||||||
|
datedebut = f"{annee_scolaire}-{scu.MONTH_DEBUT_ANNEE_SCOLAIRE+1}-01"
|
||||||
etudid = etudid or False
|
etudid = etudid or False
|
||||||
etuds = sco_etud.get_etud_info(etudid=etudid, code_nip=code_nip, filled=True)
|
etuds = sco_etud.get_etud_info(etudid=etudid, code_nip=code_nip, filled=True)
|
||||||
if not etuds:
|
if not etuds:
|
||||||
|
@ -511,7 +511,7 @@ class ApoEtud(dict):
|
|||||||
# print 'comp_elt_annuel cur_sem=%s autre_sem=%s' % (cur_sem['formsemestre_id'], autre_sem['formsemestre_id'])
|
# print 'comp_elt_annuel cur_sem=%s autre_sem=%s' % (cur_sem['formsemestre_id'], autre_sem['formsemestre_id'])
|
||||||
if not cur_sem:
|
if not cur_sem:
|
||||||
# l'étudiant n'a pas de semestre courant ?!
|
# l'étudiant n'a pas de semestre courant ?!
|
||||||
log("comp_elt_annuel: etudid %s has no cur_sem" % etudid)
|
log(f"comp_elt_annuel: etudid {etudid} has no cur_sem")
|
||||||
return VOID_APO_RES
|
return VOID_APO_RES
|
||||||
cur_formsemestre = FormSemestre.query.get_or_404(cur_sem["formsemestre_id"])
|
cur_formsemestre = FormSemestre.query.get_or_404(cur_sem["formsemestre_id"])
|
||||||
cur_nt: NotesTableCompat = res_sem.load_formsemestre_results(cur_formsemestre)
|
cur_nt: NotesTableCompat = res_sem.load_formsemestre_results(cur_formsemestre)
|
||||||
@ -586,15 +586,10 @@ 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) # TODO à remplacer par ?
|
|
||||||
sco_formsemestre.sem_in_semestre_scolaire(
|
sco_formsemestre.sem_in_semestre_scolaire(
|
||||||
sem,
|
sem,
|
||||||
apo_data.annee_scolaire,
|
apo_data.annee_scolaire,
|
||||||
0,
|
0, # annee complete
|
||||||
# jour_pivot_annee,
|
|
||||||
# mois_pivot_annee,
|
|
||||||
# jour_pivot_periode,
|
|
||||||
# mois_pivot_periode
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -49,6 +49,7 @@ from app.scodoc import sco_groups
|
|||||||
from app.scodoc import sco_photos
|
from app.scodoc import sco_photos
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
|
from app.scodoc.sco_xml import quote_xml_attr
|
||||||
|
|
||||||
# -------- Bulletin en JSON
|
# -------- Bulletin en JSON
|
||||||
|
|
||||||
@ -129,12 +130,12 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
etudid=etudid,
|
etudid=etudid,
|
||||||
code_nip=etudinfo["code_nip"],
|
code_nip=etudinfo["code_nip"],
|
||||||
code_ine=etudinfo["code_ine"],
|
code_ine=etudinfo["code_ine"],
|
||||||
nom=scu.quote_xml_attr(etudinfo["nom"]),
|
nom=quote_xml_attr(etudinfo["nom"]),
|
||||||
prenom=scu.quote_xml_attr(etudinfo["prenom"]),
|
prenom=quote_xml_attr(etudinfo["prenom"]),
|
||||||
civilite=scu.quote_xml_attr(etudinfo["civilite_str"]),
|
civilite=quote_xml_attr(etudinfo["civilite_str"]),
|
||||||
photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(etudinfo, fast=True)),
|
photo_url=quote_xml_attr(sco_photos.etud_photo_url(etudinfo, fast=True)),
|
||||||
email=scu.quote_xml_attr(etudinfo["email"]),
|
email=quote_xml_attr(etudinfo["email"]),
|
||||||
emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
|
emailperso=quote_xml_attr(etudinfo["emailperso"]),
|
||||||
)
|
)
|
||||||
d["etudiant"]["sexe"] = d["etudiant"]["civilite"] # backward compat for our clients
|
d["etudiant"]["sexe"] = d["etudiant"]["civilite"] # backward compat for our clients
|
||||||
# Disponible pour publication ?
|
# Disponible pour publication ?
|
||||||
@ -209,9 +210,9 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
rang, effectif = nt.get_etud_ue_rang(ue["ue_id"], etudid)
|
rang, effectif = nt.get_etud_ue_rang(ue["ue_id"], etudid)
|
||||||
u = dict(
|
u = dict(
|
||||||
id=ue["ue_id"],
|
id=ue["ue_id"],
|
||||||
numero=scu.quote_xml_attr(ue["numero"]),
|
numero=quote_xml_attr(ue["numero"]),
|
||||||
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
acronyme=quote_xml_attr(ue["acronyme"]),
|
||||||
titre=scu.quote_xml_attr(ue["titre"]),
|
titre=quote_xml_attr(ue["titre"]),
|
||||||
note=dict(
|
note=dict(
|
||||||
value=scu.fmt_note(ue_status["cur_moy_ue"] if ue_status else ""),
|
value=scu.fmt_note(ue_status["cur_moy_ue"] if ue_status else ""),
|
||||||
min=scu.fmt_note(ue["min"]),
|
min=scu.fmt_note(ue["min"]),
|
||||||
@ -223,7 +224,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
rang=rang,
|
rang=rang,
|
||||||
effectif=effectif,
|
effectif=effectif,
|
||||||
ects=ects_txt,
|
ects=ects_txt,
|
||||||
code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
|
code_apogee=quote_xml_attr(ue["code_apogee"]),
|
||||||
)
|
)
|
||||||
d["ue"].append(u)
|
d["ue"].append(u)
|
||||||
u["module"] = []
|
u["module"] = []
|
||||||
@ -247,11 +248,11 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
code=mod["code"],
|
code=mod["code"],
|
||||||
coefficient=mod["coefficient"],
|
coefficient=mod["coefficient"],
|
||||||
numero=mod["numero"],
|
numero=mod["numero"],
|
||||||
titre=scu.quote_xml_attr(mod["titre"]),
|
titre=quote_xml_attr(mod["titre"]),
|
||||||
abbrev=scu.quote_xml_attr(mod["abbrev"]),
|
abbrev=quote_xml_attr(mod["abbrev"]),
|
||||||
# ects=ects, ects des modules maintenant inutilisés
|
# ects=ects, ects des modules maintenant inutilisés
|
||||||
note=dict(value=mod_moy),
|
note=dict(value=mod_moy),
|
||||||
code_apogee=scu.quote_xml_attr(mod["code_apogee"]),
|
code_apogee=quote_xml_attr(mod["code_apogee"]),
|
||||||
)
|
)
|
||||||
m["note"].update(modstat)
|
m["note"].update(modstat)
|
||||||
for k in ("min", "max", "moy"): # formatte toutes les notes
|
for k in ("min", "max", "moy"): # formatte toutes les notes
|
||||||
@ -291,7 +292,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
evaluation_id=e[
|
evaluation_id=e[
|
||||||
"evaluation_id"
|
"evaluation_id"
|
||||||
], # CM : ajout pour permettre de faire le lien sur les bulletins en ligne avec l'évaluation
|
], # CM : ajout pour permettre de faire le lien sur les bulletins en ligne avec l'évaluation
|
||||||
description=scu.quote_xml_attr(e["description"]),
|
description=quote_xml_attr(e["description"]),
|
||||||
note=val,
|
note=val,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -318,7 +319,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
e["heure_fin"], null_is_empty=True
|
e["heure_fin"], null_is_empty=True
|
||||||
),
|
),
|
||||||
coefficient=e["coefficient"],
|
coefficient=e["coefficient"],
|
||||||
description=scu.quote_xml_attr(e["description"]),
|
description=quote_xml_attr(e["description"]),
|
||||||
incomplete="1",
|
incomplete="1",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -332,9 +333,9 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
d["ue_capitalisee"].append(
|
d["ue_capitalisee"].append(
|
||||||
dict(
|
dict(
|
||||||
id=ue["ue_id"],
|
id=ue["ue_id"],
|
||||||
numero=scu.quote_xml_attr(ue["numero"]),
|
numero=quote_xml_attr(ue["numero"]),
|
||||||
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
acronyme=quote_xml_attr(ue["acronyme"]),
|
||||||
titre=scu.quote_xml_attr(ue["titre"]),
|
titre=quote_xml_attr(ue["titre"]),
|
||||||
note=scu.fmt_note(ue_status["moy"]),
|
note=scu.fmt_note(ue_status["moy"]),
|
||||||
coefficient_ue=scu.fmt_note(ue_status["coef_ue"]),
|
coefficient_ue=scu.fmt_note(ue_status["coef_ue"]),
|
||||||
date_capitalisation=ndb.DateDMYtoISO(ue_status["event_date"]),
|
date_capitalisation=ndb.DateDMYtoISO(ue_status["event_date"]),
|
||||||
@ -358,7 +359,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
for app in apprecs:
|
for app in apprecs:
|
||||||
d["appreciation"].append(
|
d["appreciation"].append(
|
||||||
dict(
|
dict(
|
||||||
comment=scu.quote_xml_attr(app["comment"]),
|
comment=quote_xml_attr(app["comment"]),
|
||||||
date=ndb.DateDMYtoISO(app["date"]),
|
date=ndb.DateDMYtoISO(app["date"]),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -53,7 +53,6 @@ from app.but.bulletin_but_xml_compat import bulletin_but_xml_compat
|
|||||||
from app.models.formsemestre import FormSemestre
|
from app.models.formsemestre import FormSemestre
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_abs
|
||||||
from app.scodoc import sco_codes_parcours
|
from app.scodoc import sco_codes_parcours
|
||||||
from app.scodoc import sco_cache
|
|
||||||
from app.scodoc import sco_edit_ue
|
from app.scodoc import sco_edit_ue
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
@ -62,6 +61,7 @@ from app.scodoc import sco_photos
|
|||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_xml
|
from app.scodoc import sco_xml
|
||||||
|
from app.scodoc.sco_xml import quote_xml_attr
|
||||||
|
|
||||||
# -------- Bulletin en XML
|
# -------- Bulletin en XML
|
||||||
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
|
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
|
||||||
@ -131,13 +131,13 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
etudid=str(etudid),
|
etudid=str(etudid),
|
||||||
code_nip=str(etudinfo["code_nip"]),
|
code_nip=str(etudinfo["code_nip"]),
|
||||||
code_ine=str(etudinfo["code_ine"]),
|
code_ine=str(etudinfo["code_ine"]),
|
||||||
nom=scu.quote_xml_attr(etudinfo["nom"]),
|
nom=quote_xml_attr(etudinfo["nom"]),
|
||||||
prenom=scu.quote_xml_attr(etudinfo["prenom"]),
|
prenom=quote_xml_attr(etudinfo["prenom"]),
|
||||||
civilite=scu.quote_xml_attr(etudinfo["civilite_str"]),
|
civilite=quote_xml_attr(etudinfo["civilite_str"]),
|
||||||
sexe=scu.quote_xml_attr(etudinfo["civilite_str"]), # compat
|
sexe=quote_xml_attr(etudinfo["civilite_str"]), # compat
|
||||||
photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(etudinfo)),
|
photo_url=quote_xml_attr(sco_photos.etud_photo_url(etudinfo)),
|
||||||
email=scu.quote_xml_attr(etudinfo["email"]),
|
email=quote_xml_attr(etudinfo["email"]),
|
||||||
emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
|
emailperso=quote_xml_attr(etudinfo["emailperso"]),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -210,10 +210,10 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
x_ue = Element(
|
x_ue = Element(
|
||||||
"ue",
|
"ue",
|
||||||
id=str(ue["ue_id"]),
|
id=str(ue["ue_id"]),
|
||||||
numero=scu.quote_xml_attr(ue["numero"]),
|
numero=quote_xml_attr(ue["numero"]),
|
||||||
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
acronyme=quote_xml_attr(ue["acronyme"]),
|
||||||
titre=scu.quote_xml_attr(ue["titre"]),
|
titre=quote_xml_attr(ue["titre"]),
|
||||||
code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
|
code_apogee=quote_xml_attr(ue["code_apogee"]),
|
||||||
)
|
)
|
||||||
doc.append(x_ue)
|
doc.append(x_ue)
|
||||||
if ue["type"] != sco_codes_parcours.UE_SPORT:
|
if ue["type"] != sco_codes_parcours.UE_SPORT:
|
||||||
@ -255,9 +255,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
code=str(mod["code"] or ""),
|
code=str(mod["code"] or ""),
|
||||||
coefficient=str(mod["coefficient"]),
|
coefficient=str(mod["coefficient"]),
|
||||||
numero=str(mod["numero"]),
|
numero=str(mod["numero"]),
|
||||||
titre=scu.quote_xml_attr(mod["titre"]),
|
titre=quote_xml_attr(mod["titre"]),
|
||||||
abbrev=scu.quote_xml_attr(mod["abbrev"]),
|
abbrev=quote_xml_attr(mod["abbrev"]),
|
||||||
code_apogee=scu.quote_xml_attr(mod["code_apogee"])
|
code_apogee=quote_xml_attr(mod["code_apogee"])
|
||||||
# ects=ects ects des modules maintenant inutilisés
|
# ects=ects ects des modules maintenant inutilisés
|
||||||
)
|
)
|
||||||
x_ue.append(x_mod)
|
x_ue.append(x_mod)
|
||||||
@ -302,7 +302,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
),
|
),
|
||||||
coefficient=str(e["coefficient"]),
|
coefficient=str(e["coefficient"]),
|
||||||
evaluation_type=str(e["evaluation_type"]),
|
evaluation_type=str(e["evaluation_type"]),
|
||||||
description=scu.quote_xml_attr(e["description"]),
|
description=quote_xml_attr(e["description"]),
|
||||||
# notes envoyées sur 20, ceci juste pour garder trace:
|
# notes envoyées sur 20, ceci juste pour garder trace:
|
||||||
note_max_origin=str(e["note_max"]),
|
note_max_origin=str(e["note_max"]),
|
||||||
)
|
)
|
||||||
@ -333,7 +333,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
e["heure_fin"], null_is_empty=True
|
e["heure_fin"], null_is_empty=True
|
||||||
),
|
),
|
||||||
coefficient=str(e["coefficient"]),
|
coefficient=str(e["coefficient"]),
|
||||||
description=scu.quote_xml_attr(e["description"]),
|
description=quote_xml_attr(e["description"]),
|
||||||
incomplete="1",
|
incomplete="1",
|
||||||
# notes envoyées sur 20, ceci juste pour garder trace:
|
# notes envoyées sur 20, ceci juste pour garder trace:
|
||||||
note_max_origin=str(e["note_max"] or ""),
|
note_max_origin=str(e["note_max"] or ""),
|
||||||
@ -348,9 +348,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
x_ue = Element(
|
x_ue = Element(
|
||||||
"ue_capitalisee",
|
"ue_capitalisee",
|
||||||
id=str(ue["ue_id"]),
|
id=str(ue["ue_id"]),
|
||||||
numero=scu.quote_xml_attr(ue["numero"]),
|
numero=quote_xml_attr(ue["numero"]),
|
||||||
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
acronyme=quote_xml_attr(ue["acronyme"]),
|
||||||
titre=scu.quote_xml_attr(ue["titre"]),
|
titre=quote_xml_attr(ue["titre"]),
|
||||||
)
|
)
|
||||||
doc.append(x_ue)
|
doc.append(x_ue)
|
||||||
x_ue.append(Element("note", value=scu.fmt_note(ue_status["moy"])))
|
x_ue.append(Element("note", value=scu.fmt_note(ue_status["moy"])))
|
||||||
@ -383,7 +383,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
x_situation = Element("situation")
|
x_situation = Element("situation")
|
||||||
x_situation.text = scu.quote_xml_attr(infos["situation"])
|
x_situation.text = quote_xml_attr(infos["situation"])
|
||||||
doc.append(x_situation)
|
doc.append(x_situation)
|
||||||
if dpv:
|
if dpv:
|
||||||
decision = dpv["decisions"][0]
|
decision = dpv["decisions"][0]
|
||||||
@ -418,9 +418,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
Element(
|
Element(
|
||||||
"decision_ue",
|
"decision_ue",
|
||||||
ue_id=str(ue["ue_id"]),
|
ue_id=str(ue["ue_id"]),
|
||||||
numero=scu.quote_xml_attr(ue["numero"]),
|
numero=quote_xml_attr(ue["numero"]),
|
||||||
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
acronyme=quote_xml_attr(ue["acronyme"]),
|
||||||
titre=scu.quote_xml_attr(ue["titre"]),
|
titre=quote_xml_attr(ue["titre"]),
|
||||||
code=decision["decisions_ue"][ue_id]["code"],
|
code=decision["decisions_ue"][ue_id]["code"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -443,7 +443,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
"appreciation",
|
"appreciation",
|
||||||
date=ndb.DateDMYtoISO(appr["date"]),
|
date=ndb.DateDMYtoISO(appr["date"]),
|
||||||
)
|
)
|
||||||
x_appr.text = scu.quote_xml_attr(appr["comment"])
|
x_appr.text = quote_xml_attr(appr["comment"])
|
||||||
doc.append(x_appr)
|
doc.append(x_appr)
|
||||||
|
|
||||||
if is_appending:
|
if is_appending:
|
||||||
|
@ -137,7 +137,7 @@ class DataEtudiant(object):
|
|||||||
self.data_apogee = None
|
self.data_apogee = None
|
||||||
self.data_scodoc = None
|
self.data_scodoc = None
|
||||||
self.etapes = set() # l'ensemble des étapes où il est inscrit
|
self.etapes = set() # l'ensemble des étapes où il est inscrit
|
||||||
self.semestres = set() # l'ensemble des semestres où il est inscrit
|
self.semestres = set() # l'ensemble des formsemestre_id où il est inscrit
|
||||||
self.tags = set() # les anomalies relevées
|
self.tags = set() # les anomalies relevées
|
||||||
self.ind_row = "-" # là où il compte dans les effectifs (ligne et colonne)
|
self.ind_row = "-" # là où il compte dans les effectifs (ligne et colonne)
|
||||||
self.ind_col = "-"
|
self.ind_col = "-"
|
||||||
@ -145,8 +145,8 @@ class DataEtudiant(object):
|
|||||||
def add_etape(self, etape):
|
def add_etape(self, etape):
|
||||||
self.etapes.add(etape)
|
self.etapes.add(etape)
|
||||||
|
|
||||||
def add_semestre(self, semestre):
|
def add_semestre(self, formsemestre_id: int):
|
||||||
self.semestres.add(semestre)
|
self.semestres.add(formsemestre_id)
|
||||||
|
|
||||||
def set_apogee(self, data_apogee):
|
def set_apogee(self, data_apogee):
|
||||||
self.data_apogee = data_apogee
|
self.data_apogee = data_apogee
|
||||||
@ -231,25 +231,30 @@ def entete_liste_etudiant():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class EtapeBilan(object):
|
class EtapeBilan:
|
||||||
"""
|
"""
|
||||||
Structure de donnée représentation l'état global de la comparaison ScoDoc/Apogée
|
Structure de donnée représentation l'état global de la comparaison ScoDoc/Apogée
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.semestres = (
|
self.semestres = {}
|
||||||
{}
|
"Dictionnaire des formsemestres du semset (formsemestre_id -> semestre)"
|
||||||
) # Dictionnaire des formsemestres du semset (formsemestre_id -> semestre)
|
|
||||||
self.etapes = [] # Liste des étapes apogées du semset (clé_apogée)
|
self.etapes = [] # Liste des étapes apogées du semset (clé_apogée)
|
||||||
# pour les descriptions qui suivents:
|
# pour les descriptions qui suivent:
|
||||||
# cle_etu = nip si non vide, sinon etudid
|
# cle_etu = nip si non vide, sinon etudid
|
||||||
# data_etu = { nip, etudid, data_apogee, data_scodoc }
|
# data_etu = { nip, etudid, data_apogee, data_scodoc }
|
||||||
self.etudiants = {} # cle_etu -> data_etu
|
self.etudiants = {}
|
||||||
self.keys_etu = {} # nip -> [ etudid* ]
|
"cle_etu -> data_etu"
|
||||||
self.etu_semestre = {} # semestre -> { key_etu }
|
self.keys_etu = {}
|
||||||
self.etu_etapes = {} # etape -> { key_etu }
|
"nip -> [ etudid* ]"
|
||||||
self.repartition = {} # (ind_row, ind_col) -> nombre d étudiants
|
self.etu_semestre = {}
|
||||||
self.tag_count = {} # nombre d'animalies détectées (par type d'anomalie)
|
"semestre -> { key_etu }"
|
||||||
|
self.etu_etapes = {}
|
||||||
|
"etape -> { key_etu }"
|
||||||
|
self.repartition = {}
|
||||||
|
"(ind_row, ind_col) -> nombre d étudiants"
|
||||||
|
self.tag_count = {}
|
||||||
|
"nombre d'anomalies détectées (par type d'anomalie)"
|
||||||
|
|
||||||
# on collectionne les indicatifs trouvés pour n'afficher que les indicatifs 'utiles'
|
# on collectionne les indicatifs trouvés pour n'afficher que les indicatifs 'utiles'
|
||||||
self.indicatifs = {}
|
self.indicatifs = {}
|
||||||
@ -273,7 +278,8 @@ class EtapeBilan(object):
|
|||||||
self.tag_count[tag] = 0
|
self.tag_count[tag] = 0
|
||||||
self.tag_count[tag] += 1
|
self.tag_count[tag] += 1
|
||||||
|
|
||||||
def set_indicatif(self, item, as_row): # item = semestre ou key_etape
|
def set_indicatif(self, item, as_row):
|
||||||
|
"""item = semestre ou key_etape"""
|
||||||
if as_row:
|
if as_row:
|
||||||
indicatif = "R" + chr(self.top_row + 97)
|
indicatif = "R" + chr(self.top_row + 97)
|
||||||
self.all_rows_ind.append(indicatif)
|
self.all_rows_ind.append(indicatif)
|
||||||
@ -288,7 +294,7 @@ class EtapeBilan(object):
|
|||||||
if self.top_col > 26:
|
if self.top_col > 26:
|
||||||
log("Dépassement (plus de 26 étapes dans la table diagnostic")
|
log("Dépassement (plus de 26 étapes dans la table diagnostic")
|
||||||
|
|
||||||
def add_sem(self, semestre):
|
def add_sem(self, sem: dict):
|
||||||
"""
|
"""
|
||||||
Prise en compte d'un semestre dans le bilan.
|
Prise en compte d'un semestre dans le bilan.
|
||||||
* ajoute le semestre et les étudiants du semestre
|
* ajoute le semestre et les étudiants du semestre
|
||||||
@ -296,16 +302,16 @@ class EtapeBilan(object):
|
|||||||
:param semestre: Le semestre à prendre en compte
|
:param semestre: Le semestre à prendre en compte
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
self.semestres[semestre["formsemestre_id"]] = semestre
|
self.semestres[sem["formsemestre_id"]] = sem
|
||||||
# if anneeapogee == None: # année d'inscription par défaut
|
# if anneeapogee == None: # année d'inscription par défaut
|
||||||
anneeapogee = str(
|
annee_apogee = str(
|
||||||
annee_scolaire_debut(semestre["annee_debut"], semestre["mois_debut_ord"])
|
annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])
|
||||||
)
|
)
|
||||||
self.set_indicatif(semestre["formsemestre_id"], True)
|
self.set_indicatif(sem["formsemestre_id"], True)
|
||||||
for etape in semestre["etapes"]:
|
for etape in sem["etapes"]:
|
||||||
self.add_etape(etape.etape_vdi, anneeapogee)
|
self.add_etape(etape.etape_vdi, annee_apogee)
|
||||||
|
|
||||||
def add_etape(self, etape_str, anneeapogee):
|
def add_etape(self, etape_str, annee_apogee):
|
||||||
"""
|
"""
|
||||||
Prise en compte d'une étape apogée
|
Prise en compte d'une étape apogée
|
||||||
:param etape_str: La clé de l'étape à prendre en compte
|
:param etape_str: La clé de l'étape à prendre en compte
|
||||||
@ -313,7 +319,7 @@ class EtapeBilan(object):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if etape_str != "":
|
if etape_str != "":
|
||||||
key_etape = etape_to_key(anneeapogee, etape_str)
|
key_etape = etape_to_key(annee_apogee, etape_str)
|
||||||
if key_etape not in self.etapes:
|
if key_etape not in self.etapes:
|
||||||
self.etapes.append(key_etape)
|
self.etapes.append(key_etape)
|
||||||
self.set_indicatif(
|
self.set_indicatif(
|
||||||
@ -367,7 +373,7 @@ class EtapeBilan(object):
|
|||||||
self.etudiants[key_etu].add_etape(etape)
|
self.etudiants[key_etu].add_etape(etape)
|
||||||
return key_etu
|
return key_etu
|
||||||
|
|
||||||
def register_etud_scodoc(self, etud, semestre):
|
def register_etud_scodoc(self, etud: dict, sem: dict):
|
||||||
"""
|
"""
|
||||||
Enregistrement de l'étudiant par rapport à son semestre
|
Enregistrement de l'étudiant par rapport à son semestre
|
||||||
:param etud: Les données de l'étudiant
|
:param etud: Les données de l'étudiant
|
||||||
@ -380,10 +386,10 @@ class EtapeBilan(object):
|
|||||||
if key_etu not in self.etudiants:
|
if key_etu not in self.etudiants:
|
||||||
data = DataEtudiant(nip, etudid)
|
data = DataEtudiant(nip, etudid)
|
||||||
data.set_scodoc(etud)
|
data.set_scodoc(etud)
|
||||||
data.add_semestre(semestre)
|
data.add_semestre(sem)
|
||||||
self.etudiants[key_etu] = data
|
self.etudiants[key_etu] = data
|
||||||
else:
|
else:
|
||||||
self.etudiants[key_etu].add_semestre(semestre)
|
self.etudiants[key_etu].add_semestre(sem)
|
||||||
return key_etu
|
return key_etu
|
||||||
|
|
||||||
def load_listes(self):
|
def load_listes(self):
|
||||||
@ -393,12 +399,12 @@ class EtapeBilan(object):
|
|||||||
* Puis pour toutes les étapes
|
* Puis pour toutes les étapes
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
for semestre in self.semestres:
|
for formsemestre_id, sem in self.semestres.items():
|
||||||
etuds = self.semestres[semestre]["etuds"]
|
etuds = sem["etuds"]
|
||||||
self.etu_semestre[semestre] = set()
|
self.etu_semestre[formsemestre_id] = set()
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
key_etu = self.register_etud_scodoc(etud, semestre)
|
key_etu = self.register_etud_scodoc(etud, formsemestre_id)
|
||||||
self.etu_semestre[semestre].add(key_etu)
|
self.etu_semestre[formsemestre_id].add(key_etu)
|
||||||
|
|
||||||
for key_etape in self.etapes:
|
for key_etape in self.etapes:
|
||||||
anneeapogee, etapestr = key_to_values(key_etape)
|
anneeapogee, etapestr = key_to_values(key_etape)
|
||||||
@ -426,17 +432,17 @@ class EtapeBilan(object):
|
|||||||
self.repartition[ROW_CUMUL, self.indicatifs[key_etape]] = 0
|
self.repartition[ROW_CUMUL, self.indicatifs[key_etape]] = 0
|
||||||
|
|
||||||
# recherche des nip identiques
|
# recherche des nip identiques
|
||||||
for nip in self.keys_etu:
|
for nip, keys_etu_nip in self.keys_etu.items():
|
||||||
if nip != "":
|
if nip != "":
|
||||||
nbnips = len(self.keys_etu[nip])
|
nbnips = len(keys_etu_nip)
|
||||||
if nbnips > 1:
|
if nbnips > 1:
|
||||||
for i, etudid in enumerate(self.keys_etu[nip]):
|
for i, etudid in enumerate(keys_etu_nip):
|
||||||
data_etu = self.etudiants[nip, etudid]
|
data_etu = self.etudiants[nip, etudid]
|
||||||
data_etu.add_tag(NIP_NON_UNIQUE)
|
data_etu.add_tag(NIP_NON_UNIQUE)
|
||||||
data_etu.nip = data_etu.nip + " (%d/%d)" % (i + 1, nbnips)
|
data_etu.nip = data_etu.nip + f" ({i+1}/{nbnips})"
|
||||||
self.inc_tag_count(NIP_NON_UNIQUE)
|
self.inc_tag_count(NIP_NON_UNIQUE)
|
||||||
for nip in self.keys_etu:
|
for nip, keys_etu_nip in self.keys_etu.items():
|
||||||
for etudid in self.keys_etu[nip]:
|
for etudid in keys_etu_nip:
|
||||||
key_etu = (nip, etudid)
|
key_etu = (nip, etudid)
|
||||||
data_etu = self.etudiants[key_etu]
|
data_etu = self.etudiants[key_etu]
|
||||||
ind_col = "-"
|
ind_col = "-"
|
||||||
@ -504,7 +510,7 @@ class EtapeBilan(object):
|
|||||||
if (ind_row, ind_col) in self.repartition:
|
if (ind_row, ind_col) in self.repartition:
|
||||||
count = self.repartition[ind_row, ind_col]
|
count = self.repartition[ind_row, ind_col]
|
||||||
if count > 1:
|
if count > 1:
|
||||||
comptage = "(%d étudiants)" % count
|
comptage = f"({count} étudiants)"
|
||||||
else:
|
else:
|
||||||
comptage = "(1 étudiant)"
|
comptage = "(1 étudiant)"
|
||||||
else:
|
else:
|
||||||
|
@ -939,7 +939,18 @@ def fill_etuds_info(etuds: list[dict], add_admission=True):
|
|||||||
|
|
||||||
|
|
||||||
def etud_inscriptions_infos(etudid: int, ne="") -> dict:
|
def etud_inscriptions_infos(etudid: int, ne="") -> dict:
|
||||||
"""Dict avec les informations sur les semestres passés et courant"""
|
"""Dict avec les informations sur les semestres passés et courant.
|
||||||
|
{
|
||||||
|
"sems" : ,
|
||||||
|
"ins" : ,
|
||||||
|
"cursem" : ,
|
||||||
|
"inscription" : ,
|
||||||
|
"inscriptionstr" : ,
|
||||||
|
"inscription_formsemestre_id" : ,
|
||||||
|
"etatincursem" : ,
|
||||||
|
"situation" : ,
|
||||||
|
}
|
||||||
|
"""
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
|
|
||||||
|
@ -27,26 +27,23 @@
|
|||||||
|
|
||||||
"""Operations de base sur les formsemestres
|
"""Operations de base sur les formsemestres
|
||||||
"""
|
"""
|
||||||
from operator import itemgetter
|
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
|
from operator import itemgetter
|
||||||
|
|
||||||
from flask import g, request
|
from flask import g, request, url_for
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import log
|
|
||||||
from app.models import Departement
|
|
||||||
|
|
||||||
from app.scodoc import sco_codes_parcours
|
|
||||||
from app.scodoc import sco_cache
|
|
||||||
from app.scodoc import sco_formations
|
|
||||||
from app.scodoc import sco_preferences
|
|
||||||
from app.scodoc.gen_tables import GenTable
|
|
||||||
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
|
||||||
from app.scodoc.sco_exceptions import ScoValueError, ScoInvalidIdType
|
|
||||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
|
from app import log
|
||||||
|
from app.models import Departement
|
||||||
|
from app.models import FormSemestre
|
||||||
|
from app.scodoc import sco_cache, sco_codes_parcours, sco_formations, sco_preferences
|
||||||
|
from app.scodoc.gen_tables import GenTable
|
||||||
|
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
||||||
|
from app.scodoc.sco_exceptions import ScoInvalidIdType, ScoValueError
|
||||||
|
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||||
|
|
||||||
_formsemestreEditor = ndb.EditableTable(
|
_formsemestreEditor = ndb.EditableTable(
|
||||||
"notes_formsemestre",
|
"notes_formsemestre",
|
||||||
@ -82,11 +79,9 @@ _formsemestreEditor = ndb.EditableTable(
|
|||||||
"date_debut": ndb.DateDMYtoISO,
|
"date_debut": ndb.DateDMYtoISO,
|
||||||
"date_fin": ndb.DateDMYtoISO,
|
"date_fin": ndb.DateDMYtoISO,
|
||||||
"etat": bool,
|
"etat": bool,
|
||||||
"gestion_compensation": bool,
|
|
||||||
"bul_hide_xml": bool,
|
"bul_hide_xml": bool,
|
||||||
"block_moyennes": bool,
|
"block_moyennes": bool,
|
||||||
"block_moyenne_generale": bool,
|
"block_moyenne_generale": bool,
|
||||||
"gestion_semestrielle": bool,
|
|
||||||
"gestion_compensation": bool,
|
"gestion_compensation": bool,
|
||||||
"gestion_semestrielle": bool,
|
"gestion_semestrielle": bool,
|
||||||
"resp_can_edit": bool,
|
"resp_can_edit": bool,
|
||||||
@ -99,7 +94,7 @@ _formsemestreEditor = ndb.EditableTable(
|
|||||||
def get_formsemestre(formsemestre_id, raise_soft_exc=False):
|
def get_formsemestre(formsemestre_id, raise_soft_exc=False):
|
||||||
"list ONE formsemestre"
|
"list ONE formsemestre"
|
||||||
if formsemestre_id is None:
|
if formsemestre_id is None:
|
||||||
raise ValueError(f"get_formsemestre: id manquant")
|
raise ValueError("get_formsemestre: id manquant")
|
||||||
if formsemestre_id in g.stored_get_formsemestre:
|
if formsemestre_id in g.stored_get_formsemestre:
|
||||||
return g.stored_get_formsemestre[formsemestre_id]
|
return g.stored_get_formsemestre[formsemestre_id]
|
||||||
if not isinstance(formsemestre_id, int):
|
if not isinstance(formsemestre_id, int):
|
||||||
@ -107,7 +102,7 @@ def get_formsemestre(formsemestre_id, raise_soft_exc=False):
|
|||||||
raise ScoInvalidIdType("get_formsemestre: formsemestre_id must be an integer !")
|
raise ScoInvalidIdType("get_formsemestre: formsemestre_id must be an integer !")
|
||||||
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
|
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
|
||||||
if not sems:
|
if not sems:
|
||||||
log("get_formsemestre: invalid formsemestre_id (%s)" % formsemestre_id)
|
log(f"get_formsemestre: invalid formsemestre_id ({formsemestre_id})")
|
||||||
if raise_soft_exc:
|
if raise_soft_exc:
|
||||||
raise ScoValueError(f"semestre {formsemestre_id} inconnu !")
|
raise ScoValueError(f"semestre {formsemestre_id} inconnu !")
|
||||||
else:
|
else:
|
||||||
@ -240,8 +235,8 @@ def etapes_apo_str(etapes):
|
|||||||
|
|
||||||
def do_formsemestre_create(args, silent=False):
|
def do_formsemestre_create(args, silent=False):
|
||||||
"create a formsemestre"
|
"create a formsemestre"
|
||||||
from app.scodoc import sco_groups
|
|
||||||
from app.models import ScolarNews
|
from app.models import ScolarNews
|
||||||
|
from app.scodoc import sco_groups
|
||||||
|
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
formsemestre_id = _formsemestreEditor.create(cnx, args)
|
formsemestre_id = _formsemestreEditor.create(cnx, args)
|
||||||
@ -422,97 +417,46 @@ def sem_set_responsable_name(sem):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_periode(
|
|
||||||
debut: datetime,
|
|
||||||
jour_pivot_annee=1,
|
|
||||||
mois_pivot_annee=8,
|
|
||||||
jour_pivot_periode=1,
|
|
||||||
mois_pivot_periode=12,
|
|
||||||
):
|
|
||||||
"""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 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
|
|
||||||
"""
|
|
||||||
"""Implementation
|
|
||||||
Cas à considérer pour le calcul de la période
|
|
||||||
|
|
||||||
pa < pp -----------------|-------------------|---------------->
|
|
||||||
(A-1, P:2) pa (A, P:1) pp (A, P:2)
|
|
||||||
pp < pa -----------------|-------------------|---------------->
|
|
||||||
(A-1, P:1) pp (A-1, P:2) pa (A, P:1)
|
|
||||||
"""
|
|
||||||
pa = 100 * mois_pivot_annee + jour_pivot_annee
|
|
||||||
pp = 100 * mois_pivot_periode + jour_pivot_periode
|
|
||||||
ps = 100 * debut.month + debut.day
|
|
||||||
if ps < pa:
|
|
||||||
annee = debut.year - 1
|
|
||||||
else:
|
|
||||||
annee = debut.year
|
|
||||||
if pa < pp:
|
|
||||||
if ps < pa or ps > pp:
|
|
||||||
periode = 2
|
|
||||||
else:
|
|
||||||
periode = 1
|
|
||||||
else:
|
|
||||||
if ps < pp or ps > pa:
|
|
||||||
periode = 1
|
|
||||||
else:
|
|
||||||
periode = 2
|
|
||||||
return annee, periode
|
|
||||||
|
|
||||||
|
|
||||||
def sem_in_semestre_scolaire(
|
def sem_in_semestre_scolaire(
|
||||||
sem,
|
sem,
|
||||||
year=False,
|
year=False,
|
||||||
periode=None,
|
periode=None,
|
||||||
jour_pivot_annee=1,
|
mois_pivot_annee=scu.MONTH_DEBUT_ANNEE_SCOLAIRE,
|
||||||
mois_pivot_annee=8,
|
mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
|
||||||
jour_pivot_periode=1,
|
) -> bool:
|
||||||
mois_pivot_periode=12,
|
"""Vrai si la date du début du semestre est dans la période indiquée (1,2,0)
|
||||||
):
|
du semestre `periode` de l'année scolaire indiquée
|
||||||
"""n'utilise que la date de debut,
|
(ou, à défaut, de celle en cours).
|
||||||
si annee non specifiée, année scolaire courante
|
|
||||||
la période garde les même convention que semset["sem_id"];
|
La période utilise les même conventions que semset["sem_id"];
|
||||||
* 1 : premère période
|
* 1 : première période
|
||||||
* 2 : deuxième période
|
* 2 : deuxième période
|
||||||
* 0 ou periode non précisée: annualisé (donc inclut toutes les périodes)
|
* 0 ou période non précisée: annualisé (donc inclut toutes les périodes)
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
if not year:
|
if not year:
|
||||||
year = scu.AnneeScolaire()
|
year = scu.annee_scolaire()
|
||||||
# calcule l'année universitaire et la periode
|
# n'utilise pas le jour pivot
|
||||||
sem_annee, sem_periode = get_periode(
|
jour_pivot_annee = jour_pivot_periode = 1
|
||||||
|
# calcule l'année universitaire et la période
|
||||||
|
sem_annee, sem_periode = FormSemestre.comp_periode(
|
||||||
datetime.datetime.fromisoformat(sem["date_debut_iso"]),
|
datetime.datetime.fromisoformat(sem["date_debut_iso"]),
|
||||||
jour_pivot_annee,
|
|
||||||
mois_pivot_annee,
|
mois_pivot_annee,
|
||||||
jour_pivot_periode,
|
|
||||||
mois_pivot_periode,
|
mois_pivot_periode,
|
||||||
|
jour_pivot_annee,
|
||||||
|
jour_pivot_periode,
|
||||||
)
|
)
|
||||||
if periode is None or periode == 0:
|
if periode is None or periode == 0:
|
||||||
return sem_annee == year
|
return sem_annee == year
|
||||||
else:
|
return sem_annee == year and sem_periode == periode
|
||||||
return sem_annee == year and sem_periode == periode
|
|
||||||
|
|
||||||
|
|
||||||
# def sem_in_annee_scolaire(sem, year=False):
|
def sem_in_annee_scolaire(sem, year=False):
|
||||||
# """Test si sem appartient à l'année scolaire year (int).
|
"""Test si sem appartient à l'année scolaire year (int).
|
||||||
# N'utilise que la date de début, pivot au 1er août.
|
N'utilise que la date de début, pivot au 1er août.
|
||||||
# Si année non specifiée, année scolaire courante
|
Si année non specifiée, année scolaire courante
|
||||||
# """
|
"""
|
||||||
# if not year:
|
return sem_in_semestre_scolaire(sem, year, periode=0)
|
||||||
# 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
|
||||||
@ -520,7 +464,7 @@ def sem_est_courant(sem): # -> FormSemestre.est_courant
|
|||||||
now = time.strftime("%Y-%m-%d")
|
now = time.strftime("%Y-%m-%d")
|
||||||
debut = ndb.DateDMYtoISO(sem["date_debut"])
|
debut = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
fin = ndb.DateDMYtoISO(sem["date_fin"])
|
fin = ndb.DateDMYtoISO(sem["date_fin"])
|
||||||
return (debut <= now) and (now <= fin)
|
return debut <= now <= fin
|
||||||
|
|
||||||
|
|
||||||
def scodoc_get_all_unlocked_sems():
|
def scodoc_get_all_unlocked_sems():
|
||||||
@ -540,7 +484,7 @@ def scodoc_get_all_unlocked_sems():
|
|||||||
|
|
||||||
|
|
||||||
def table_formsemestres(
|
def table_formsemestres(
|
||||||
sems,
|
sems: list[dict],
|
||||||
columns_ids=(),
|
columns_ids=(),
|
||||||
sup_columns_ids=(),
|
sup_columns_ids=(),
|
||||||
html_title="<h2>Semestres</h2>",
|
html_title="<h2>Semestres</h2>",
|
||||||
@ -549,8 +493,10 @@ def table_formsemestres(
|
|||||||
"""Une table presentant des semestres"""
|
"""Une table presentant des semestres"""
|
||||||
for sem in sems:
|
for sem in sems:
|
||||||
sem_set_responsable_name(sem)
|
sem_set_responsable_name(sem)
|
||||||
sem["_titre_num_target"] = (
|
sem["_titre_num_target"] = url_for(
|
||||||
"formsemestre_status?formsemestre_id=%s" % sem["formsemestre_id"]
|
"notes.formsemestre_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=sem["formsemestre_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not columns_ids:
|
if not columns_ids:
|
||||||
@ -592,8 +538,10 @@ def table_formsemestres(
|
|||||||
return tab
|
return tab
|
||||||
|
|
||||||
|
|
||||||
def list_formsemestre_by_etape(etape_apo=False, annee_scolaire=False):
|
def list_formsemestre_by_etape(etape_apo=False, annee_scolaire=False) -> list[dict]:
|
||||||
"""Liste des semestres de cette etape, pour l'annee scolaire indiquée (sinon, pour toutes)"""
|
"""Liste des semestres de cette etape,
|
||||||
|
pour l'annee scolaire indiquée (sinon, pour toutes).
|
||||||
|
"""
|
||||||
ds = {} # formsemestre_id : sem
|
ds = {} # formsemestre_id : sem
|
||||||
if etape_apo:
|
if etape_apo:
|
||||||
sems = do_formsemestre_list(args={"etape_apo": etape_apo})
|
sems = do_formsemestre_list(args={"etape_apo": etape_apo})
|
||||||
@ -618,14 +566,12 @@ def list_formsemestre_by_etape(etape_apo=False, annee_scolaire=False):
|
|||||||
def view_formsemestre_by_etape(etape_apo=None, format="html"):
|
def view_formsemestre_by_etape(etape_apo=None, format="html"):
|
||||||
"""Affiche table des semestres correspondants à l'étape"""
|
"""Affiche table des semestres correspondants à l'étape"""
|
||||||
if etape_apo:
|
if etape_apo:
|
||||||
html_title = (
|
html_title = f"""<h2>Semestres courants de l'étape <tt>{etape_apo}</tt></h2>"""
|
||||||
"""<h2>Semestres courants de l'étape <tt>%s</tt></h2>""" % etape_apo
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
html_title = """<h2>Semestres courants</h2>"""
|
html_title = """<h2>Semestres courants</h2>"""
|
||||||
tab = table_formsemestres(
|
tab = table_formsemestres(
|
||||||
list_formsemestre_by_etape(
|
list_formsemestre_by_etape(
|
||||||
etape_apo=etape_apo, annee_scolaire=scu.AnneeScolaire()
|
etape_apo=etape_apo, annee_scolaire=scu.annee_scolaire()
|
||||||
),
|
),
|
||||||
html_title=html_title,
|
html_title=html_title,
|
||||||
html_next_section="""<form action="view_formsemestre_by_etape">
|
html_next_section="""<form action="view_formsemestre_by_etape">
|
||||||
|
@ -40,13 +40,11 @@ sem_set_list()
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import g
|
|
||||||
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_cache
|
|
||||||
from app.scodoc import sco_etape_apogee
|
from app.scodoc import sco_etape_apogee
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_status
|
from app.scodoc import sco_formsemestre_status
|
||||||
@ -77,6 +75,7 @@ semset_delete = _semset_editor.delete
|
|||||||
class SemSet(dict):
|
class SemSet(dict):
|
||||||
def __init__(self, semset_id=None, title="", annee_scolaire="", sem_id=""):
|
def __init__(self, semset_id=None, title="", annee_scolaire="", sem_id=""):
|
||||||
"""Load and init, or, if semset_id is not specified, create"""
|
"""Load and init, or, if semset_id is not specified, create"""
|
||||||
|
super().__init__()
|
||||||
if not annee_scolaire and not semset_id:
|
if not annee_scolaire and not semset_id:
|
||||||
# on autorise annee_scolaire null si sem_id pour pouvoir lire les anciens semsets
|
# on autorise annee_scolaire null si sem_id pour pouvoir lire les anciens semsets
|
||||||
# mal construits...
|
# mal construits...
|
||||||
@ -491,7 +490,7 @@ def semset_page(format="html"):
|
|||||||
]
|
]
|
||||||
H.append(tab.html())
|
H.append(tab.html())
|
||||||
|
|
||||||
annee_courante = int(scu.AnneeScolaire())
|
annee_courante = int(scu.annee_scolaire())
|
||||||
menu_annee = "\n".join(
|
menu_annee = "\n".join(
|
||||||
[
|
[
|
||||||
'<option value="%s">%s</option>' % (i, i)
|
'<option value="%s">%s</option>' % (i, i)
|
||||||
|
@ -58,9 +58,7 @@ from werkzeug.http import HTTP_STATUS_CODES
|
|||||||
from config import Config
|
from config import Config
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||||
from app.scodoc.sco_xml import quote_xml_attr
|
|
||||||
from app.scodoc.sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL
|
from app.scodoc.sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL
|
||||||
from app.scodoc import sco_exceptions
|
|
||||||
from app.scodoc import sco_xml
|
from app.scodoc import sco_xml
|
||||||
import sco_version
|
import sco_version
|
||||||
|
|
||||||
@ -201,8 +199,14 @@ EVALUATION_RATTRAPAGE = 1
|
|||||||
EVALUATION_SESSION2 = 2
|
EVALUATION_SESSION2 = 2
|
||||||
|
|
||||||
# Dates et années scolaires
|
# Dates et années scolaires
|
||||||
MONTH_FIN_ANNEE_SCOLAIRE = 7 # juillet (TODO: passer en paramètre config.)
|
# Ces dates "pivot" sont paramétrables dans les préférences générales
|
||||||
DAY_FIN_ANNEE_SCOLAIRE = 31 # TODO calculer en fct du mois
|
# on donne ici les valeurs par défaut.
|
||||||
|
# Les semestres commençant à partir du 1er août 20XX sont
|
||||||
|
# dans l'année scolaire 20XX
|
||||||
|
MONTH_DEBUT_ANNEE_SCOLAIRE = 8 # août
|
||||||
|
# Les semestres commençant à partir du 1er décembre
|
||||||
|
# sont "2eme période" (S_pair):
|
||||||
|
MONTH_DEBUT_PERIODE2 = MONTH_DEBUT_ANNEE_SCOLAIRE + 4
|
||||||
|
|
||||||
MONTH_NAMES_ABBREV = (
|
MONTH_NAMES_ABBREV = (
|
||||||
"Jan ",
|
"Jan ",
|
||||||
@ -950,36 +954,47 @@ def annee_scolaire_repr(year, month):
|
|||||||
"""representation de l'annee scolaire : '2009 - 2010'
|
"""representation de l'annee scolaire : '2009 - 2010'
|
||||||
à partir d'une date.
|
à partir d'une date.
|
||||||
"""
|
"""
|
||||||
if month > MONTH_FIN_ANNEE_SCOLAIRE: # apres le 1er aout
|
if month >= MONTH_DEBUT_ANNEE_SCOLAIRE: # apres le 1er aout
|
||||||
return "%s - %s" % (year, year + 1)
|
return f"{year} - {year + 1}"
|
||||||
else:
|
else:
|
||||||
return "%s - %s" % (year - 1, year)
|
return f"{year - 1} - {year}"
|
||||||
|
|
||||||
|
|
||||||
|
def annee_scolaire() -> int:
|
||||||
|
"""Année de debut de l'annee scolaire courante"""
|
||||||
|
t = time.localtime()
|
||||||
|
year, month = t[0], t[1]
|
||||||
|
return annee_scolaire_debut(year, month)
|
||||||
|
|
||||||
|
|
||||||
def annee_scolaire_debut(year, month) -> int:
|
def annee_scolaire_debut(year, month) -> int:
|
||||||
"""Annee scolaire de debut (septembre): heuristique pour l'hémisphère nord..."""
|
"""Annee scolaire de début.
|
||||||
if int(month) > MONTH_FIN_ANNEE_SCOLAIRE:
|
Par défaut (hémisphère nord), l'année du mois de août
|
||||||
|
précédent la date indiquée.
|
||||||
|
"""
|
||||||
|
if int(month) >= MONTH_DEBUT_ANNEE_SCOLAIRE:
|
||||||
return int(year)
|
return int(year)
|
||||||
else:
|
else:
|
||||||
return int(year) - 1
|
return int(year) - 1
|
||||||
|
|
||||||
|
|
||||||
def date_debut_anne_scolaire(annee_scolaire: int) -> datetime:
|
def date_debut_anne_scolaire(annee_sco: int) -> datetime:
|
||||||
"""La date de début de l'année scolaire
|
"""La date de début de l'année scolaire
|
||||||
= 1er aout
|
(par défaut, le 1er aout)
|
||||||
"""
|
"""
|
||||||
return datetime.datetime(year=annee_scolaire, month=8, day=1)
|
return datetime.datetime(year=annee_sco, month=MONTH_DEBUT_ANNEE_SCOLAIRE, day=1)
|
||||||
|
|
||||||
|
|
||||||
def date_fin_anne_scolaire(annee_scolaire: int) -> datetime:
|
def date_fin_anne_scolaire(annee_sco: int) -> datetime:
|
||||||
"""La date de fin de l'année scolaire
|
"""La date de fin de l'année scolaire
|
||||||
= 31 juillet de l'année suivante
|
(par défaut, le 31 juillet de l'année suivante)
|
||||||
"""
|
"""
|
||||||
|
# on prend la date de début de l'année scolaire suivante,
|
||||||
|
# et on lui retre 1 jour.
|
||||||
|
# On s'affranchit ainsi des problèmes de durées de mois.
|
||||||
return datetime.datetime(
|
return datetime.datetime(
|
||||||
year=annee_scolaire + 1,
|
year=annee_sco + 1, month=MONTH_DEBUT_ANNEE_SCOLAIRE, day=1
|
||||||
month=MONTH_FIN_ANNEE_SCOLAIRE,
|
) - datetime.timedelta(days=1)
|
||||||
day=DAY_FIN_ANNEE_SCOLAIRE,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def sem_decale_str(sem):
|
def sem_decale_str(sem):
|
||||||
@ -1105,23 +1120,6 @@ def query_portal(req, msg="Portail Apogee", timeout=3):
|
|||||||
return r.text
|
return r.text
|
||||||
|
|
||||||
|
|
||||||
def AnneeScolaire(sco_year=None) -> int:
|
|
||||||
"annee de debut de l'annee scolaire courante"
|
|
||||||
if sco_year:
|
|
||||||
year = sco_year
|
|
||||||
try:
|
|
||||||
year = int(year)
|
|
||||||
if year > 1900 and year < 2999:
|
|
||||||
return year
|
|
||||||
except:
|
|
||||||
raise sco_exceptions.ScoValueError("invalid sco_year")
|
|
||||||
t = time.localtime()
|
|
||||||
year, month = t[0], t[1]
|
|
||||||
if month < 8: # le "pivot" est le 1er aout
|
|
||||||
year = year - 1
|
|
||||||
return year
|
|
||||||
|
|
||||||
|
|
||||||
def confirm_dialog(
|
def confirm_dialog(
|
||||||
message="<p>Confirmer ?</p>",
|
message="<p>Confirmer ?</p>",
|
||||||
OK="OK",
|
OK="OK",
|
||||||
|
@ -198,7 +198,7 @@ def choix_semaine(group_id):
|
|||||||
def cal_select_week(year=None):
|
def cal_select_week(year=None):
|
||||||
"display calendar allowing week selection"
|
"display calendar allowing week selection"
|
||||||
if not year:
|
if not year:
|
||||||
year = scu.AnneeScolaire()
|
year = scu.annee_scolaire()
|
||||||
sems = sco_formsemestre.do_formsemestre_list()
|
sems = sco_formsemestre.do_formsemestre_list()
|
||||||
if not sems:
|
if not sems:
|
||||||
js = ""
|
js = ""
|
||||||
@ -1215,9 +1215,9 @@ def add_billets_absence_form(etudid):
|
|||||||
@bp.route("/billets_etud/<int:etudid>")
|
@bp.route("/billets_etud/<int:etudid>")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
def billets_etud(etudid=False):
|
def billets_etud(etudid=False, format=False):
|
||||||
"""Liste billets pour un etudiant"""
|
"""Liste billets pour un étudiant"""
|
||||||
fmt = request.args.get("format", "html")
|
fmt = format or request.args.get("format", "html")
|
||||||
if not fmt in {"html", "json", "xml", "xls", "xlsx"}:
|
if not fmt in {"html", "json", "xml", "xls", "xlsx"}:
|
||||||
return ScoValueError("Format invalide")
|
return ScoValueError("Format invalide")
|
||||||
table = sco_abs_billets.table_billets_etud(etudid)
|
table = sco_abs_billets.table_billets_etud(etudid)
|
||||||
|
@ -636,16 +636,16 @@ def index_html():
|
|||||||
</li>
|
</li>
|
||||||
<li><a class="stdlink" href="{
|
<li><a class="stdlink" href="{
|
||||||
url_for("notes.export_recap_formations_annee_scolaire",
|
url_for("notes.export_recap_formations_annee_scolaire",
|
||||||
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.AnneeScolaire()-1)
|
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.annee_scolaire()-1)
|
||||||
}">exporter les formations de l'année scolaire
|
}">exporter les formations de l'année scolaire
|
||||||
{scu.AnneeScolaire()-1} - {scu.AnneeScolaire()}
|
{scu.annee_scolaire()-1} - {scu.annee_scolaire()}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a class="stdlink" href="{
|
<li><a class="stdlink" href="{
|
||||||
url_for("notes.export_recap_formations_annee_scolaire",
|
url_for("notes.export_recap_formations_annee_scolaire",
|
||||||
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.AnneeScolaire())
|
scodoc_dept=g.scodoc_dept, annee_scolaire=scu.annee_scolaire())
|
||||||
}">exporter les formations de l'année scolaire
|
}">exporter les formations de l'année scolaire
|
||||||
{scu.AnneeScolaire()} - {scu.AnneeScolaire()+1}
|
{scu.annee_scolaire()} - {scu.annee_scolaire()+1}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -90,9 +90,7 @@ def test_nouvel_an_special_pp_before_pa():
|
|||||||
|
|
||||||
|
|
||||||
def test_nouvel_ete_pp_before_pa():
|
def test_nouvel_ete_pp_before_pa():
|
||||||
assert (2023, 2) == FormSemestre.comp_periode(
|
assert (2023, 2) == FormSemestre.comp_periode(datetime.datetime(2024, 6, 1), 8, 2)
|
||||||
datetime.datetime(2024, 6, 1), 1, 8, 1, 2
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_automne_special_pp_before_pa():
|
def test_automne_special_pp_before_pa():
|
||||||
@ -108,27 +106,27 @@ sem_prev_year = {"date_debut_iso": "2022-07-31"}
|
|||||||
|
|
||||||
|
|
||||||
def test_sem_in_periode1_default():
|
def test_sem_in_periode1_default():
|
||||||
assert True == sem_in_semestre_scolaire(sem_automne, 2022, 1)
|
assert True is sem_in_semestre_scolaire(sem_automne, 2022, 1)
|
||||||
assert False == sem_in_semestre_scolaire(sem_nouvel_an, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_nouvel_an, 2022, 1)
|
||||||
assert False == sem_in_semestre_scolaire(sem_printemps, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_printemps, 2022, 1)
|
||||||
assert False == sem_in_semestre_scolaire(sem_ete, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_ete, 2022, 1)
|
||||||
assert False == sem_in_semestre_scolaire(sem_next_year, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_next_year, 2022, 1)
|
||||||
assert False == sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_sem_in_periode2_default():
|
def test_sem_in_periode2_default():
|
||||||
assert False == sem_in_semestre_scolaire(sem_automne, 2022, 2)
|
assert False is sem_in_semestre_scolaire(sem_automne, 2022, 2)
|
||||||
assert True == sem_in_semestre_scolaire(sem_nouvel_an, 2022, 2)
|
assert True is sem_in_semestre_scolaire(sem_nouvel_an, 2022, 2)
|
||||||
assert True == sem_in_semestre_scolaire(sem_printemps, 2022, 2)
|
assert True is sem_in_semestre_scolaire(sem_printemps, 2022, 2)
|
||||||
assert True == sem_in_semestre_scolaire(sem_ete, 2022, 2)
|
assert True is sem_in_semestre_scolaire(sem_ete, 2022, 2)
|
||||||
assert False == sem_in_semestre_scolaire(sem_next_year, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_next_year, 2022, 1)
|
||||||
assert False == sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
|
assert False is sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
|
||||||
|
|
||||||
|
|
||||||
def test_sem_in_annee_default():
|
def test_sem_in_annee_default():
|
||||||
assert True == sem_in_semestre_scolaire(sem_automne, 2022, 0)
|
assert True is sem_in_semestre_scolaire(sem_automne, 2022, 0)
|
||||||
assert True == sem_in_semestre_scolaire(sem_nouvel_an, 2022)
|
assert True is sem_in_semestre_scolaire(sem_nouvel_an, 2022)
|
||||||
assert True == sem_in_semestre_scolaire(sem_printemps, 2022, 0)
|
assert True is sem_in_semestre_scolaire(sem_printemps, 2022, 0)
|
||||||
assert True == sem_in_semestre_scolaire(sem_ete, 2022, 0)
|
assert True is sem_in_semestre_scolaire(sem_ete, 2022, 0)
|
||||||
assert False == sem_in_semestre_scolaire(sem_next_year, 2022)
|
assert False is sem_in_semestre_scolaire(sem_next_year, 2022)
|
||||||
assert False == sem_in_semestre_scolaire(sem_prev_year, 2022, 0)
|
assert False is sem_in_semestre_scolaire(sem_prev_year, 2022, 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user