"""ScoDoc 9 models : Formations """ from app import db from app.models import SHORT_STR_LEN from app.scodoc import notesdb as ndb from app.scodoc import sco_utils as scu from app.scodoc import sco_codes_parcours from app.comp import df_cache class Formation(db.Model): """Programme pédagogique d'une formation""" __tablename__ = "notes_formations" __table_args__ = (db.UniqueConstraint("dept_id", "acronyme", "titre", "version"),) id = db.Column(db.Integer, primary_key=True) formation_id = db.synonym("id") dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True) acronyme = db.Column(db.Text(), nullable=False) titre = db.Column(db.Text(), nullable=False) titre_officiel = db.Column(db.Text(), nullable=False) version = db.Column(db.Integer, default=1, server_default="1") formation_code = db.Column( db.String(SHORT_STR_LEN), server_default=db.text("notes_newid_fcod()"), nullable=False, ) # nb: la fonction SQL notes_newid_fcod doit être créée à part type_parcours = db.Column(db.Integer, default=0, server_default="0") code_specialite = db.Column(db.String(SHORT_STR_LEN)) # Optionnel, pour les formations type BUT referentiel_competence_id = db.Column( db.Integer, db.ForeignKey("apc_referentiel_competences.id") ) ues = db.relationship("UniteEns", backref="formation", lazy="dynamic") formsemestres = db.relationship("FormSemestre", lazy="dynamic", backref="formation") ues = db.relationship("UniteEns", lazy="dynamic", backref="formation") modules = db.relationship("Module", lazy="dynamic", backref="formation") def __repr__(self): return f"<{self.__class__.__name__}(id={self.id}, dept_id={self.dept_id}, acronyme='{self.acronyme}')>" def to_dict(self): e = dict(self.__dict__) e.pop("_sa_instance_state", None) # ScoDoc7 output_formators: (backward compat) e["formation_id"] = self.id return e def get_parcours(self): """get l'instance de TypeParcours de cette formation""" return sco_codes_parcours.get_parcours_from_code(self.type_parcours) def is_apc(self): "True si formation APC avec SAE (BUT)" return self.get_parcours().APC_SAE def get_module_coefs(self, semestre_idx: int = None): """Les coefs des modules vers les UE (accès via cache)""" from app.comp import moy_ue if semestre_idx is None: key = f"{self.id}" else: key = f"{self.id}.{semestre_idx}" modules_coefficients = df_cache.ModuleCoefsCache.get(key) if modules_coefficients is None: modules_coefficients, _, _ = moy_ue.df_load_module_coefs( self.id, semestre_idx ) df_cache.ModuleCoefsCache.set(key, modules_coefficients) return modules_coefficients def invalidate_module_coefs(self, semestre_idx: int = None): """Invalide les coefficients de modules cachés. Si semestre_idx est None, invalide tous les semestres, sinon invalide le semestre indiqué et le cache de la formation. """ if semestre_idx is None: keys = {f"{self.id}.{m.semestre_id}" for m in self.modules} else: keys = f"{self.id}.{semestre_idx}" df_cache.ModuleCoefsCache.delete_many(keys | {f"{self.id}"}) class Matiere(db.Model): """Matières: regroupe les modules d'une UE La matière a peu d'utilité en dehors de la présentation des modules d'une UE. """ __tablename__ = "notes_matieres" __table_args__ = (db.UniqueConstraint("ue_id", "titre"),) id = db.Column(db.Integer, primary_key=True) matiere_id = db.synonym("id") ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id")) titre = db.Column(db.Text()) numero = db.Column(db.Integer) # ordre de présentation modules = db.relationship("Module", lazy="dynamic", backref="matiere")