# -*- 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