ScoDoc-PE/app/models/assiduites.py

197 lines
5.4 KiB
Python

# -*- coding: UTF-8 -*
"""Gestion de l'assiduité (assiduités + justificatifs)
"""
from app import db
from app.models import ModuleImpl
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre
from app.scodoc.sco_utils import EtatAssiduite
from datetime import datetime
from typing import Tuple, List
class Assiduite(db.Model):
"""
Représente une assiduité:
- une plage horaire lié à un état et un étudiant
- un module si spécifiée
"""
__tablename__ = "assiduites"
id = db.Column(db.Integer, primary_key=True)
assiduiteid = db.synonym("id")
date_debut = db.Column(
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
)
date_fin = db.Column(
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
)
moduleimpl_id = db.Column(
db.Integer,
db.ForeignKey("notes_moduleimpl.id", ondelete="SET NULL"),
)
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id", ondelete="CASCADE"),
index=True,
nullable=False,
)
etat = db.Column(db.Integer, nullable=False)
def to_dict(self) -> dict:
data = {
"assiduiteid": self.assiduiteid,
"etudid": self.etudid,
"moduleimpl_id": self.moduleimpl_id,
"date_debut": self.date_debut,
"date_fin": self.date_fin,
"etat": self.etat,
}
return data
@classmethod
def create_assiduite(
cls,
etud: Identite,
date_debut: datetime,
date_fin: datetime,
etat: EtatAssiduite,
module: int or None = None or int,
) -> object or int:
"Créer une nouvelle assiduité pour l'étudiant"
# Vérification de non duplication des périodes
assiduites: List[Assiduite] = etud.assiduites.all()
assiduites = [
ass
for ass in assiduites
if verif_interval((date_debut, date_fin), (ass.date_debut, ass.date_fin))
]
if len(assiduites) != 0:
return 1
if module is not None:
# Vérification de l'existance du module pour l'étudiant
if cls.verif_moduleimpl(module, etud):
nouv_assiduite = Assiduite(
date_debut=date_debut.isoformat(),
date_fin=date_fin.isoformat(),
etat=etat,
etudiant=etud,
moduleimpl_id=module,
)
else:
return 2
else:
nouv_assiduite = Assiduite(
date_debut=date_debut.isoformat(),
date_fin=date_fin.isoformat(),
etat=etat,
etudiant=etud,
)
db.session.add(nouv_assiduite)
db.session.commit()
return nouv_assiduite
@staticmethod
def verif_moduleimpl(moduleimpl_id: int, etud: Identite or int) -> bool:
"""
Vérifie si l'étudiant est bien inscrit au moduleimpl
Retourne Vrai si c'est le cas, faux sinon
"""
# -> get obj module impl -> get obj formsemestres -> query etuds avec etuid -> si vide = Error sinon good
module: ModuleImpl = ModuleImpl.query.filter_by(
moduleimpl_id=moduleimpl_id
).first()
if module is None:
retour = False
semestre: FormSemestre = FormSemestre.query.filter_by(
id=module.formsemestre_id
).first()
if semestre is None:
retour = False
etudiants: List[Identite] = semestre.etuds.all()
if type(etud) is Identite:
retour = etud in etudiants
else:
retour = etud in [e.id for e in etudiants]
return retour
class Justificatif(db.Model):
"""
Représente un justificatif:
- une plage horaire lié à un état et un étudiant
- une raison si spécifiée
- un fichier si spécifié
"""
__tablename__ = "justificatifs"
justifid = db.Column(db.Integer, primary_key=True)
date_debut = db.Column(
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
)
date_fin = db.Column(
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
)
etudid = db.Column(
db.Integer,
db.ForeignKey("identite.id", ondelete="CASCADE"),
index=True,
nullable=False,
)
etat = db.Column(
db.Integer,
)
raison = db.Column(db.Text())
fichier = db.Column(db.Integer())
def to_dict(self) -> dict:
data = {
"justifid": self.assiduiteid,
"etudid": self.etudid,
"date_debut": self.date_debut,
"date_fin": self.date_fin,
"etat": self.etat,
"raison": self.raison,
"fichier": self.fichier,
}
return data
def verif_interval(periode: Tuple[datetime], interval: Tuple[datetime]) -> bool:
"""
Vérifie si une période est comprise dans un interval, chevauche l'interval ou comprend l'interval
Retourne Vrai si c'est le cas, faux sinon
"""
p_deb, p_fin = periode
i_deb, i_fin = interval
from app.scodoc.intervals import intervalmap
i = intervalmap()
p = intervalmap()
i[:] = 0
p[:] = 0
i[i_deb:i_fin] = 1
p[p_deb:p_fin] = 1
res: int = sum((i[p_deb], i[p_fin], p[i_deb], p[i_fin]))
return res > 0