1
0
forked from ScoDoc/ScoDoc

Assiduite: notifications mail. Fix #789

This commit is contained in:
Emmanuel Viennet 2023-10-09 23:01:19 +02:00
parent 3ecbe5128e
commit 6c3d13b3e1
3 changed files with 63 additions and 44 deletions

View File

@ -559,7 +559,7 @@ def _create_singular(
data: dict,
etud: Identite,
) -> tuple[int, object]:
"""TODO: documenter"""
"""TODO @iziram: documenter"""
errors: list[str] = []
# -- vérifications de l'objet json --
@ -630,6 +630,7 @@ def _create_singular(
description=desc,
user_id=current_user.id,
external_data=external_data,
notify_mail=True,
)
db.session.add(nouv_assiduite)

View File

@ -7,6 +7,7 @@ from app import db, log
from app.models import ModuleImpl, Scolog
from app.models.etudiants import Identite
from app.auth.models import User
from app.scodoc import sco_abs_notification
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_utils import (
EtatAssiduite,
@ -130,13 +131,14 @@ class Assiduite(db.Model):
user_id: int = None,
est_just: bool = False,
external_data: dict = None,
notify_mail=False,
) -> "Assiduite":
"""Créer une nouvelle assiduité pour l'étudiant"""
# Vérification de non duplication des périodes
assiduites: Query = etud.assiduites
if is_period_conflicting(date_debut, date_fin, assiduites, Assiduite):
raise ScoValueError(
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
"Duplication: la période rentre en conflit avec une plage enregistrée"
)
if not est_just:
@ -147,35 +149,25 @@ class Assiduite(db.Model):
> 0
)
moduleimpl_id = None
if moduleimpl is not None:
# Vérification de l'existence du module pour l'étudiant
# Vérification de l'inscription de l'étudiant
if moduleimpl.est_inscrit(etud):
nouv_assiduite = Assiduite(
date_debut=date_debut,
date_fin=date_fin,
etat=etat,
etudiant=etud,
moduleimpl_id=moduleimpl.id,
description=description,
entry_date=entry_date,
user_id=user_id,
est_just=est_just,
external_data=external_data,
)
moduleimpl_id = moduleimpl.id
else:
raise ScoValueError("L'étudiant n'est pas inscrit au module")
else:
nouv_assiduite = Assiduite(
date_debut=date_debut,
date_fin=date_fin,
etat=etat,
etudiant=etud,
description=description,
entry_date=entry_date,
user_id=user_id,
est_just=est_just,
external_data=external_data,
)
nouv_assiduite = Assiduite(
date_debut=date_debut,
date_fin=date_fin,
description=description,
entry_date=entry_date,
est_just=est_just,
etat=etat,
etudiant=etud,
external_data=external_data,
moduleimpl_id=moduleimpl_id,
user_id=user_id,
)
db.session.add(nouv_assiduite)
log(f"create_assiduite: {etud.id} {nouv_assiduite}")
Scolog.logdb(
@ -183,6 +175,8 @@ class Assiduite(db.Model):
etudid=etud.id,
msg=f"assiduité: {nouv_assiduite}",
)
if notify_mail and etat == EtatAssiduite.ABSENT:
sco_abs_notification.abs_notify(etud.id, nouv_assiduite.date_debut)
return nouv_assiduite

View File

