forked from ScoDoc/ScoDoc
BUT ref. Comp.: fix calcul niveaux/parcours, ajoute tests unitaires GCCD et MLT.
This commit is contained in:
parent
8af5c3ffa0
commit
65b87049ca
@ -85,7 +85,11 @@ class ApcReferentielCompetences(db.Model, XMLModel):
|
||||
lazy="dynamic",
|
||||
cascade="all, delete-orphan",
|
||||
)
|
||||
formations = db.relationship("Formation", backref="referentiel_competence")
|
||||
formations = db.relationship(
|
||||
"Formation",
|
||||
backref="referentiel_competence",
|
||||
order_by="Formation.acronyme, Formation.version",
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ApcReferentielCompetences {self.id} {self.specialite!r} {self.departement!r}>"
|
||||
@ -360,32 +364,36 @@ class ApcNiveau(db.Model, XMLModel):
|
||||
parcour: "ApcParcours",
|
||||
annee: int,
|
||||
referentiel_competence: ApcReferentielCompetences = None,
|
||||
) -> flask_sqlalchemy.BaseQuery:
|
||||
) -> list["ApcNiveau"]:
|
||||
"""Les niveaux de l'année du parcours
|
||||
Si le parcour est None, tous les niveaux de l'année
|
||||
"""
|
||||
if annee not in {1, 2, 3}:
|
||||
raise ValueError("annee invalide pour un parcours BUT")
|
||||
referentiel_competence = (
|
||||
parcour.referentiel if parcour else referentiel_competence
|
||||
)
|
||||
if referentiel_competence is None:
|
||||
raise ScoNoReferentielCompetences()
|
||||
|
||||
if not parcour:
|
||||
annee_formation = f"BUT{annee}"
|
||||
if parcour is None:
|
||||
return ApcNiveau.query.filter(
|
||||
ApcNiveau.annee == annee_formation,
|
||||
ApcCompetence.id == ApcNiveau.competence_id,
|
||||
ApcCompetence.referentiel_id == referentiel_competence.id,
|
||||
)
|
||||
else:
|
||||
return ApcNiveau.query.filter(
|
||||
ApcParcoursNiveauCompetence.annee_parcours_id == ApcAnneeParcours.id,
|
||||
ApcParcours.id == ApcAnneeParcours.parcours_id,
|
||||
ApcParcours.referentiel == parcour.referentiel,
|
||||
ApcParcoursNiveauCompetence.competence_id == ApcCompetence.id,
|
||||
ApcCompetence.id == ApcNiveau.competence_id,
|
||||
ApcAnneeParcours.parcours == parcour,
|
||||
ApcNiveau.annee == annee_formation,
|
||||
)
|
||||
annee_parcour = parcour.annees.filter_by(ordre=annee).first()
|
||||
if not annee_parcour:
|
||||
return []
|
||||
|
||||
parcour_niveaux: list[
|
||||
ApcParcoursNiveauCompetence
|
||||
] = annee_parcour.niveaux_competences
|
||||
niveaux: list[ApcNiveau] = [
|
||||
pn.competence.niveaux.filter_by(ordre=pn.niveau).first()
|
||||
for pn in parcour_niveaux
|
||||
]
|
||||
return niveaux
|
||||
|
||||
|
||||
app_critiques_modules = db.Table(
|
||||
|
@ -554,7 +554,7 @@ def formation_list_table() -> GenTable:
|
||||
row["_buttons_html"] = but_locked + but_suppr + but_edit
|
||||
rows.append(row)
|
||||
# Tri par annee_dernier_sem, type, acronyme, titre, version décroissante
|
||||
# donc plus récemment utilsiée en tête
|
||||
# donc plus récemment utilisée en tête
|
||||
rows.sort(
|
||||
key=lambda row: (
|
||||
-row["annee_dernier_sem"],
|
||||
|
@ -19,7 +19,20 @@
|
||||
|
||||
|
||||
<div class="part2">
|
||||
<a class="stdlink" href="{{url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept)}}">liste des référentiels</a>
|
||||
<ul>
|
||||
<li>Formations se référant à ce référentiel:
|
||||
<ul>
|
||||
{% for formation in ref.formations %}
|
||||
<li><a class="stdlink" href="{{
|
||||
url_for('notes.ue_table', scodoc_dept=g.scodoc_dept, formation_id=formation.id )
|
||||
}}">{{ formation.get_titre_version() }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="stdlink" href="{{url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept)}}">Liste des référentiels</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -33,31 +33,21 @@ Emmanuel Viennet, 2021
|
||||
|
||||
from flask import url_for
|
||||
from flask import jsonify
|
||||
from flask import current_app, g, request
|
||||
from flask import g, request
|
||||
from flask.templating import render_template
|
||||
from flask_login import current_user
|
||||
from werkzeug.utils import redirect
|
||||
from app.scodoc.codes_cursus import UE_SPORT
|
||||
|
||||
from config import Config
|
||||
|
||||
from app import db
|
||||
from app import models
|
||||
from app.auth.models import User
|
||||
from app import db, models
|
||||
|
||||
from app.comp import moy_ue
|
||||
from app.decorators import scodoc, permission_required
|
||||
from app.models import ApcParcours, Formation, Module
|
||||
from app.views import notes_bp as bp
|
||||
|
||||
# ---------------
|
||||
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc import sco_formations
|
||||
from app import log
|
||||
|
||||
from app.models import ApcParcours, Formation, UniteEns, Module
|
||||
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
|
||||
|
||||
|
@ -44,17 +44,17 @@ def refcomp(refcomp_id):
|
||||
@permission_required(Permission.ScoView)
|
||||
def refcomp_show(refcomp_id):
|
||||
"""Affichage du référentiel de compétences."""
|
||||
ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
|
||||
referentiel_competence = ApcReferentielCompetences.query.get_or_404(refcomp_id)
|
||||
return render_template(
|
||||
"but/refcomp_show.j2",
|
||||
ref=ref,
|
||||
ref=referentiel_competence,
|
||||
title="Référentiel de compétences",
|
||||
sco=ScoData(),
|
||||
data_source=url_for(
|
||||
"notes.refcomp",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
refcomp_id=refcomp_id,
|
||||
),
|
||||
sco=ScoData(),
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.4.70"
|
||||
SCOVERSION = "9.4.71"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
@ -24,6 +24,12 @@ from tests.unit import setup
|
||||
REF_RT_XML = open(
|
||||
"ressources/referentiels/but2022/competences/but-RT-05012022-081735.xml"
|
||||
).read()
|
||||
REF_MLT_XML = open(
|
||||
"ressources/referentiels/but2022/competences/but-MLT-05012022-081603.xml"
|
||||
).read()
|
||||
REF_GCCD_XML = open(
|
||||
"ressources/referentiels/but2022/competences/but-GCCD-05012022-081630.xml"
|
||||
).read()
|
||||
|
||||
|
||||
def test_but_refcomp(test_client):
|
||||
@ -84,3 +90,110 @@ def test_but_assoc_refcomp(test_client):
|
||||
db.session.commit()
|
||||
formation.refcomp_desassoc()
|
||||
assert ue.niveau_competence_id is None
|
||||
|
||||
|
||||
def test_refcomp_niveaux_mlt(test_client):
|
||||
"""Test calcul niveaux / parcours pour un BUT MLT
|
||||
avec en parcours "Mobilité et Supply Chain Connectées"
|
||||
une compétence "Transporter" sur BUT1, BUT2
|
||||
et une compétence "Digitaliser" sur BUT2, BUT3
|
||||
"""
|
||||
# Charger le ref. comp. MLT
|
||||
dept_id = models.Departement.query.first().id
|
||||
ref_comp: ApcReferentielCompetences = orebut_import_refcomp(REF_MLT_XML, dept_id)
|
||||
# Vérifier qu'on a 2 parcours et 4 compétences dans chaque
|
||||
nb_parcours = ref_comp.parcours.count()
|
||||
assert nb_parcours == 2
|
||||
assert [len(p.query_competences().all()) for p in ref_comp.parcours] == [
|
||||
4
|
||||
] * nb_parcours
|
||||
# 3 niveaux en 1ere année (dans chaque parcours):
|
||||
assert [
|
||||
len(ApcNiveau.niveaux_annee_de_parcours(p, 1, ref_comp))
|
||||
for p in ref_comp.parcours
|
||||
] == [3, 3]
|
||||
# 2 niveaux en 2ème année (dans chaque parcours):
|
||||
assert [
|
||||
len(ApcNiveau.niveaux_annee_de_parcours(p, 2, ref_comp))
|
||||
for p in ref_comp.parcours
|
||||
] == [4, 4]
|
||||
# 3 niveaux en 3ème année (dans chaque parcours):
|
||||
assert [
|
||||
len(ApcNiveau.niveaux_annee_de_parcours(p, 3, ref_comp))
|
||||
for p in ref_comp.parcours
|
||||
] == [3, 3]
|
||||
# Vérifier les niveaux_by_parcours
|
||||
parcour = ref_comp.parcours.first()
|
||||
# BUT 1
|
||||
parcours, niveaux_by_parcours = ref_comp.get_niveaux_by_parcours(1, parcour)
|
||||
assert parcours == [parcour] # le parcours indiqué
|
||||
assert (tuple(niveaux_by_parcours.keys())) == (parcour.id, "TC")
|
||||
assert niveaux_by_parcours[parcour.id] == [] # tout en tronc commun en BUT1 MLT
|
||||
assert niveaux_by_parcours["TC"][0].competence.titre == "Transporter"
|
||||
assert len(niveaux_by_parcours["TC"]) == 3
|
||||
# BUT 2
|
||||
parcours, niveaux_by_parcours = ref_comp.get_niveaux_by_parcours(2, parcour)
|
||||
assert parcours == [parcour] # le parcours indiqué
|
||||
assert (tuple(niveaux_by_parcours.keys())) == (parcour.id, "TC")
|
||||
assert len(niveaux_by_parcours[parcour.id]) == 1
|
||||
assert len(niveaux_by_parcours["TC"]) == 3
|
||||
# BUT 3
|
||||
parcours, niveaux_by_parcours = ref_comp.get_niveaux_by_parcours(3, parcour)
|
||||
assert parcours == [parcour] # le parcours indiqué
|
||||
assert (tuple(niveaux_by_parcours.keys())) == (parcour.id, "TC")
|
||||
assert len(niveaux_by_parcours[parcour.id]) == 1
|
||||
assert len(niveaux_by_parcours["TC"]) == 2
|
||||
# Vérifier les niveaux de chaque année
|
||||
assert len(ApcNiveau.niveaux_annee_de_parcours(parcour, 1)) == 3
|
||||
assert len(ApcNiveau.niveaux_annee_de_parcours(parcour, 2)) == 4
|
||||
assert len(ApcNiveau.niveaux_annee_de_parcours(parcour, 3)) == 3
|
||||
|
||||
|
||||
def test_refcomp_niveaux_gccd(test_client):
|
||||
"""Test calcul niveaux / parcours pour un BUT GCCD
|
||||
avec en parcours "Travaux Bâtiment" 5 compétences
|
||||
dont la première "Solutions Bâtiment" sur BUT1, BUT2, BUT3
|
||||
et en parcours "Travaux Publics" la même sur BUT1, BUT2 seulement.
|
||||
"""
|
||||
# Charger le ref. comp. GCCD
|
||||
dept_id = models.Departement.query.first().id
|
||||
ref_comp: ApcReferentielCompetences = orebut_import_refcomp(REF_GCCD_XML, dept_id)
|
||||
# Vérifier qu'on a 4 parcours et 5 compétences dans chaque
|
||||
nb_parcours = ref_comp.parcours.count()
|
||||
assert nb_parcours == 4
|
||||
assert [len(p.query_competences().all()) for p in ref_comp.parcours] == [
|
||||
5
|
||||
] * nb_parcours
|
||||
# 5 niveaux en 1ere année (dans chaque parcours):
|
||||
assert [
|
||||
len(ApcNiveau.niveaux_annee_de_parcours(p, 1, ref_comp))
|
||||
for p in ref_comp.parcours
|
||||
] == [5] * nb_parcours
|
||||
# 5 niveaux en 2ème année (dans chaque parcours):
|
||||
assert [
|
||||
len(ApcNiveau.niveaux_annee_de_parcours(p, 2, ref_comp))
|
||||
for p in ref_comp.parcours
|
||||
] == [5] * nb_parcours
|
||||
# 3 niveaux en 3ème année (dans chaque parcours):
|
||||
assert [
|
||||
len(ApcNiveau.niveaux_annee_de_parcours(p, 3, ref_comp))
|
||||
for p in ref_comp.parcours
|
||||
] == [3] * nb_parcours
|
||||
# Vérifier les niveaux_by_parcours
|
||||
parcour = ref_comp.parcours.first()
|
||||
# BUT 1
|
||||
parcours, niveaux_by_parcours = ref_comp.get_niveaux_by_parcours(1, parcour)
|
||||
assert parcours == [parcour] # le parcours indiqué
|
||||
assert (tuple(niveaux_by_parcours.keys())) == (parcour.id, "TC")
|
||||
assert len(niveaux_by_parcours[parcour.id]) == 0
|
||||
assert len(niveaux_by_parcours["TC"]) == 5
|
||||
# BUT 3
|
||||
parcours, niveaux_by_parcours = ref_comp.get_niveaux_by_parcours(3, parcour)
|
||||
assert parcours == [parcour] # le parcours indiqué
|
||||
assert (tuple(niveaux_by_parcours.keys())) == (parcour.id, "TC")
|
||||
assert len(niveaux_by_parcours[parcour.id]) == 3
|
||||
assert len(niveaux_by_parcours["TC"]) == 0
|
||||
# Vérifier les niveaux de chaque année
|
||||
assert len(ApcNiveau.niveaux_annee_de_parcours(parcour, 1)) == 5
|
||||
assert len(ApcNiveau.niveaux_annee_de_parcours(parcour, 2)) == 5
|
||||
assert len(ApcNiveau.niveaux_annee_de_parcours(parcour, 3)) == 3
|
||||
|
Loading…
Reference in New Issue
Block a user