BUT: assoc. modules <-> App. Critiques

This commit is contained in:
Emmanuel Viennet 2022-05-02 14:39:06 +02:00
parent f537cd2e48
commit 96248ccfd3
6 changed files with 145 additions and 29 deletions

View File

@ -286,6 +286,21 @@ class ApcNiveau(db.Model, XMLModel):
)
app_critiques_modules = db.Table(
"apc_modules_acs",
db.Column(
"module_id",
db.ForeignKey("notes_modules.id", ondelete="CASCADE"),
primary_key=True,
),
db.Column(
"app_crit_id",
db.ForeignKey("apc_app_critique.id"),
primary_key=True,
),
)
class ApcAppCritique(db.Model, XMLModel):
"Apprentissage Critique BUT"
id = db.Column(db.Integer, primary_key=True)
@ -293,12 +308,31 @@ class ApcAppCritique(db.Model, XMLModel):
code = db.Column(db.Text(), nullable=False, index=True)
libelle = db.Column(db.Text())
modules = db.relationship(
"Module",
secondary="apc_modules_acs",
lazy="dynamic",
backref=db.backref("app_critiques", lazy="dynamic"),
# modules = db.relationship(
# "Module",
# secondary="apc_modules_acs",
# lazy="dynamic",
# backref=db.backref("app_critiques", lazy="dynamic"),
# )
@classmethod
def app_critiques_ref_comp(
cls,
ref_comp: ApcReferentielCompetences,
annee: str,
competence: ApcCompetence = None,
) -> flask_sqlalchemy.BaseQuery:
"Liste les AC de tous les parcours de ref_comp pour l'année indiquée"
assert annee in {"BUT1", "BUT2", "BUT3"}
query = cls.query.filter(
ApcAppCritique.niveau_id == ApcNiveau.id,
ApcNiveau.competence_id == ApcCompetence.id,
ApcNiveau.annee == annee,
ApcCompetence.referentiel_id == ref_comp.id,
)
if competence is not None:
query = query.filter(ApcNiveau.competence == competence)
return query
def to_dict(self) -> dict:
return {"libelle": self.libelle}
@ -314,13 +348,6 @@ class ApcAppCritique(db.Model, XMLModel):
return [m for m in self.modules if m.module_type == ModuleType.SAE]
ApcAppCritiqueModules = db.Table(
"apc_modules_acs",
db.Column("module_id", db.ForeignKey("notes_modules.id")),
db.Column("app_crit_id", db.ForeignKey("apc_app_critique.id")),
)
parcours_modules = db.Table(
"parcours_modules",
db.Column(
@ -350,11 +377,6 @@ class ApcParcours(db.Model, XMLModel):
lazy="dynamic",
cascade="all, delete-orphan",
)
# modules = db.relationship(
# "Module",
# secondary=parcours_modules,
# back_populates="parcours",
# )
def __repr__(self):
return f"<{self.__class__.__name__} {self.code}>"

View File

@ -3,7 +3,7 @@
from app import db
from app.models import APO_CODE_STR_LEN
from app.models.but_refcomp import parcours_modules
from app.models.but_refcomp import app_critiques_modules, parcours_modules
from app.scodoc import sco_utils as scu
from app.scodoc.sco_codes_parcours import UE_SPORT
from app.scodoc.sco_utils import ModuleType
@ -50,7 +50,13 @@ class Module(db.Model):
"ApcParcours",
secondary=parcours_modules,
lazy="subquery",
# cascade="all, delete",
backref=db.backref("modules", lazy=True),
)
app_critiques = db.relationship(
"ApcAppCritique",
secondary=app_critiques_modules,
lazy="subquery",
backref=db.backref("modules", lazy=True),
)

View File

@ -127,7 +127,7 @@ def html_edit_formation_apc(
formation=formation,
titre=f"Ressources du S{semestre_idx}",
create_element_msg="créer une nouvelle ressource",
matiere_parent=matiere_parent,
# matiere_parent=matiere_parent,
modules=ressources_in_sem,
module_type=ModuleType.RESSOURCE,
editable=editable,
@ -143,7 +143,7 @@ def html_edit_formation_apc(
formation=formation,
titre=f"Situations d'Apprentissage et d'Évaluation (SAÉs) S{semestre_idx}",
create_element_msg="créer une nouvelle SAÉ",
matiere_parent=matiere_parent,
# matiere_parent=matiere_parent,
modules=saes_in_sem,
module_type=ModuleType.SAE,
editable=editable,

View File

@ -39,7 +39,7 @@ from app.models import APO_CODE_STR_LEN
from app.models import Formation, Matiere, Module, UniteEns
from app.models import FormSemestre, ModuleImpl
from app.models import ScolarNews
from app.models.but_refcomp import ApcParcours
from app.models.but_refcomp import ApcAppCritique, ApcParcours
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
@ -272,6 +272,7 @@ def module_edit(
# --- Détermination de la formation
orig_semestre_idx = None
ue = None
if create:
if matiere_id:
matiere = Matiere.query.get_or_404(matiere_id)
@ -286,6 +287,7 @@ def module_edit(
if not module_id:
raise ValueError("missing module_id !")
module = models.Module.query.get_or_404(module_id)
ue = module.ue
module_dict = module.to_dict()
formation = module.formation
unlocked = not module_is_locked(module_id)
@ -633,8 +635,9 @@ def module_edit(
},
),
]
# Choix des parcours
if is_apc:
# Choix des parcours
ref_comp = formation.referentiel_competence
if ref_comp:
descr += [
@ -656,13 +659,54 @@ def module_edit(
module_dict["parcours"] = [
str(parcour.id) for parcour in module.parcours
]
module_dict["app_critiques"] = [
str(app_crit.id) for app_crit in module.app_critiques
]
# Choix des Apprentissages Critiques
if ue is not None:
annee = f"BUT{orig_semestre_idx//2 + 1}"
app_critiques = ApcAppCritique.app_critiques_ref_comp(ref_comp, annee)
descr += (
[
(
"app_critiques",
{
"title": "Apprentissages Critiques",
"input_type": "checkbox",
"vertical": True,
"dom_id": "tf_module_app_critiques",
"labels": [
app_crit.libelle for app_crit in app_critiques
],
"allowed_values": [
str(app_crit.id) for app_crit in app_critiques
],
"explanation": "apprentissages critiques liés à ce module.",
},
)
]
if (ue.niveau_competence is not None)
else [
(
"app_critiques",
{
"input_type": "separator",
"title": f"""<span class="fontred">{scu.EMO_WARNING }
L'UE {ue.acronyme} {ue.titre}
n'est pas associée à un niveau de compétences
</span>""",
},
)
]
)
else:
descr += [
(
"parcours",
{
"input_type": "separator",
"title": f"""<span class="fontred">Pas de parcours:
"title": f"""<span class="fontred">{scu.EMO_WARNING }
Pas de parcours:
<a class="stdlink" href="{ url_for('notes.refcomp_assoc_formation',
scodoc_dept=g.scodoc_dept, formation_id=formation.id)
}">associer un référentiel de compétence</a>
@ -748,10 +792,17 @@ def module_edit(
#
do_module_edit(tf[2])
# Modifie les parcours
if "parcours" in tf[2]:
module.parcours = [
ApcParcours.query.get(int(parcour_id_str))
for parcour_id_str in tf[2]["parcours"]
]
# Modifie les AC
if "app_critiques" in tf[2]:
module.app_critiques = [
ApcAppCritique.query.get(int(ac_id_str))
for ac_id_str in tf[2]["app_critiques"]
]
db.session.add(module)
db.session.commit()
return flask.redirect(

View File

@ -2271,6 +2271,10 @@ tr#tf_module_parcours>td {
background-color: rgb(229, 229, 229);
}
tr#tf_module_app_critiques>td {
background-color: rgb(194, 209, 228);
}
/* tableau recap notes */
table.notes_recapcomplet {
border: 2px solid blue;

View File

@ -47,6 +47,23 @@ def upgrade():
),
sa.PrimaryKeyConstraint("parcours_id", "module_id"),
)
op.alter_column(
"apc_modules_acs", "module_id", existing_type=sa.INTEGER(), nullable=False
)
op.alter_column(
"apc_modules_acs", "app_crit_id", existing_type=sa.INTEGER(), nullable=False
)
op.drop_constraint(
"apc_modules_acs_module_id_fkey", "apc_modules_acs", type_="foreignkey"
)
op.create_foreign_key(
"apc_modules_acs_module_id_fkey",
"apc_modules_acs",
"notes_modules",
["module_id"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ###
@ -57,4 +74,20 @@ def downgrade():
)
op.drop_column("notes_ue", "niveau_competence_id")
op.drop_table("parcours_modules")
op.drop_constraint(
"apc_modules_acs_module_id_fkey", "apc_modules_acs", type_="foreignkey"
)
op.create_foreign_key(
"apc_modules_acs_module_id_fkey",
"apc_modules_acs",
"notes_modules",
["module_id"],
["id"],
)
op.alter_column(
"apc_modules_acs", "app_crit_id", existing_type=sa.INTEGER(), nullable=True
)
op.alter_column(
"apc_modules_acs", "module_id", existing_type=sa.INTEGER(), nullable=True
)
# ### end Alembic commands ###