forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -1097,10 +1097,12 @@ def mail_bulletin(formsemestre_id, infos, pdfdata, filename, recipient_addr):
|
|||||||
hea = ""
|
hea = ""
|
||||||
|
|
||||||
if sco_preferences.get_preference("bul_mail_list_abs"):
|
if sco_preferences.get_preference("bul_mail_list_abs"):
|
||||||
hea += "\n\n" + "(LISTE D'ABSENCES NON DISPONIBLE)" # XXX TODO-ASSIDUITE
|
from app.views.assiduites import generate_bul_list
|
||||||
# sco_abs_views.ListeAbsEtud(
|
|
||||||
# etud["etudid"], with_evals=False, format="text"
|
etud_identite: Identite = Identite.get_etud(etud["etudid"])
|
||||||
# )
|
form_semestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
|
hea += "\n\n"
|
||||||
|
hea += generate_bul_list(etud_identite, form_semestre)
|
||||||
|
|
||||||
subject = f"""Relevé de notes de {etud["nomprenom"]}"""
|
subject = f"""Relevé de notes de {etud["nomprenom"]}"""
|
||||||
recipients = [recipient_addr]
|
recipients = [recipient_addr]
|
||||||
|
@ -1750,6 +1750,17 @@ class BasePreferences:
|
|||||||
"category": "bul_mail",
|
"category": "bul_mail",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"bul_mail_list_abs_nb",
|
||||||
|
{
|
||||||
|
"initvalue": 10,
|
||||||
|
"title": "Nombre maximum de dates par catégorie",
|
||||||
|
"explanation": "dans la liste des absences dans le mail envoyant le bulletin de notes (catégories : abs,abs_just, retard,justificatifs)",
|
||||||
|
"type": "int",
|
||||||
|
"size": 3,
|
||||||
|
"category": "bul_mail",
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"bul_mail_contact_addr",
|
"bul_mail_contact_addr",
|
||||||
{
|
{
|
||||||
|
16
app/templates/assiduites/widgets/liste_assiduites_mail.j2
Normal file
16
app/templates/assiduites/widgets/liste_assiduites_mail.j2
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<=== Assiduité ===>
|
||||||
|
--- Absences non justifiées {{stats.absent[metric] - stats.absent.justifie[metric]}} ({{metrique}}) ---
|
||||||
|
{% for assi in abs_nj %}- Absence non just. {{assi.date}}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
--- Absences justifiées {{stats.absent.justifie[metric]}} ({{metrique}}) ---
|
||||||
|
{% for assi in abs_j %}- Absence just. {{assi.date}}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
--- Retard {{stats.retard[metric]}} ({{metrique}}) ---
|
||||||
|
{% for assi in retards %}- Retard {{assi.date}}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
--- Justificatif ---
|
||||||
|
{% for justi in justifs %}- Justificatif {{justi.date}} {{justi.raison}} : {{justi.etat}}
|
||||||
|
{% endfor %}
|
@ -16,6 +16,7 @@ from app.models import (
|
|||||||
Identite,
|
Identite,
|
||||||
ScoDocSiteConfig,
|
ScoDocSiteConfig,
|
||||||
Assiduite,
|
Assiduite,
|
||||||
|
Justificatif,
|
||||||
Departement,
|
Departement,
|
||||||
FormSemestreInscription,
|
FormSemestreInscription,
|
||||||
Evaluation,
|
Evaluation,
|
||||||
@ -1082,7 +1083,7 @@ def signal_evaluation_abs(etudid: int = None, evaluation_id: int = None):
|
|||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
duplication="oui",
|
duplication="oui",
|
||||||
)
|
)
|
||||||
raise ScoValueError(msg, dest)
|
raise ScoValueError(msg, dest) from see
|
||||||
|
|
||||||
db.session.add(assiduite_unique)
|
db.session.add(assiduite_unique)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@ -1098,9 +1099,81 @@ def signal_evaluation_abs(etudid: int = None, evaluation_id: int = None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_bul_list(etud: Identite, semestre: FormSemestre) -> str:
|
||||||
|
"""Génère la liste des assiduités d'un étudiant pour le bulletin mail"""
|
||||||
|
metrique: str = scu.translate_assiduites_metric(
|
||||||
|
sco_preferences.get_preference("assi_metrique", formsemestre_id=semestre.id),
|
||||||
|
)
|
||||||
|
|
||||||
|
max_nb: int = int(
|
||||||
|
sco_preferences.get_preference(
|
||||||
|
"bul_mail_list_abs_nb", formsemestre_id=semestre.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assiduites = scass.filter_by_formsemestre(
|
||||||
|
etud.assiduites, Assiduite, semestre
|
||||||
|
).order_by(Assiduite.entry_date.desc())
|
||||||
|
justificatifs = scass.filter_by_formsemestre(
|
||||||
|
etud.justificatifs, Justificatif, semestre
|
||||||
|
).order_by(Justificatif.entry_date.desc())
|
||||||
|
|
||||||
|
stats: dict = scass.get_assiduites_stats(
|
||||||
|
assiduites, metric=metrique, filtered={"split": True}
|
||||||
|
)
|
||||||
|
|
||||||
|
abs_j: list[str] = [
|
||||||
|
{"date": _get_date_str(assi.date_debut, assi.date_fin)}
|
||||||
|
for assi in assiduites
|
||||||
|
if assi.etat == scu.EtatAssiduite.ABSENT and assi.est_just is True
|
||||||
|
]
|
||||||
|
abs_nj: list[str] = [
|
||||||
|
{"date": _get_date_str(assi.date_debut, assi.date_fin)}
|
||||||
|
for assi in assiduites
|
||||||
|
if assi.etat == scu.EtatAssiduite.ABSENT and assi.est_just is False
|
||||||
|
]
|
||||||
|
retards: list[str] = [
|
||||||
|
{"date": _get_date_str(assi.date_debut, assi.date_fin)}
|
||||||
|
for assi in assiduites
|
||||||
|
if assi.etat == scu.EtatAssiduite.RETARD
|
||||||
|
]
|
||||||
|
|
||||||
|
justifs: list[dict[str, str]] = [
|
||||||
|
{
|
||||||
|
"date": _get_date_str(justi.date_debut, justi.date_fin),
|
||||||
|
"raison": "" if justi.raison is None else justi.raison,
|
||||||
|
"etat": {
|
||||||
|
scu.EtatJustificatif.VALIDE: "justificatif valide",
|
||||||
|
scu.EtatJustificatif.NON_VALIDE: "justificatif invalide",
|
||||||
|
scu.EtatJustificatif.ATTENTE: "justificatif en attente de validation",
|
||||||
|
scu.EtatJustificatif.MODIFIE: "justificatif ayant été modifié",
|
||||||
|
}.get(justi.etat),
|
||||||
|
}
|
||||||
|
for justi in justificatifs
|
||||||
|
]
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"assiduites/widgets/liste_assiduites_mail.j2",
|
||||||
|
abs_j=abs_j[:max_nb],
|
||||||
|
abs_nj=abs_nj[:max_nb],
|
||||||
|
retards=retards[:max_nb],
|
||||||
|
justifs=justifs[:max_nb],
|
||||||
|
stats=stats,
|
||||||
|
metrique=scu.translate_assiduites_metric(metrique, short=True, inverse=False),
|
||||||
|
metric=metrique,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# --- Fonctions internes ---
|
# --- Fonctions internes ---
|
||||||
|
|
||||||
|
|
||||||
|
def _get_date_str(deb: datetime.datetime, fin: datetime.datetime) -> str:
|
||||||
|
if deb.date() == fin.date():
|
||||||
|
temps = deb.strftime("%d/%m/%Y %H:%M").split(" ") + [fin.strftime("%H:%M")]
|
||||||
|
return f"le {temps[0]} de {temps[1]} à {temps[2]}"
|
||||||
|
return f'du {deb.strftime("%d/%m/%Y %H:%M")} au {fin.strftime("%d/%m/%Y %H:%M")}'
|
||||||
|
|
||||||
|
|
||||||
def _get_days_between_dates(deb: str, fin: str):
|
def _get_days_between_dates(deb: str, fin: str):
|
||||||
if deb is None or fin is None:
|
if deb is None or fin is None:
|
||||||
return "null"
|
return "null"
|
||||||
|
Loading…
Reference in New Issue
Block a user