forked from ScoDoc/ScoDoc
Add get_instance method to all ScoDoc models
This commit is contained in:
parent
98127e7c1d
commit
24ccd8f9f7
@ -5,6 +5,7 @@
|
||||
|
||||
from flask import abort, g
|
||||
import sqlalchemy
|
||||
import app
|
||||
from app import db
|
||||
|
||||
CODE_STR_LEN = 16 # chaine pour les codes
|
||||
@ -133,11 +134,22 @@ class ScoDocModel(db.Model):
|
||||
return None
|
||||
abort(404, "oid invalide")
|
||||
|
||||
query = (
|
||||
cls.query.filter_by(id=oid, dept_id=g.scodoc_dept_id)
|
||||
if g.scodoc_dept
|
||||
else cls.query.filter_by(id=oid)
|
||||
)
|
||||
if g.scodoc_dept:
|
||||
if hasattr(cls, "_sco_dept_relations"):
|
||||
# Quand dept_id n'est pas dans le modèle courant,
|
||||
# cet attribut indique la liste des tables à joindre pour
|
||||
# obtenir le departement.
|
||||
query = cls.query.filter_by(id=oid)
|
||||
for relation_name in cls._sco_dept_relations:
|
||||
query = query.join(getattr(app.models, relation_name))
|
||||
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||
else:
|
||||
# département accessible dans le modèle courant
|
||||
query = cls.query.filter_by(id=oid, dept_id=g.scodoc_dept_id)
|
||||
else:
|
||||
# Pas de département courant (API non départementale)
|
||||
query = cls.query.filter_by(id=oid)
|
||||
|
||||
if accept_none:
|
||||
return query.first()
|
||||
return query.first_or_404()
|
||||
|
@ -7,7 +7,10 @@ from app import db
|
||||
|
||||
|
||||
class Absence(db.Model):
|
||||
"""une absence (sur une demi-journée)"""
|
||||
"""LEGACY
|
||||
Ce modèle n'est PLUS UTILISE depuis ScoDoc 9.6 et remplacé par assiduité.
|
||||
une absence (sur une demi-journée)
|
||||
"""
|
||||
|
||||
__tablename__ = "absences"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
@ -61,6 +61,8 @@ class ApcValidationRCUE(ScoDocModel):
|
||||
ue2 = db.relationship("UniteEns", foreign_keys=ue2_id)
|
||||
parcour = db.relationship("ApcParcours")
|
||||
|
||||
_sco_dept_relations = ("Identite",) # pour accéder au département
|
||||
|
||||
def __repr__(self):
|
||||
return f"""<{self.__class__.__name__} {self.id} {self.etud} {
|
||||
self.ue1}/{self.ue2}:{self.code!r}>"""
|
||||
@ -154,6 +156,8 @@ class ApcValidationAnnee(ScoDocModel):
|
||||
etud = db.relationship("Identite", backref="apc_validations_annees")
|
||||
formsemestre = db.relationship("FormSemestre", backref="apc_validations_annees")
|
||||
|
||||
_sco_dept_relations = ("Identite",) # pour accéder au département
|
||||
|
||||
def __repr__(self):
|
||||
return f"""<{self.__class__.__name__} {self.id} {self.etud
|
||||
} BUT{self.ordre}/{self.annee_scolaire}:{self.code!r}>"""
|
||||
@ -317,6 +321,8 @@ class ValidationDUT120(ScoDocModel):
|
||||
etud = db.relationship("Identite", backref="validations_dut120")
|
||||
formsemestre = db.relationship("FormSemestre", backref="validations_dut120")
|
||||
|
||||
_sco_dept_relations = ("Identite",) # pour accéder au département
|
||||
|
||||
def __repr__(self):
|
||||
return f"""<ValidationDUT120 {self.etud}>"""
|
||||
|
||||
|
@ -1080,8 +1080,9 @@ class Admission(models.ScoDocModel):
|
||||
return args_dict
|
||||
|
||||
|
||||
# Suivi scolarité / débouchés
|
||||
class ItemSuivi(db.Model):
|
||||
class ItemSuivi(models.ScoDocModel):
|
||||
"""Suivi scolarité / débouchés"""
|
||||
|
||||
__tablename__ = "itemsuivi"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
@ -1093,6 +1094,8 @@ class ItemSuivi(db.Model):
|
||||
item_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
situation = db.Column(db.Text)
|
||||
|
||||
_sco_dept_relations = ("Identite",) # accès au dept_id
|
||||
|
||||
|
||||
class ItemSuiviTag(db.Model):
|
||||
__tablename__ = "itemsuivi_tags"
|
||||
@ -1114,7 +1117,7 @@ itemsuivi_tags_assoc = db.Table(
|
||||
)
|
||||
|
||||
|
||||
class EtudAnnotation(db.Model):
|
||||
class EtudAnnotation(models.ScoDocModel):
|
||||
"""Annotation sur un étudiant"""
|
||||
|
||||
__tablename__ = "etud_annotations"
|
||||
@ -1125,6 +1128,8 @@ class EtudAnnotation(db.Model):
|
||||
author = db.Column(db.Text) # le pseudo (user_name), was zope_authenticated_user
|
||||
comment = db.Column(db.Text)
|
||||
|
||||
_sco_dept_relations = ("Identite",) # accès au dept_id
|
||||
|
||||
def to_dict(self):
|
||||
"""Représentation dictionnaire."""
|
||||
e = dict(self.__dict__)
|
||||
|
@ -60,6 +60,8 @@ class Evaluation(models.ScoDocModel):
|
||||
numero = db.Column(db.Integer, nullable=False, default=0)
|
||||
ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
|
||||
|
||||
_sco_dept_relations = ("ModuleImpl", "FormSemestre") # accès au dept_id
|
||||
|
||||
EVALUATION_NORMALE = 0 # valeurs stockées en base, ne pas changer !
|
||||
EVALUATION_RATTRAPAGE = 1
|
||||
EVALUATION_SESSION2 = 2
|
||||
|
@ -7,7 +7,7 @@ from flask_sqlalchemy.query import Query
|
||||
import app
|
||||
from app import db
|
||||
from app.comp import df_cache
|
||||
from app.models import SHORT_STR_LEN
|
||||
from app.models import ScoDocModel, SHORT_STR_LEN
|
||||
from app.models.but_refcomp import (
|
||||
ApcAnneeParcours,
|
||||
ApcCompetence,
|
||||
@ -23,7 +23,7 @@ from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.codes_cursus import UE_STANDARD
|
||||
|
||||
|
||||
class Formation(db.Model):
|
||||
class Formation(ScoDocModel):
|
||||
"""Programme pédagogique d'une formation"""
|
||||
|
||||
__tablename__ = "notes_formations"
|
||||
@ -297,7 +297,7 @@ class Formation(db.Model):
|
||||
db.session.commit()
|
||||
|
||||
|
||||
class Matiere(db.Model):
|
||||
class Matiere(ScoDocModel):
|
||||
"""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.
|
||||
@ -313,6 +313,7 @@ class Matiere(db.Model):
|
||||
numero = db.Column(db.Integer, nullable=False, default=0) # ordre de présentation
|
||||
|
||||
modules = db.relationship("Module", lazy="dynamic", backref="matiere")
|
||||
_sco_dept_relations = ("UniteEns", "Formation") # accès au dept_id
|
||||
|
||||
def __repr__(self):
|
||||
return f"""<{self.__class__.__name__}(id={self.id}, ue_id={
|
||||
|
@ -54,6 +54,7 @@ class Partition(ScoDocModel):
|
||||
cascade="all, delete-orphan",
|
||||
order_by="GroupDescr.numero, GroupDescr.group_name",
|
||||
)
|
||||
_sco_dept_relations = ("FormSemestre",)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Partition, self).__init__(**kwargs)
|
||||
@ -225,6 +226,11 @@ class GroupDescr(ScoDocModel):
|
||||
numero = db.Column(db.Integer, nullable=False, default=0)
|
||||
"Numero = ordre de presentation"
|
||||
|
||||
_sco_dept_relations = (
|
||||
"Partition",
|
||||
"FormSemestre",
|
||||
)
|
||||
|
||||
etuds = db.relationship(
|
||||
"Identite",
|
||||
secondary="group_membership",
|
||||
|
@ -60,6 +60,8 @@ class ModuleImpl(ScoDocModel):
|
||||
)
|
||||
"enseignants du module (sans le responsable)"
|
||||
|
||||
_sco_dept_relations = ("FormSemestre",) # accès au dept_id
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} {self.id} module={repr(self.module)}>"
|
||||
|
||||
|
@ -75,6 +75,8 @@ class Module(models.ScoDocModel):
|
||||
backref=db.backref("modules", lazy=True),
|
||||
)
|
||||
|
||||
_sco_dept_relations = "Formation" # accès au dept_id
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.ue_coefs = []
|
||||
super(Module, self).__init__(**kwargs)
|
||||
|
@ -5,11 +5,12 @@
|
||||
|
||||
import sqlalchemy as sa
|
||||
from app import db
|
||||
from app import models
|
||||
from app.scodoc import safehtml
|
||||
import app.scodoc.sco_utils as scu
|
||||
|
||||
|
||||
class BulAppreciations(db.Model):
|
||||
class BulAppreciations(models.ScoDocModel):
|
||||
"""Appréciations sur bulletins"""
|
||||
|
||||
__tablename__ = "notes_appreciations"
|
||||
@ -27,6 +28,8 @@ class BulAppreciations(db.Model):
|
||||
author = db.Column(db.Text) # le pseudo (user_name), sans contrainte
|
||||
comment = db.Column(db.Text) # texte libre
|
||||
|
||||
_sco_dept_relations = ("Identite",) # accès au dept_id
|
||||
|
||||
@classmethod
|
||||
def get_appreciations_list(
|
||||
cls, formsemestre_id: int, etudid: int
|
||||
|
@ -3,10 +3,10 @@
|
||||
"""Model : preferences
|
||||
"""
|
||||
|
||||
from app import db
|
||||
from app import db, models
|
||||
|
||||
|
||||
class ScoPreference(db.Model):
|
||||
class ScoPreference(models.ScoDocModel):
|
||||
"""ScoDoc preferences (par département)"""
|
||||
|
||||
__tablename__ = "sco_prefs"
|
||||
@ -19,5 +19,8 @@ class ScoPreference(db.Model):
|
||||
value = db.Column(db.Text())
|
||||
formsemestre_id = db.Column(db.Integer, db.ForeignKey("notes_formsemestre.id"))
|
||||
|
||||
_sco_dept_relations = ("FormSemestre",) # accès au dept_id
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} {self.id} {self.departement.acronym} {self.name}={self.value}>"
|
||||
return f"""<{self.__class__.__name__} {self.id} {self.departement.acronym
|
||||
} {self.name}={self.value}>"""
|
||||
|
@ -767,15 +767,16 @@ def scolars_import_admission(
|
||||
)
|
||||
|
||||
for group_id in group_ids:
|
||||
group = db.session.get(GroupDescr, group_id)
|
||||
group: GroupDescr = GroupDescr.get_instance(group_id)
|
||||
if group.partition.groups_editable:
|
||||
sco_groups.change_etud_group_in_partition(
|
||||
args["etudid"], group
|
||||
)
|
||||
else:
|
||||
elif not group.partition.is_parcours:
|
||||
log("scolars_import_admission: partition non editable")
|
||||
diag.append(
|
||||
f"Attention: partition {group.partition} non editable (ignorée)"
|
||||
f"""Attention: partition {
|
||||
group.partition} (g{group.id}) non editable et ignorée"""
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.7.4"
|
||||
SCOVERSION = "9.7.5"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
@ -267,9 +267,7 @@ class ScoFake(object):
|
||||
responsables = (self.default_user.id,)
|
||||
titre = titre or "sans titre"
|
||||
oid = sco_formsemestre.do_formsemestre_create(locals())
|
||||
oids = sco_formsemestre.do_formsemestre_list(
|
||||
args={"formsemestre_id": oid}
|
||||
) # API inconsistency
|
||||
oids = sco_formsemestre.do_formsemestre_list(args={"formsemestre_id": oid})
|
||||
if not oids:
|
||||
raise ScoValueError("formsemestre not created !")
|
||||
return oid
|
||||
|
@ -42,8 +42,7 @@ DEPT = TestConfig.DEPT_TEST
|
||||
def test_formsemestres_associate_new_version(test_client):
|
||||
"""Test association à une nouvelle version du programme"""
|
||||
app.set_sco_dept(DEPT)
|
||||
# Construit la base de test GB une seule fois
|
||||
# puis lance les tests de jury
|
||||
# Construit la base de test GB
|
||||
doc, formation, formsemestre_titres = yaml_setup.setup_from_yaml(
|
||||
"tests/ressources/yaml/simple_formsemestres.yaml"
|
||||
)
|
||||
|
49
tests/unit/test_models.py
Normal file
49
tests/unit/test_models.py
Normal file
@ -0,0 +1,49 @@
|
||||
""" Test méthodes génériques sur les modèles ScoDoc
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from flask import g
|
||||
|
||||
import app
|
||||
from app import db
|
||||
from app.models import Departement, GroupDescr
|
||||
|
||||
from config import TestConfig
|
||||
from tests.unit import yaml_setup
|
||||
|
||||
DEPT = TestConfig.DEPT_TEST
|
||||
|
||||
|
||||
def test_get_instance(test_client):
|
||||
"""Test accès instance avec ou sans dept"""
|
||||
assert DEPT
|
||||
app.set_sco_dept(DEPT)
|
||||
# Création d'un autre départment
|
||||
other_dept = Departement(acronym="X666")
|
||||
db.session.add(other_dept)
|
||||
db.session.flush()
|
||||
# Crée qq semestres...
|
||||
doc, formation, formsemestre_titres = yaml_setup.setup_from_yaml(
|
||||
"tests/ressources/yaml/simple_formsemestres.yaml"
|
||||
)
|
||||
for formsemestre_titre in formsemestre_titres:
|
||||
formsemestre = yaml_setup.create_formsemestre_with_etuds(
|
||||
doc, formation, formsemestre_titre
|
||||
)
|
||||
assert formsemestre
|
||||
# prend l'exemple de GroupDescr
|
||||
# Crée un formsemestre et un groupe
|
||||
gr = GroupDescr.query.first()
|
||||
assert gr
|
||||
oid = gr.id
|
||||
# Accès sans département (comme le fait l'API non départementale)
|
||||
g.scodoc_dept = None
|
||||
g.scodoc_dept_id = -1 # invalide
|
||||
assert GroupDescr.get_instance(oid, accept_none=True).id == oid
|
||||
# Accès avec le bon département
|
||||
app.set_sco_dept(DEPT)
|
||||
assert GroupDescr.get_instance(oid, accept_none=True).id == oid
|
||||
# Accès avec un autre département
|
||||
app.set_sco_dept(other_dept.acronym)
|
||||
assert GroupDescr.get_instance(oid, accept_none=True) is None
|
Loading…
Reference in New Issue
Block a user