@ -40,17 +40,17 @@ from flask_mail import Message
from app import db
from app import email
from app import log
from app.auth.models import User
from app.models.absences import AbsenceNotification
from app.models.events import Scolog
from app.models.formsemestre import FormSemestre
import app.scodoc.notesdb as ndb
from app.scodoc import sco_etud
from app.scodoc import sco_preferences
from app.scodoc import sco_users
from app.scodoc import sco_utils as scu
def abs_notify(etudid, date):
def abs_notify(etudid: int, date: str | datetime.datetime):
"""Check if notifications are requested and send them
Considère le nombre d'absence dans le semestre courant
(s'il n'y a pas de semestre courant, ne fait rien,
@ -64,18 +64,28 @@ def abs_notify(etudid, date):
nbabs, nbabsjust = sco_assiduites.get_assiduites_count_in_interval(
etudid,
formsemestre.date_debut.isoformat(),
formsemestre.date_fin.isoformat(),
scu.translate_assiduites_metric(
metrique=scu.translate_assiduites_metric(
sco_preferences.get_preference(
"assi_metrique", formsemestre.formsemestre_id
)
),
date_debut=datetime.datetime.combine(
formsemestre.date_debut, datetime.datetime.min.time()
),
date_fin=datetime.datetime.combine(
formsemestre.date_fin, datetime.datetime.min.time()
),
)
do_abs_notify(formsemestre, etudid, date, nbabs, nbabsjust)
def do_abs_notify(formsemestre: FormSemestre, etudid, date, nbabs, nbabsjust):
def do_abs_notify(
formsemestre: FormSemestre,
etudid: int,
date: str | datetime.datetime,
nbabs: int,
nbabsjust: int,
):
"""Given new counts of absences, check if notifications are requested and send them."""
# prefs fallback to global pref if sem is None:
if formsemestre:
@ -138,8 +148,13 @@ def abs_notify_send(destinations, etudid, msg, nbabs, nbabsjust, formsemestre_id
def abs_notify_get_destinations(
formsemestre: FormSemestre, prefs, etudid, date, nbabs, nbabsjust
) -> set:
formsemestre: FormSemestre,
prefs: dict,
etudid: int,
date: str | datetime.datetime,
nbabs: int,
nbabsjust: int,
) -> set[str]:
"""Returns set of destination emails to be notified"""
destinations = [] # list of email address to notify
@ -165,9 +180,9 @@ def abs_notify_get_destinations(
if prefs["abs_notify_respeval"]:
mods = mod_with_evals_at_date(date, etudid)
for mod in mods:
u = sco_users.user_info(mod["responsable_id"])
if u["email"]:
destinations.append(u["email"])
u: User = db.session.get(User, mod["responsable_id"])
if u is not None and u.is_active and u.email:
destinations.append(u.email)
# uniq
destinations = set(destinations)
@ -267,9 +282,11 @@ def abs_notification_message(
return msg
def retreive_current_formsemestre(etudid: int, cur_date) -> Optional[FormSemestre]:
def retreive_current_formsemestre(
etudid: int, cur_date: str | datetime.date
) -> Optional[FormSemestre]:
"""Get formsemestre dans lequel etudid est (ou était) inscrit a la date indiquée
date est une chaine au format ISO (yyyy-mm-dd)
date est une chaine au format ISO (yyyy-mm-dd) ou un datetime.date
Result: FormSemestre ou None si pas inscrit à la date indiquée
"""
@ -287,10 +304,17 @@ def retreive_current_formsemestre(etudid: int, cur_date) -> Optional[FormSemestr
return formsemestre
def mod_with_evals_at_date(date_abs, etudid):
def mod_with_evals_at_date(
date_abs: str | datetime.datetime, etudid: int
) -> list[dict]:
"""Liste des moduleimpls avec des evaluations à la date indiquée"""
req = """SELECT m.id AS moduleimpl_id, m.*
req = """
SELECT m.id AS moduleimpl_id, m.*
FROM notes_moduleimpl m, notes_evaluation e, notes_moduleimpl_inscription i
WHERE m.id = e.moduleimpl_id AND e.moduleimpl_id = i.moduleimpl_id
AND i.etudid = %(etudid)s AND e.jour = %(date_abs)s"""
WHERE m.id = e.moduleimpl_id
AND e.moduleimpl_id = i.moduleimpl_id
AND i.etudid = %(etudid)s
AND e.date_debut <= %(date_abs)s
AND e.date_fin >= %(date_abs)s
"""
return ndb.SimpleDictFetch(req, {"etudid": etudid, "date_abs": date_abs})