forked from ScoDoc/ScoDoc
Assiduites : préférences - métrique + lien assiduité avec reste scodoc
This commit is contained in:
parent
238b6b10d4
commit
825dc6ecb1
@ -386,6 +386,12 @@ class BulletinBUT:
|
|||||||
semestre_infos["absences"] = {
|
semestre_infos["absences"] = {
|
||||||
"injustifie": nbabs - nbabsjust,
|
"injustifie": nbabs - nbabsjust,
|
||||||
"total": nbabs,
|
"total": nbabs,
|
||||||
|
"metrique": {
|
||||||
|
"H.": "Heure(s)",
|
||||||
|
"J.": "Journée(s)",
|
||||||
|
"1/2 J.": "1/2 Jour.",
|
||||||
|
"N.": "Nombre",
|
||||||
|
}.get(sco_preferences.get_preference("assi_metrique")),
|
||||||
}
|
}
|
||||||
decisions_ues = self.res.get_etud_decisions_ue(etud.id) or {}
|
decisions_ues = self.res.get_etud_decisions_ue(etud.id) or {}
|
||||||
if self.prefs["bul_show_ects"]:
|
if self.prefs["bul_show_ects"]:
|
||||||
|
@ -39,9 +39,11 @@ from app.models.validations import ScolarFormSemestreValidation
|
|||||||
from app.scodoc import codes_cursus, sco_preferences
|
from app.scodoc import codes_cursus, sco_preferences
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
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, translate_assiduites_metric
|
||||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||||
|
|
||||||
|
from app.scodoc.sco_utils import translate_assiduites_metric
|
||||||
|
|
||||||
GROUPS_AUTO_ASSIGNMENT_DATA_MAX = 1024 * 1024 # bytes
|
GROUPS_AUTO_ASSIGNMENT_DATA_MAX = 1024 * 1024 # bytes
|
||||||
|
|
||||||
|
|
||||||
@ -678,8 +680,12 @@ class FormSemestre(db.Model):
|
|||||||
"""
|
"""
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_abs
|
||||||
|
|
||||||
return sco_abs.get_abs_count_in_interval(
|
metrique = sco_preferences.get_preference("assi_metrique", self.id)
|
||||||
etudid, self.date_debut.isoformat(), self.date_fin.isoformat()
|
return sco_abs.get_assiduites_count_in_interval(
|
||||||
|
etudid,
|
||||||
|
self.date_debut.isoformat(),
|
||||||
|
self.date_fin.isoformat(),
|
||||||
|
translate_assiduites_metric(metrique),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_codes_apogee(self, category=None) -> set[str]:
|
def get_codes_apogee(self, category=None) -> set[str]:
|
||||||
|
@ -116,10 +116,10 @@ def sidebar(etudid: int = None):
|
|||||||
)
|
)
|
||||||
if etud["cursem"]:
|
if etud["cursem"]:
|
||||||
cur_sem = etud["cursem"]
|
cur_sem = etud["cursem"]
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, cur_sem)
|
nbabs, nbabsjust = sco_abs.get_assiduites_count(etudid, cur_sem)
|
||||||
nbabsnj = nbabs - nbabsjust
|
nbabsnj = nbabs - nbabsjust
|
||||||
H.append(
|
H.append(
|
||||||
f"""<span title="absences du { cur_sem["date_debut"] } au { cur_sem["date_fin"] }">(1/2 j.)
|
f"""<span title="absences du { cur_sem["date_debut"] } au { cur_sem["date_fin"] }">({sco_preferences.get_preference("assi_metrique", None)})
|
||||||
<br>{ nbabsjust } J., { nbabsnj } N.J.</span>"""
|
<br>{ nbabsjust } J., { nbabsnj } N.J.</span>"""
|
||||||
)
|
)
|
||||||
H.append("<ul>")
|
H.append("<ul>")
|
||||||
|
@ -1054,19 +1054,42 @@ def get_abs_count_in_interval(etudid, date_debut_iso, date_fin_iso):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def get_assiduites_count_in_interval(etudid, date_debut_iso, date_fin_iso):
|
def get_assiduites_count(etudid, sem):
|
||||||
|
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
||||||
|
tuple (nb abs non justifiées, nb abs justifiées)
|
||||||
|
Utilise un cache.
|
||||||
|
"""
|
||||||
|
metrique = sco_preferences.get_preference("assi_metrique", sem["formsemestre_id"])
|
||||||
|
return get_assiduites_count_in_interval(
|
||||||
|
etudid,
|
||||||
|
sem["date_debut_iso"],
|
||||||
|
sem["date_fin_iso"],
|
||||||
|
scu.translate_assiduites_metric(metrique),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_assiduites_count_in_interval(
|
||||||
|
etudid, date_debut_iso, date_fin_iso, metrique="demi"
|
||||||
|
):
|
||||||
"""Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
|
"""Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
|
||||||
tuple (nb abs, nb abs justifiées)
|
tuple (nb abs, nb abs justifiées)
|
||||||
Utilise un cache.
|
Utilise un cache.
|
||||||
"""
|
"""
|
||||||
key = str(etudid) + "_" + date_debut_iso + "_" + date_fin_iso + "_assiduites"
|
key = (
|
||||||
|
str(etudid)
|
||||||
|
+ "_"
|
||||||
|
+ date_debut_iso
|
||||||
|
+ "_"
|
||||||
|
+ date_fin_iso
|
||||||
|
+ f"{metrique}_assiduites"
|
||||||
|
)
|
||||||
r = sco_cache.AbsSemEtudCache.get(key)
|
r = sco_cache.AbsSemEtudCache.get(key)
|
||||||
if not r:
|
if not r:
|
||||||
|
|
||||||
date_debut: datetime.datetime = scu.is_iso_formated(date_debut_iso, True)
|
date_debut: datetime.datetime = scu.is_iso_formated(date_debut_iso, True)
|
||||||
date_fin: datetime.datetime = scu.is_iso_formated(date_fin_iso, True)
|
date_fin: datetime.datetime = scu.is_iso_formated(date_fin_iso, True)
|
||||||
|
|
||||||
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid)
|
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid)
|
||||||
|
assiduites = assiduites.filter(Assiduite.etat != 0)
|
||||||
justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid)
|
justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid)
|
||||||
|
|
||||||
assiduites = scass.filter_by_date(assiduites, Assiduite, date_debut, date_fin)
|
assiduites = scass.filter_by_date(assiduites, Assiduite, date_debut, date_fin)
|
||||||
@ -1076,7 +1099,7 @@ def get_assiduites_count_in_interval(etudid, date_debut_iso, date_fin_iso):
|
|||||||
|
|
||||||
calculator: scass.CountCalculator = scass.CountCalculator()
|
calculator: scass.CountCalculator = scass.CountCalculator()
|
||||||
calculator.compute_assiduites(assiduites)
|
calculator.compute_assiduites(assiduites)
|
||||||
nb_abs: dict = calculator.to_dict()["demi"]
|
nb_abs: dict = calculator.to_dict()[metrique]
|
||||||
|
|
||||||
abs_just: list[Assiduite] = scass.get_all_justified(
|
abs_just: list[Assiduite] = scass.get_all_justified(
|
||||||
etudid, date_debut, date_fin
|
etudid, date_debut, date_fin
|
||||||
@ -1084,7 +1107,7 @@ def get_assiduites_count_in_interval(etudid, date_debut_iso, date_fin_iso):
|
|||||||
|
|
||||||
calculator.reset()
|
calculator.reset()
|
||||||
calculator.compute_assiduites(abs_just)
|
calculator.compute_assiduites(abs_just)
|
||||||
nb_abs_just: dict = calculator.to_dict()["demi"]
|
nb_abs_just: dict = calculator.to_dict()[metrique]
|
||||||
|
|
||||||
r = (nb_abs, nb_abs_just)
|
r = (nb_abs, nb_abs_just)
|
||||||
ans = sco_cache.AbsSemEtudCache.set(key, r)
|
ans = sco_cache.AbsSemEtudCache.set(key, r)
|
||||||
@ -1101,6 +1124,15 @@ def invalidate_abs_count(etudid, sem):
|
|||||||
sco_cache.AbsSemEtudCache.delete(key)
|
sco_cache.AbsSemEtudCache.delete(key)
|
||||||
|
|
||||||
|
|
||||||
|
def invalidate_assiduites_count(etudid, sem):
|
||||||
|
"""Invalidate (clear) cached counts"""
|
||||||
|
date_debut = sem["date_debut_iso"]
|
||||||
|
date_fin = sem["date_fin_iso"]
|
||||||
|
for met in ["demi", "journee", "compte", "heure"]:
|
||||||
|
key = str(etudid) + "_" + date_debut + "_" + date_fin + f"{met}_assiduites"
|
||||||
|
sco_cache.AbsSemEtudCache.delete(key)
|
||||||
|
|
||||||
|
|
||||||
def invalidate_abs_count_sem(sem):
|
def invalidate_abs_count_sem(sem):
|
||||||
"""Invalidate (clear) cached abs counts for all the students of this semestre"""
|
"""Invalidate (clear) cached abs counts for all the students of this semestre"""
|
||||||
inscriptions = (
|
inscriptions = (
|
||||||
@ -1112,6 +1144,17 @@ def invalidate_abs_count_sem(sem):
|
|||||||
invalidate_abs_count(ins["etudid"], sem)
|
invalidate_abs_count(ins["etudid"], sem)
|
||||||
|
|
||||||
|
|
||||||
|
def invalidate_assiduites_count_sem(sem):
|
||||||
|
"""Invalidate (clear) cached abs counts for all the students of this semestre"""
|
||||||
|
inscriptions = (
|
||||||
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||||
|
sem["formsemestre_id"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for ins in inscriptions:
|
||||||
|
invalidate_assiduites_count(ins["etudid"], sem)
|
||||||
|
|
||||||
|
|
||||||
def invalidate_abs_etud_date(etudid, date): # was invalidateAbsEtudDate
|
def invalidate_abs_etud_date(etudid, date): # was invalidateAbsEtudDate
|
||||||
"""Doit etre appelé à chaque modification des absences pour cet étudiant et cette date.
|
"""Doit etre appelé à chaque modification des absences pour cet étudiant et cette date.
|
||||||
Invalide cache absence et caches semestre
|
Invalide cache absence et caches semestre
|
||||||
@ -1145,3 +1188,38 @@ def invalidate_abs_etud_date(etudid, date): # was invalidateAbsEtudDate
|
|||||||
|
|
||||||
# Inval cache compteurs absences:
|
# Inval cache compteurs absences:
|
||||||
invalidate_abs_count_sem(sem)
|
invalidate_abs_count_sem(sem)
|
||||||
|
|
||||||
|
|
||||||
|
def invalidate_assiduites_etud_date(etudid, date):
|
||||||
|
"""Doit etre appelé à chaque modification des assiduites pour cet étudiant et cette date.
|
||||||
|
Invalide cache absence et caches semestre
|
||||||
|
date: date au format ISO
|
||||||
|
"""
|
||||||
|
from app.scodoc import sco_compute_moy
|
||||||
|
|
||||||
|
# Semestres a cette date:
|
||||||
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
|
sems = [
|
||||||
|
sem
|
||||||
|
for sem in etud["sems"]
|
||||||
|
if sem["date_debut_iso"] <= date and sem["date_fin_iso"] >= date
|
||||||
|
]
|
||||||
|
|
||||||
|
# Invalide les PDF et les absences:
|
||||||
|
for sem in sems:
|
||||||
|
# Inval cache bulletin et/ou note_table
|
||||||
|
if sco_compute_moy.formsemestre_expressions_use_abscounts(
|
||||||
|
sem["formsemestre_id"]
|
||||||
|
):
|
||||||
|
# certaines formules utilisent les absences
|
||||||
|
pdfonly = False
|
||||||
|
else:
|
||||||
|
# efface toujours le PDF car il affiche en général les absences
|
||||||
|
pdfonly = True
|
||||||
|
|
||||||
|
sco_cache.invalidate_formsemestre(
|
||||||
|
formsemestre_id=sem["formsemestre_id"], pdfonly=pdfonly
|
||||||
|
)
|
||||||
|
|
||||||
|
# Inval cache compteurs absences:
|
||||||
|
invalidate_assiduites_count(etudid, sem)
|
||||||
|
@ -47,6 +47,7 @@ import app.scodoc.notesdb as ndb
|
|||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_users
|
from app.scodoc import sco_users
|
||||||
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
def abs_notify(etudid, date):
|
def abs_notify(etudid, date):
|
||||||
@ -61,8 +62,15 @@ def abs_notify(etudid, date):
|
|||||||
if not formsemestre:
|
if not formsemestre:
|
||||||
return # non inscrit a la date, pas de notification
|
return # non inscrit a la date, pas de notification
|
||||||
|
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count_in_interval(
|
nbabs, nbabsjust = sco_abs.get_assiduites_count_in_interval(
|
||||||
etudid, formsemestre.date_debut.isoformat(), formsemestre.date_fin.isoformat()
|
etudid,
|
||||||
|
formsemestre.date_debut.isoformat(),
|
||||||
|
formsemestre.date_fin.isoformat(),
|
||||||
|
scu.translate_assiduites_metric(
|
||||||
|
sco_preferences.get_preference(
|
||||||
|
"assi_metrique", formsemestre.formsemestre_id
|
||||||
|
)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
do_abs_notify(formsemestre, etudid, date, nbabs, nbabsjust)
|
do_abs_notify(formsemestre, etudid, date, nbabs, nbabsjust)
|
||||||
|
|
||||||
@ -85,6 +93,7 @@ def do_abs_notify(formsemestre: FormSemestre, etudid, date, nbabs, nbabsjust):
|
|||||||
return # abort
|
return # abort
|
||||||
|
|
||||||
# Vérification fréquence (pour ne pas envoyer de mails trop souvent)
|
# Vérification fréquence (pour ne pas envoyer de mails trop souvent)
|
||||||
|
# TODO Mettre la fréquence dans les préférences assiduités
|
||||||
abs_notify_max_freq = sco_preferences.get_preference("abs_notify_max_freq")
|
abs_notify_max_freq = sco_preferences.get_preference("abs_notify_max_freq")
|
||||||
destinations_filtered = []
|
destinations_filtered = []
|
||||||
for email_addr in destinations:
|
for email_addr in destinations:
|
||||||
@ -174,6 +183,8 @@ def abs_notify_is_above_threshold(etudid, nbabs, nbabsjust, formsemestre_id):
|
|||||||
|
|
||||||
(nbabs > abs_notify_abs_threshold)
|
(nbabs > abs_notify_abs_threshold)
|
||||||
(nbabs - nbabs_last_notified) > abs_notify_abs_increment
|
(nbabs - nbabs_last_notified) > abs_notify_abs_increment
|
||||||
|
|
||||||
|
TODO Mettre à jour avec le module assiduité + fonctionnement métrique
|
||||||
"""
|
"""
|
||||||
abs_notify_abs_threshold = sco_preferences.get_preference(
|
abs_notify_abs_threshold = sco_preferences.get_preference(
|
||||||
"abs_notify_abs_threshold", formsemestre_id
|
"abs_notify_abs_threshold", formsemestre_id
|
||||||
|
@ -197,7 +197,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
|||||||
pid = partition["partition_id"]
|
pid = partition["partition_id"]
|
||||||
partitions_etud_groups[pid] = sco_groups.get_etud_groups_in_partition(pid)
|
partitions_etud_groups[pid] = sco_groups.get_etud_groups_in_partition(pid)
|
||||||
# --- Absences
|
# --- Absences
|
||||||
I["nbabs"], I["nbabsjust"] = sco_abs.get_abs_count(etudid, nt.sem)
|
I["nbabs"], I["nbabsjust"] = sco_abs.get_assiduites_count(etudid, nt.sem)
|
||||||
|
|
||||||
# --- Decision Jury
|
# --- Decision Jury
|
||||||
infos, dpv = etud_descr_situation_semestre(
|
infos, dpv = etud_descr_situation_semestre(
|
||||||
@ -487,7 +487,7 @@ def _ue_mod_bulletin(
|
|||||||
) # peut etre 'NI'
|
) # peut etre 'NI'
|
||||||
is_malus = mod["module"]["module_type"] == ModuleType.MALUS
|
is_malus = mod["module"]["module_type"] == ModuleType.MALUS
|
||||||
if bul_show_abs_modules:
|
if bul_show_abs_modules:
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
nbabs, nbabsjust = sco_abs.get_assiduites_count(etudid, sem)
|
||||||
mod_abs = [nbabs, nbabsjust]
|
mod_abs = [nbabs, nbabsjust]
|
||||||
mod["mod_abs_txt"] = scu.fmt_abs(mod_abs)
|
mod["mod_abs_txt"] = scu.fmt_abs(mod_abs)
|
||||||
else:
|
else:
|
||||||
|
@ -297,7 +297,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
|
|
||||||
# --- Absences
|
# --- Absences
|
||||||
if prefs["bul_show_abs"]:
|
if prefs["bul_show_abs"]:
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
nbabs, nbabsjust = sco_abs.get_assiduites_count(etudid, sem)
|
||||||
d["absences"] = dict(nbabs=nbabs, nbabsjust=nbabsjust)
|
d["absences"] = dict(nbabs=nbabs, nbabsjust=nbabsjust)
|
||||||
|
|
||||||
# --- Décision Jury
|
# --- Décision Jury
|
||||||
|
@ -63,6 +63,7 @@ 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
|
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()
|
||||||
# pour simplifier le code, mais attention a la maintenance !)
|
# pour simplifier le code, mais attention a la maintenance !)
|
||||||
@ -369,7 +370,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
|
|
||||||
# --- Absences
|
# --- Absences
|
||||||
if sco_preferences.get_preference("bul_show_abs", formsemestre_id):
|
if sco_preferences.get_preference("bul_show_abs", formsemestre_id):
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
nbabs, nbabsjust = sco_abs.get_assiduites_count(etudid, sem)
|
||||||
doc.append(Element("absences", nbabs=str(nbabs), nbabsjust=str(nbabsjust)))
|
doc.append(Element("absences", nbabs=str(nbabs), nbabsjust=str(nbabsjust)))
|
||||||
# --- Decision Jury
|
# --- Decision Jury
|
||||||
if (
|
if (
|
||||||
|
@ -696,7 +696,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
f"""<td class="rcp_moy">{scu.fmt_note(nt.get_etud_moy_gen(etudid))}</td>"""
|
f"""<td class="rcp_moy">{scu.fmt_note(nt.get_etud_moy_gen(etudid))}</td>"""
|
||||||
)
|
)
|
||||||
# Absences (nb d'abs non just. dans ce semestre)
|
# Absences (nb d'abs non just. dans ce semestre)
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
nbabs, nbabsjust = sco_abs.get_assiduites_count(etudid, sem)
|
||||||
H.append(f"""<td class="rcp_abs">{nbabs - nbabsjust}</td>""")
|
H.append(f"""<td class="rcp_abs">{nbabs - nbabsjust}</td>""")
|
||||||
|
|
||||||
# UEs
|
# UEs
|
||||||
|
@ -107,7 +107,7 @@ def etud_get_poursuite_info(sem, etud):
|
|||||||
rangs.append(["rang_" + codeModule, rangModule])
|
rangs.append(["rang_" + codeModule, rangModule])
|
||||||
|
|
||||||
# Absences
|
# Absences
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, nt.sem)
|
nbabs, nbabsjust = sco_abs.get_assiduites_count(etudid, nt.sem)
|
||||||
if (
|
if (
|
||||||
dec
|
dec
|
||||||
and not sem_descr # not sem_descr pour ne prendre que le semestre validé le plus récent
|
and not sem_descr # not sem_descr pour ne prendre que le semestre validé le plus récent
|
||||||
|
@ -653,6 +653,19 @@ class BasePreferences(object):
|
|||||||
"explanation": "Liste des jours (lun,mar,mer,jeu,ven,sam,dim)",
|
"explanation": "Liste des jours (lun,mar,mer,jeu,ven,sam,dim)",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"assi_metrique",
|
||||||
|
{
|
||||||
|
"initvalue": "1/2 J.",
|
||||||
|
"input_type": "menu",
|
||||||
|
"labels": ["1/2 J.", "J.", "H.", "N."],
|
||||||
|
"allowed_values": ["1/2 J.", "J.", "H.", "N."],
|
||||||
|
"title": "Métrique de l'assiduité",
|
||||||
|
"explanation": "Unité affichée dans la fiche étudiante et le bilan\n(J. = journée, H. = heure, N. = nombre)",
|
||||||
|
"category": "assi",
|
||||||
|
"only_global" : True,
|
||||||
|
},
|
||||||
|
),
|
||||||
# portal
|
# portal
|
||||||
(
|
(
|
||||||
"portal_url",
|
"portal_url",
|
||||||
|
@ -139,7 +139,7 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
main_partition_id, ""
|
main_partition_id, ""
|
||||||
)
|
)
|
||||||
# absences:
|
# absences:
|
||||||
e_nbabs, e_nbabsjust = sco_abs.get_abs_count(etud.id, sem)
|
e_nbabs, e_nbabsjust = sco_abs.get_assiduites_count(etud.id, sem)
|
||||||
nbabs[etud.id] = e_nbabs
|
nbabs[etud.id] = e_nbabs
|
||||||
nbabsjust[etud.id] = e_nbabs - e_nbabsjust
|
nbabsjust[etud.id] = e_nbabs - e_nbabsjust
|
||||||
|
|
||||||
|
@ -251,6 +251,17 @@ def is_period_overlapping(
|
|||||||
return p_deb < i_fin and p_fin > i_deb
|
return p_deb < i_fin and p_fin > i_deb
|
||||||
|
|
||||||
|
|
||||||
|
def translate_assiduites_metric(hr_metric) -> str:
|
||||||
|
if hr_metric == "1/2 J.":
|
||||||
|
return "demi"
|
||||||
|
if hr_metric == "J.":
|
||||||
|
return "journee"
|
||||||
|
if hr_metric == "N.":
|
||||||
|
return "compte"
|
||||||
|
if hr_metric == "H.":
|
||||||
|
return "heure"
|
||||||
|
|
||||||
|
|
||||||
# Types de modules
|
# Types de modules
|
||||||
class ModuleType(IntEnum):
|
class ModuleType(IntEnum):
|
||||||
"""Code des types de module."""
|
"""Code des types de module."""
|
||||||
|
@ -2,38 +2,45 @@
|
|||||||
class releveBUT extends HTMLElement {
|
class releveBUT extends HTMLElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.shadow = this.attachShadow({ mode: 'open' });
|
this.shadow = this.attachShadow({ mode: "open" });
|
||||||
|
|
||||||
/* Config par defaut */
|
/* Config par defaut */
|
||||||
this.config = {
|
this.config = {
|
||||||
showURL: true
|
showURL: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Template du module */
|
/* Template du module */
|
||||||
this.shadow.innerHTML = this.template();
|
this.shadow.innerHTML = this.template();
|
||||||
|
|
||||||
/* Style du module */
|
/* Style du module */
|
||||||
const styles = document.createElement('link');
|
const styles = document.createElement("link");
|
||||||
styles.setAttribute('rel', 'stylesheet');
|
styles.setAttribute("rel", "stylesheet");
|
||||||
if (location.href.includes("ScoDoc")) {
|
if (location.href.includes("ScoDoc")) {
|
||||||
styles.setAttribute('href', removeLastTwoComponents(getCurrentScriptPath()) + '/css/releve-but.css'); // Scodoc
|
styles.setAttribute(
|
||||||
|
"href",
|
||||||
|
removeLastTwoComponents(getCurrentScriptPath()) + "/css/releve-but.css"
|
||||||
|
); // Scodoc
|
||||||
} else {
|
} else {
|
||||||
styles.setAttribute('href', '/assets/styles/releve-but.css'); // Passerelle
|
styles.setAttribute("href", "/assets/styles/releve-but.css"); // Passerelle
|
||||||
}
|
}
|
||||||
this.shadow.appendChild(styles);
|
this.shadow.appendChild(styles);
|
||||||
}
|
}
|
||||||
listeOnOff() {
|
listeOnOff() {
|
||||||
this.parentElement.parentElement.classList.toggle("listeOff");
|
this.parentElement.parentElement.classList.toggle("listeOff");
|
||||||
this.parentElement.parentElement.querySelectorAll(".moduleOnOff").forEach(e => {
|
this.parentElement.parentElement
|
||||||
e.classList.remove("moduleOnOff")
|
.querySelectorAll(".moduleOnOff")
|
||||||
})
|
.forEach((e) => {
|
||||||
|
e.classList.remove("moduleOnOff");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
moduleOnOff() {
|
moduleOnOff() {
|
||||||
this.parentElement.classList.toggle("moduleOnOff");
|
this.parentElement.classList.toggle("moduleOnOff");
|
||||||
}
|
}
|
||||||
goTo() {
|
goTo() {
|
||||||
let module = this.dataset.module;
|
let module = this.dataset.module;
|
||||||
this.parentElement.parentElement.parentElement.parentElement.querySelector("#Module_" + module).scrollIntoView();
|
this.parentElement.parentElement.parentElement.parentElement
|
||||||
|
.querySelector("#Module_" + module)
|
||||||
|
.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
set setConfig(config) {
|
set setConfig(config) {
|
||||||
@ -50,15 +57,17 @@ class releveBUT extends HTMLElement {
|
|||||||
|
|
||||||
this.setOptions(data.options);
|
this.setOptions(data.options);
|
||||||
|
|
||||||
this.shadow.querySelectorAll(".CTA_Liste").forEach(e => {
|
this.shadow.querySelectorAll(".CTA_Liste").forEach((e) => {
|
||||||
e.addEventListener("click", this.listeOnOff)
|
e.addEventListener("click", this.listeOnOff);
|
||||||
})
|
});
|
||||||
this.shadow.querySelectorAll(".ue, .module").forEach(e => {
|
this.shadow.querySelectorAll(".ue, .module").forEach((e) => {
|
||||||
e.addEventListener("click", this.moduleOnOff)
|
e.addEventListener("click", this.moduleOnOff);
|
||||||
})
|
});
|
||||||
this.shadow.querySelectorAll(":not(.ueBonus)+.syntheseModule").forEach(e => {
|
this.shadow
|
||||||
e.addEventListener("click", this.goTo)
|
.querySelectorAll(":not(.ueBonus)+.syntheseModule")
|
||||||
})
|
.forEach((e) => {
|
||||||
|
e.addEventListener("click", this.goTo);
|
||||||
|
});
|
||||||
|
|
||||||
this.shadow.children[0].classList.add("ready");
|
this.shadow.children[0].classList.add("ready");
|
||||||
}
|
}
|
||||||
@ -146,9 +155,10 @@ class releveBUT extends HTMLElement {
|
|||||||
/* Informations sur l'étudiant */
|
/* Informations sur l'étudiant */
|
||||||
/********************************/
|
/********************************/
|
||||||
showInformations(data) {
|
showInformations(data) {
|
||||||
this.shadow.querySelector(".studentPic").src = data.etudiant.photo_url || "default_Student.svg";
|
this.shadow.querySelector(".studentPic").src =
|
||||||
|
data.etudiant.photo_url || "default_Student.svg";
|
||||||
|
|
||||||
let output = '';
|
let output = "";
|
||||||
|
|
||||||
if (this.config.showURL) {
|
if (this.config.showURL) {
|
||||||
output += `<a href="${data.etudiant.fiche_url}" class=info_etudiant>`;
|
output += `<a href="${data.etudiant.fiche_url}" class=info_etudiant>`;
|
||||||
@ -163,7 +173,9 @@ class releveBUT extends HTMLElement {
|
|||||||
${data.etudiant.prenom}`;
|
${data.etudiant.prenom}`;
|
||||||
|
|
||||||
if (data.etudiant.date_naissance) {
|
if (data.etudiant.date_naissance) {
|
||||||
output += ` <div class=dateNaissance>né${(data.etudiant.civilite == "F") ? "e" : ""} le ${this.ISOToDate(data.etudiant.date_naissance)}</div>`;
|
output += ` <div class=dateNaissance>né${
|
||||||
|
data.etudiant.civilite == "F" ? "e" : ""
|
||||||
|
} le ${this.ISOToDate(data.etudiant.date_naissance)}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
output += `
|
output += `
|
||||||
@ -195,23 +207,28 @@ class releveBUT extends HTMLElement {
|
|||||||
/*******************************/
|
/*******************************/
|
||||||
showSemestre(data) {
|
showSemestre(data) {
|
||||||
let correspondanceCodes = {
|
let correspondanceCodes = {
|
||||||
"ADM": "Admis",
|
ADM: "Admis",
|
||||||
"AJD": "Admis par décision de jury",
|
AJD: "Admis par décision de jury",
|
||||||
"PASD": "Passage de droit : tout n'est pas validé, mais d'après les règles du BUT, vous passez",
|
PASD: "Passage de droit : tout n'est pas validé, mais d'après les règles du BUT, vous passez",
|
||||||
"PAS1NCI": "Vous passez par décision de jury mais attention, vous n'avez pas partout le niveau suffisant",
|
PAS1NCI:
|
||||||
"RED": "Ajourné mais autorisé à redoubler",
|
"Vous passez par décision de jury mais attention, vous n'avez pas partout le niveau suffisant",
|
||||||
"NAR": "Non admis et non autorisé à redoubler : réorientation",
|
RED: "Ajourné mais autorisé à redoubler",
|
||||||
"DEM": "Démission",
|
NAR: "Non admis et non autorisé à redoubler : réorientation",
|
||||||
"ABAN": "Abandon constaté sans lettre de démission",
|
DEM: "Démission",
|
||||||
"RAT": "En attente d'un rattrapage",
|
ABAN: "Abandon constaté sans lettre de démission",
|
||||||
"EXCLU": "Exclusion dans le cadre d'une décision disciplinaire",
|
RAT: "En attente d'un rattrapage",
|
||||||
"DEF": "Défaillance : non évalué par manque d'assiduité",
|
EXCLU: "Exclusion dans le cadre d'une décision disciplinaire",
|
||||||
"ABL": "Année blanche"
|
DEF: "Défaillance : non évalué par manque d'assiduité",
|
||||||
}
|
ABL: "Année blanche",
|
||||||
|
};
|
||||||
|
|
||||||
this.shadow.querySelector("#identite_etudiant").innerHTML = ` <a href="${data.etudiant.fiche_url}">${data.etudiant.nomprenom}</a> `;
|
this.shadow.querySelector(
|
||||||
this.shadow.querySelector(".dateInscription").innerHTML += this.ISOToDate(data.semestre.inscription);
|
"#identite_etudiant"
|
||||||
let output = '';
|
).innerHTML = ` <a href="${data.etudiant.fiche_url}">${data.etudiant.nomprenom}</a> `;
|
||||||
|
this.shadow.querySelector(".dateInscription").innerHTML += this.ISOToDate(
|
||||||
|
data.semestre.inscription
|
||||||
|
);
|
||||||
|
let output = "";
|
||||||
if (!data.options.block_moyenne_generale) {
|
if (!data.options.block_moyenne_generale) {
|
||||||
output += `
|
output += `
|
||||||
<div>
|
<div>
|
||||||
@ -225,12 +242,16 @@ class releveBUT extends HTMLElement {
|
|||||||
}
|
}
|
||||||
output += `
|
output += `
|
||||||
${(() => {
|
${(() => {
|
||||||
if ((!data.semestre.rang.groupes) ||
|
if (
|
||||||
(Object.keys(data.semestre.rang.groupes).length == 0)) {
|
!data.semestre.rang.groupes ||
|
||||||
|
Object.keys(data.semestre.rang.groupes).length == 0
|
||||||
|
) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
let output = "";
|
let output = "";
|
||||||
let [idGroupe, dataGroupe] = Object.entries(data.semestre.rang.groupes)[0];
|
let [idGroupe, dataGroupe] = Object.entries(
|
||||||
|
data.semestre.rang.groupes
|
||||||
|
)[0];
|
||||||
output += `<div>
|
output += `<div>
|
||||||
<div class=enteteSemestre>${data.semestre.groupes[0]?.group_name}</div><div></div>
|
<div class=enteteSemestre>${data.semestre.groupes[0]?.group_name}</div><div></div>
|
||||||
<div class=rang>Rang :</div><div class=rang>${dataGroupe.value} / ${dataGroupe.total}</div>
|
<div class=rang>Rang :</div><div class=rang>${dataGroupe.value} / ${dataGroupe.total}</div>
|
||||||
@ -241,7 +262,9 @@ class releveBUT extends HTMLElement {
|
|||||||
return output;
|
return output;
|
||||||
})()}
|
})()}
|
||||||
<div class=absencesRecap>
|
<div class=absencesRecap>
|
||||||
<div class=enteteSemestre>Absences</div><div class=enteteSemestre>1/2 jour.</div>
|
<div class=enteteSemestre>Absences</div><div class=enteteSemestre>${
|
||||||
|
data.semestre.absences?.metrique ?? "1/2 jour."
|
||||||
|
}</div>
|
||||||
<div class=abs>Non justifiées</div>
|
<div class=abs>Non justifiées</div>
|
||||||
<div>${data.semestre.absences?.injustifie ?? "-"}</div>
|
<div>${data.semestre.absences?.injustifie ?? "-"}</div>
|
||||||
<div class=abs>Total</div><div>${data.semestre.absences?.total ?? "-"}</div>
|
<div class=abs>Total</div><div>${data.semestre.absences?.total ?? "-"}</div>
|
||||||
@ -252,13 +275,13 @@ class releveBUT extends HTMLElement {
|
|||||||
<div class=enteteSemestre>RCUE</div><div></div>
|
<div class=enteteSemestre>RCUE</div><div></div>
|
||||||
${(() => {
|
${(() => {
|
||||||
let output = "";
|
let output = "";
|
||||||
data.semestre.decision_rcue.forEach(competence => {
|
data.semestre.decision_rcue.forEach((competence) => {
|
||||||
output += `<div class=competence>${competence.niveau.competence.titre}</div><div>${competence.code}</div>`;
|
output += `<div class=competence>${competence.niveau.competence.titre}</div><div>${competence.code}</div>`;
|
||||||
})
|
});
|
||||||
return output;
|
return output;
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`;
|
||||||
}
|
}
|
||||||
if (data.semestre.decision_ue?.length) {
|
if (data.semestre.decision_ue?.length) {
|
||||||
output += `
|
output += `
|
||||||
@ -266,18 +289,20 @@ class releveBUT extends HTMLElement {
|
|||||||
<div class=enteteSemestre>UE</div><div></div>
|
<div class=enteteSemestre>UE</div><div></div>
|
||||||
${(() => {
|
${(() => {
|
||||||
let output = "";
|
let output = "";
|
||||||
data.semestre.decision_ue.forEach(ue => {
|
data.semestre.decision_ue.forEach((ue) => {
|
||||||
output += `<div class=competence>${ue.acronyme}</div><div>${ue.code}</div>`;
|
output += `<div class=competence>${ue.acronyme}</div><div>${ue.code}</div>`;
|
||||||
})
|
});
|
||||||
return output;
|
return output;
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
output += `
|
output += `
|
||||||
<a class=photo href="${data.etudiant.fiche_url}">
|
<a class=photo href="${data.etudiant.fiche_url}">
|
||||||
<img src="${data.etudiant.photo_url || "default_Student.svg"}" alt="photo de l'étudiant" title="fiche de l'étudiant" height="120" border="0">
|
<img src="${
|
||||||
|
data.etudiant.photo_url || "default_Student.svg"
|
||||||
|
}" alt="photo de l'étudiant" title="fiche de l'étudiant" height="120" border="0">
|
||||||
</a>`;
|
</a>`;
|
||||||
/*${data.semestre.groupes.map(groupe => {
|
/*${data.semestre.groupes.map(groupe => {
|
||||||
return `
|
return `
|
||||||
@ -293,16 +318,20 @@ class releveBUT extends HTMLElement {
|
|||||||
}*/
|
}*/
|
||||||
this.shadow.querySelector(".infoSemestre").innerHTML = output;
|
this.shadow.querySelector(".infoSemestre").innerHTML = output;
|
||||||
|
|
||||||
|
|
||||||
/*if(data.semestre.decision_annee?.code){
|
/*if(data.semestre.decision_annee?.code){
|
||||||
this.shadow.querySelector(".decision_annee").innerHTML = "Décision année : " + data.semestre.decision_annee.code + " - " + correspondanceCodes[data.semestre.decision_annee.code];
|
this.shadow.querySelector(".decision_annee").innerHTML = "Décision année : " + data.semestre.decision_annee.code + " - " + correspondanceCodes[data.semestre.decision_annee.code];
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
this.shadow.querySelector(".decision").innerHTML = data.semestre.situation || "";
|
this.shadow.querySelector(".decision").innerHTML =
|
||||||
|
data.semestre.situation || "";
|
||||||
/*if (data.semestre.decision?.code) {
|
/*if (data.semestre.decision?.code) {
|
||||||
this.shadow.querySelector(".decision").innerHTML = "Décision jury: " + (data.semestre.decision?.code || "");
|
this.shadow.querySelector(".decision").innerHTML = "Décision jury: " + (data.semestre.decision?.code || "");
|
||||||
}*/
|
}*/
|
||||||
this.shadow.querySelector("#ects_tot").innerHTML = "ECTS : " + (data.semestre.ECTS?.acquis ?? "-") + " / " + (data.semestre.ECTS?.total ?? "-");
|
this.shadow.querySelector("#ects_tot").innerHTML =
|
||||||
|
"ECTS : " +
|
||||||
|
(data.semestre.ECTS?.acquis ?? "-") +
|
||||||
|
" / " +
|
||||||
|
(data.semestre.ECTS?.total ?? "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************/
|
/*******************************/
|
||||||
@ -313,14 +342,15 @@ class releveBUT extends HTMLElement {
|
|||||||
/* Fusion et tri des UE et UE capitalisées */
|
/* Fusion et tri des UE et UE capitalisées */
|
||||||
let fusionUE = [
|
let fusionUE = [
|
||||||
...Object.entries(data.ues),
|
...Object.entries(data.ues),
|
||||||
...Object.entries(data.ues_capitalisees)
|
...Object.entries(data.ues_capitalisees),
|
||||||
].sort((a, b) => {
|
].sort((a, b) => {
|
||||||
return a[1].numero - b[1].numero
|
return a[1].numero - b[1].numero;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Affichage */
|
/* Affichage */
|
||||||
fusionUE.forEach(([ue, dataUE]) => {
|
fusionUE.forEach(([ue, dataUE]) => {
|
||||||
if (dataUE.type == 1) { // UE Sport / Bonus
|
if (dataUE.type == 1) {
|
||||||
|
// UE Sport / Bonus
|
||||||
output += `
|
output += `
|
||||||
<div>
|
<div>
|
||||||
<div class="ue ueBonus">
|
<div class="ue ueBonus">
|
||||||
@ -335,21 +365,29 @@ class releveBUT extends HTMLElement {
|
|||||||
<div>
|
<div>
|
||||||
<div class="ue ${dataUE.date_capitalisation ? "capitalisee" : ""}">
|
<div class="ue ${dataUE.date_capitalisation ? "capitalisee" : ""}">
|
||||||
<h3>
|
<h3>
|
||||||
${ue}${(dataUE.titre) ? " - " + dataUE.titre : ""}
|
${ue}${dataUE.titre ? " - " + dataUE.titre : ""}
|
||||||
</h3>
|
</h3>
|
||||||
<div>
|
<div>
|
||||||
<div class=moyenne>Moyenne : ${dataUE.moyenne?.value || dataUE.moyenne || "-"}</div>
|
<div class=moyenne>Moyenne : ${
|
||||||
<div class=ue_rang>Rang : ${dataUE.moyenne?.rang} / ${dataUE.moyenne?.total}</div>
|
dataUE.moyenne?.value || dataUE.moyenne || "-"
|
||||||
|
}</div>
|
||||||
|
<div class=ue_rang>Rang : ${dataUE.moyenne?.rang} / ${
|
||||||
|
dataUE.moyenne?.total
|
||||||
|
}</div>
|
||||||
<div class=info>`;
|
<div class=info>`;
|
||||||
if (!dataUE.date_capitalisation) {
|
if (!dataUE.date_capitalisation) {
|
||||||
output += ` Bonus : ${dataUE.bonus || 0} -
|
output += ` Bonus : ${dataUE.bonus || 0} -
|
||||||
Malus : ${dataUE.malus || 0}`;
|
Malus : ${dataUE.malus || 0}`;
|
||||||
} else {
|
} else {
|
||||||
output += ` le ${this.ISOToDate(dataUE.date_capitalisation.split("T")[0])} <a href="${dataUE.bul_orig_url}">dans ce semestre</a>`;
|
output += ` le ${this.ISOToDate(
|
||||||
|
dataUE.date_capitalisation.split("T")[0]
|
||||||
|
)} <a href="${dataUE.bul_orig_url}">dans ce semestre</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
output += ` <span class=ects> -
|
output += ` <span class=ects> -
|
||||||
ECTS : ${dataUE.ECTS?.acquis ?? "-"} / ${dataUE.ECTS?.total ?? "-"}
|
ECTS : ${dataUE.ECTS?.acquis ?? "-"} / ${
|
||||||
|
dataUE.ECTS?.total ?? "-"
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
@ -384,7 +422,7 @@ class releveBUT extends HTMLElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
ueSport(modules) {
|
ueSport(modules) {
|
||||||
@ -400,8 +438,8 @@ class releveBUT extends HTMLElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +447,9 @@ class releveBUT extends HTMLElement {
|
|||||||
/* Evaluations */
|
/* Evaluations */
|
||||||
/*******************************/
|
/*******************************/
|
||||||
showEvaluations(data) {
|
showEvaluations(data) {
|
||||||
this.shadow.querySelector(".evaluations").innerHTML = this.module(data.ressources);
|
this.shadow.querySelector(".evaluations").innerHTML = this.module(
|
||||||
|
data.ressources
|
||||||
|
);
|
||||||
this.shadow.querySelector(".sae").innerHTML += this.module(data.saes);
|
this.shadow.querySelector(".sae").innerHTML += this.module(data.saes);
|
||||||
}
|
}
|
||||||
module(module) {
|
module(module) {
|
||||||
@ -420,7 +460,9 @@ class releveBUT extends HTMLElement {
|
|||||||
<div class=module>
|
<div class=module>
|
||||||
<h3>${this.URL(content.url, `${numero} - ${content.titre}`)}</h3>
|
<h3>${this.URL(content.url, `${numero} - ${content.titre}`)}</h3>
|
||||||
<div>
|
<div>
|
||||||
<div class=moyenne>Moyenne indicative : ${content.moyenne.value}</div>
|
<div class=moyenne>Moyenne indicative : ${
|
||||||
|
content.moyenne.value
|
||||||
|
}</div>
|
||||||
<div class=info>
|
<div class=info>
|
||||||
Classe : ${content.moyenne.moy} -
|
Classe : ${content.moyenne.moy} -
|
||||||
Max : ${content.moyenne.max} -
|
Max : ${content.moyenne.max} -
|
||||||
@ -435,7 +477,7 @@ class releveBUT extends HTMLElement {
|
|||||||
${this.evaluation(content.evaluations)}
|
${this.evaluation(content.evaluations)}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,16 +496,18 @@ class releveBUT extends HTMLElement {
|
|||||||
<div>Max. promo.</div><div>${evaluation.note.max}</div>
|
<div>Max. promo.</div><div>${evaluation.note.max}</div>
|
||||||
<div>Moy. promo.</div><div>${evaluation.note.moy}</div>
|
<div>Moy. promo.</div><div>${evaluation.note.moy}</div>
|
||||||
<div>Min. promo.</div><div>${evaluation.note.min}</div>
|
<div>Min. promo.</div><div>${evaluation.note.min}</div>
|
||||||
${Object.entries(evaluation.poids).map(([UE, poids]) => {
|
${Object.entries(evaluation.poids)
|
||||||
|
.map(([UE, poids]) => {
|
||||||
return `
|
return `
|
||||||
<div>Poids ${UE}</div>
|
<div>Poids ${UE}</div>
|
||||||
<div>${poids}</div>
|
<div>${poids}</div>
|
||||||
`;
|
`;
|
||||||
}).join("")}
|
})
|
||||||
|
.join("")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +522,6 @@ class releveBUT extends HTMLElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************/
|
/********************/
|
||||||
/* Fonctions d'aide */
|
/* Fonctions d'aide */
|
||||||
/********************/
|
/********************/
|
||||||
@ -491,15 +534,17 @@ class releveBUT extends HTMLElement {
|
|||||||
}
|
}
|
||||||
civilite(txt) {
|
civilite(txt) {
|
||||||
switch (txt) {
|
switch (txt) {
|
||||||
case "M": return "M.";
|
case "M":
|
||||||
case "F": return "Mme";
|
return "M.";
|
||||||
default: return "";
|
case "F":
|
||||||
|
return "Mme";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ISOToDate(ISO) {
|
ISOToDate(ISO) {
|
||||||
return ISO.split("-").reverse().join("/");
|
return ISO.split("-").reverse().join("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
customElements.define('releve-but', releveBUT);
|
customElements.define("releve-but", releveBUT);
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
<b>Absences</b>
|
<b>Absences</b>
|
||||||
{% if sco.etud_cur_sem %}
|
{% if sco.etud_cur_sem %}
|
||||||
<span title="absences du {{ sco.etud_cur_sem['date_debut'] }}
|
<span title="absences du {{ sco.etud_cur_sem['date_debut'] }}
|
||||||
au {{ sco.etud_cur_sem['date_fin'] }}">(1/2 j.)
|
au {{ sco.etud_cur_sem['date_fin'] }}">({{sco.prefs["assi_metrique"]}})
|
||||||
<br />{{sco.nbabsjust}} J., {{sco.nbabsnj}} N.J.</span>
|
<br />{{sco.nbabsjust}} J., {{sco.nbabsnj}} N.J.</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -72,10 +72,13 @@ class ScoData:
|
|||||||
ins = self.etud.inscription_courante()
|
ins = self.etud.inscription_courante()
|
||||||
if ins:
|
if ins:
|
||||||
self.etud_cur_sem = ins.formsemestre
|
self.etud_cur_sem = ins.formsemestre
|
||||||
self.nbabs, self.nbabsjust = sco_abs.get_abs_count_in_interval(
|
self.nbabs, self.nbabsjust = sco_abs.get_assiduites_count_in_interval(
|
||||||
etud.id,
|
etud.id,
|
||||||
self.etud_cur_sem.date_debut.isoformat(),
|
self.etud_cur_sem.date_debut.isoformat(),
|
||||||
self.etud_cur_sem.date_fin.isoformat(),
|
self.etud_cur_sem.date_fin.isoformat(),
|
||||||
|
scu.translate_assiduites_metric(
|
||||||
|
sco_preferences.get_preference("assi_metrique")
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.nbabsnj = self.nbabs - self.nbabsjust
|
self.nbabsnj = self.nbabs - self.nbabsjust
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user