2021-12-08 22:33:32 +01:00
|
|
|
"""ScoDoc 9 models : Unités d'Enseignement (UE)
|
|
|
|
"""
|
|
|
|
|
|
|
|
from app import db
|
|
|
|
from app.models import APO_CODE_STR_LEN
|
|
|
|
from app.models import SHORT_STR_LEN
|
|
|
|
from app.scodoc import sco_utils as scu
|
|
|
|
|
|
|
|
|
|
|
|
class UniteEns(db.Model):
|
|
|
|
"""Unité d'Enseignement (UE)"""
|
|
|
|
|
|
|
|
__tablename__ = "notes_ue"
|
|
|
|
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
ue_id = db.synonym("id")
|
|
|
|
formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id"))
|
|
|
|
acronyme = db.Column(db.Text(), nullable=False)
|
|
|
|
numero = db.Column(db.Integer) # ordre de présentation
|
|
|
|
titre = db.Column(db.Text())
|
|
|
|
# Le semestre_idx n'est pas un id mais le numéro du semestre: 1, 2, ...
|
|
|
|
# En ScoDoc7 et pour les formations classiques, il est NULL
|
|
|
|
# (le numéro du semestre étant alors déterminé par celui des modules de l'UE)
|
|
|
|
# Pour les formations APC, il est obligatoire (de 1 à 6 pour le BUT):
|
|
|
|
semestre_idx = db.Column(db.Integer, nullable=True, index=True)
|
|
|
|
# Type d'UE: 0 normal ("fondamentale"), 1 "sport", 2 "projet et stage (LP)",
|
|
|
|
# 4 "élective"
|
|
|
|
type = db.Column(db.Integer, default=0, server_default="0")
|
|
|
|
# Les UE sont "compatibles" (pour la capitalisation) ssi elles ont ^m code
|
|
|
|
# note: la fonction SQL notes_newid_ucod doit être créée à part
|
|
|
|
ue_code = db.Column(
|
|
|
|
db.String(SHORT_STR_LEN),
|
|
|
|
server_default=db.text("notes_newid_ucod()"),
|
|
|
|
nullable=False,
|
|
|
|
)
|
|
|
|
ects = db.Column(db.Float) # nombre de credits ECTS
|
|
|
|
is_external = db.Column(db.Boolean(), default=False, server_default="false")
|
|
|
|
# id de l'element pedagogique Apogee correspondant:
|
|
|
|
code_apogee = db.Column(db.String(APO_CODE_STR_LEN))
|
|
|
|
# coef UE, utilise seulement si l'option use_ue_coefs est activée:
|
|
|
|
coefficient = db.Column(db.Float)
|
|
|
|
|
2022-01-25 10:45:13 +01:00
|
|
|
color = db.Column(db.Text())
|
|
|
|
|
2022-04-29 08:17:04 +02:00
|
|
|
# BUT
|
|
|
|
niveau_competence_id = db.Column(db.Integer, db.ForeignKey("apc_niveau.id"))
|
|
|
|
niveau_competence = db.relationship("ApcNiveau", back_populates="ues")
|
|
|
|
|
2021-12-08 22:33:32 +01:00
|
|
|
# relations
|
|
|
|
matieres = db.relationship("Matiere", lazy="dynamic", backref="ue")
|
|
|
|
modules = db.relationship("Module", lazy="dynamic", backref="ue")
|
|
|
|
|
|
|
|
def __repr__(self):
|
2022-01-08 14:01:16 +01:00
|
|
|
return f"""<{self.__class__.__name__}(id={self.id}, formation_id={
|
|
|
|
self.formation_id}, acronyme='{self.acronyme}', semestre_idx={
|
|
|
|
self.semestre_idx} {
|
|
|
|
'EXTERNE' if self.is_external else ''})>"""
|
2021-12-08 22:33:32 +01:00
|
|
|
|
|
|
|
def to_dict(self):
|
2022-02-28 11:00:24 +01:00
|
|
|
"""as a dict, with the same conversions as in ScoDoc7
|
|
|
|
(except ECTS: keep None)
|
|
|
|
"""
|
2021-12-08 22:33:32 +01:00
|
|
|
e = dict(self.__dict__)
|
|
|
|
e.pop("_sa_instance_state", None)
|
|
|
|
# ScoDoc7 output_formators
|
|
|
|
e["ue_id"] = self.id
|
|
|
|
e["numero"] = e["numero"] if e["numero"] else 0
|
2022-02-28 11:00:24 +01:00
|
|
|
e["ects"] = e["ects"]
|
2021-12-08 22:33:32 +01:00
|
|
|
e["coefficient"] = e["coefficient"] if e["coefficient"] else 0.0
|
2022-02-08 23:58:02 +01:00
|
|
|
e["code_apogee"] = e["code_apogee"] or "" # pas de None
|
2021-12-08 22:33:32 +01:00
|
|
|
return e
|
|
|
|
|
|
|
|
def is_locked(self):
|
|
|
|
"""True if UE should not be modified
|
|
|
|
(contains modules used in a locked formsemestre)
|
|
|
|
"""
|
|
|
|
# XXX todo : à ré-écrire avec SQLAlchemy
|
|
|
|
from app.scodoc import sco_edit_ue
|
|
|
|
|
|
|
|
return sco_edit_ue.ue_is_locked(self.id)
|
|
|
|
|
2022-06-08 17:42:52 +02:00
|
|
|
def can_be_deleted(self) -> bool:
|
|
|
|
"""True si l'UE n'est pas utilisée dans des formsemestre
|
|
|
|
et n'a pas de module rattachés
|
|
|
|
"""
|
|
|
|
# "pas un seul module de cette UE n'a de modimpl...""
|
|
|
|
return (self.modules.count() == 0) or not any(
|
|
|
|
m.modimpls.all() for m in self.modules
|
|
|
|
)
|
|
|
|
|
2021-12-08 22:33:32 +01:00
|
|
|
def guess_semestre_idx(self) -> None:
|
|
|
|
"""Lorsqu'on prend une ancienne formation non APC,
|
|
|
|
les UE n'ont pas d'indication de semestre.
|
|
|
|
Cette méthode fixe le semestre en prenant celui du premier module,
|
|
|
|
ou à défaut le met à 1.
|
|
|
|
"""
|
|
|
|
if self.semestre_idx is None:
|
|
|
|
module = self.modules.first()
|
|
|
|
if module is None:
|
|
|
|
self.semestre_idx = 1
|
|
|
|
else:
|
|
|
|
self.semestre_idx = module.semestre_id
|
|
|
|
db.session.add(self)
|
|
|
|
db.session.commit()
|
2021-12-11 16:46:15 +01:00
|
|
|
|
|
|
|
def get_ressources(self):
|
|
|
|
"Liste des modules ressources rattachés à cette UE"
|
|
|
|
return self.modules.filter_by(module_type=scu.ModuleType.RESSOURCE).all()
|
|
|
|
|
|
|
|
def get_saes(self):
|
|
|
|
"Liste des modules SAE rattachés à cette UE"
|
|
|
|
return self.modules.filter_by(module_type=scu.ModuleType.SAE).all()
|
|
|
|
|
|
|
|
def get_modules_not_apc(self):
|
|
|
|
"Listes des modules non SAE et non ressource (standards, mais aussi bonus...)"
|
|
|
|
return self.modules.filter(
|
|
|
|
(Module.module_type != scu.ModuleType.SAE),
|
|
|
|
(Module.module_type != scu.ModuleType.RESSOURCE),
|
|
|
|
).all()
|