ScoDoc-PE/app/models/departements.py

104 lines
3.8 KiB
Python

# -*- coding: UTF-8 -*
"""ScoDoc models : departements
"""
import re
from app import db
from app.models import SHORT_STR_LEN
from app.models.preferences import ScoPreference
from app.scodoc.sco_exceptions import ScoValueError
VALID_DEPT_EXP = re.compile(r"^[\w@\\\-\.]+$")
class Departement(db.Model):
"""Un département ScoDoc"""
id = db.Column(db.Integer, primary_key=True)
acronym = db.Column(
db.String(SHORT_STR_LEN), nullable=False, index=True, unique=True
) # ne change jamais, voir la pref. DeptName
description = db.Column(db.Text()) # pas utilisé par ScoDoc : voir DeptFullName
date_creation = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
visible = db.Column(
db.Boolean(), nullable=False, default=True, server_default="true"
) # sur page d'accueil
# entreprises = db.relationship("Entreprise", lazy="dynamic", backref="departement")
etudiants = db.relationship(
"Identite",
back_populates="departement",
cascade="all,delete-orphan",
lazy="dynamic",
)
# This means if a Departement is deleted, all related Identite instances are also
# deleted (all,delete). The orphan part means that if an Identite instance becomes
# detached from its parent Departement (for example, by setting my_identite.departement = None),
# it will be deleted.
formations = db.relationship("Formation", lazy="dynamic", backref="departement")
formsemestres = db.relationship(
"FormSemestre", lazy="dynamic", backref="departement"
)
preferences = db.relationship(
"ScoPreference", lazy="dynamic", backref="departement"
)
semsets = db.relationship("NotesSemSet", lazy="dynamic", backref="departement")
referentiels = db.relationship(
"ApcReferentielCompetences", lazy="dynamic", backref="departement"
)
def __repr__(self):
return f"<{self.__class__.__name__}(id={self.id}, acronym='{self.acronym}')>"
def to_dict(self, with_dept_name=True, with_dept_preferences=False):
data = {
"id": self.id,
"acronym": self.acronym,
"description": self.description,
"visible": self.visible,
"date_creation": self.date_creation,
}
if with_dept_name:
pref = ScoPreference.query.filter_by(
dept_id=self.id, name="DeptName"
).first()
data["dept_name"] = pref.value if pref else None
# Ceci n'est pas encore utilisé, mais pourrait être publié
# par l'API après nettoyage des préférences.
if with_dept_preferences:
data["preferences"] = {
p.name: p.value for p in ScoPreference.query.filter_by(dept_id=self.id)
}
return data
@classmethod
def invalid_dept_acronym(cls, dept_acronym: str) -> bool:
"Check that dept_acronym is invalid"
return (
not dept_acronym
or (len(dept_acronym) >= SHORT_STR_LEN)
or not VALID_DEPT_EXP.match(dept_acronym)
)
@classmethod
def from_acronym(cls, acronym):
dept = cls.query.filter_by(acronym=acronym).first_or_404()
return dept
def create_dept(acronym: str, visible=True) -> Departement:
"Create new departement"
if Departement.invalid_dept_acronym(acronym):
raise ScoValueError("acronyme departement invalide")
existing = Departement.query.filter_by(acronym=acronym).count()
if existing:
raise ScoValueError(f"acronyme {acronym} déjà existant")
departement = Departement(acronym=acronym, visible=visible)
p1 = ScoPreference(name="DeptName", value=acronym, departement=departement)
db.session.add(p1)
db.session.add(departement)
db.session.commit()
return departement