171 lines
5.7 KiB
Python
171 lines
5.7 KiB
Python
##############################################################################
|
|
#
|
|
# ScoDoc
|
|
#
|
|
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
#
|
|
##############################################################################
|
|
|
|
"""
|
|
Vues sur les formations BUT
|
|
|
|
Emmanuel Viennet, 2023
|
|
"""
|
|
|
|
from flask import g, render_template
|
|
|
|
from app import log
|
|
from app.decorators import (
|
|
scodoc,
|
|
permission_required,
|
|
)
|
|
|
|
from app.models import (
|
|
ApcCompetence,
|
|
ApcNiveau,
|
|
ApcParcours,
|
|
ApcReferentielCompetences,
|
|
Formation,
|
|
)
|
|
from app.scodoc.codes_cursus import UE_STANDARD
|
|
from app.scodoc.sco_permissions import Permission
|
|
from app.scodoc.sco_exceptions import ScoValueError
|
|
from app.views import notes_bp as bp
|
|
from app.views import ScoData
|
|
|
|
|
|
@bp.route("/parcour_formation/<int:formation_id>/<int:parcour_id>")
|
|
@bp.route("/parcour_formation/<int:formation_id>")
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
def parcour_formation(formation_id: int, parcour_id: int = None) -> str:
|
|
"""visu HTML d'un parcours dans une formation,
|
|
avec les compétences, niveaux et UEs associées."""
|
|
formation: Formation = Formation.query.filter_by(
|
|
id=formation_id, dept_id=g.scodoc_dept_id
|
|
).first_or_404()
|
|
ref_comp: ApcReferentielCompetences = formation.referentiel_competence
|
|
if ref_comp is None:
|
|
return "pas de référentiel de compétences"
|
|
if parcour_id is None:
|
|
parcour = None
|
|
else:
|
|
parcour: ApcParcours = ref_comp.parcours.filter_by(id=parcour_id).first()
|
|
if parcour is None:
|
|
raise ScoValueError("parcours invalide ou hors référentiel de formation")
|
|
|
|
competences_parcour = (
|
|
parcour_formation_competences(parcour, formation) if parcour else None
|
|
)
|
|
|
|
return render_template(
|
|
"but/parcour_formation.j2",
|
|
formation=formation,
|
|
parcour=parcour,
|
|
competences_parcour=competences_parcour,
|
|
sco=ScoData(),
|
|
title=f"{formation.acronyme} - Niveaux et UEs",
|
|
)
|
|
|
|
|
|
def parcour_formation_competences(parcour: ApcParcours, formation: Formation) -> list:
|
|
"""
|
|
[
|
|
{
|
|
'competence' : ApcCompetence,
|
|
'niveaux' : {
|
|
1 : { ... },
|
|
2 : { ... },
|
|
3 : {
|
|
'niveau' : ApcNiveau,
|
|
'ue_impair' : UniteEns, # actuellement associée
|
|
'ues_impair' : list[UniteEns], # choix possibles
|
|
'ue_pair' : UniteEns,
|
|
'ues_pair' : list[UniteEns],
|
|
}
|
|
}
|
|
}
|
|
]
|
|
"""
|
|
|
|
def _niveau_ues(competence: ApcCompetence, annee: int) -> dict:
|
|
"niveau et ues pour l'année du parcours"
|
|
niveaux = ApcNiveau.niveaux_annee_de_parcours(
|
|
parcour, annee, competence=competence
|
|
)
|
|
if len(niveaux) > 0:
|
|
if len(niveaux) > 1:
|
|
log(f"_niveau_ues: plus d'un niveau pour {competence} annee {annee}")
|
|
niveau = niveaux[0]
|
|
elif len(niveaux) == 0:
|
|
return {"niveau": None, "ue_pair": None, "ue_impair": None}
|
|
# toutes les UEs de la formation associées à ce niveau
|
|
ues = [
|
|
ue
|
|
for ue in niveau.ues
|
|
if ue.formation.id == formation.id
|
|
# and parcour.id in (p.id for p in ue.parcours)
|
|
]
|
|
ues_pair = [ue for ue in ues if ue.semestre_idx == 2 * annee]
|
|
if len(ues_pair) > 0:
|
|
ue_pair = ues_pair[0]
|
|
if len(ues_pair) > 1:
|
|
log(
|
|
f"_niveau_ues: {len(ues)} associées au niveau {niveau} / S{2*annee}"
|
|
)
|
|
else:
|
|
ue_pair = None
|
|
ues_pair_possibles = [
|
|
ue
|
|
for ue in formation.ues.filter_by(semestre_idx=2 * annee, type=UE_STANDARD)
|
|
if (ue.niveau_competence is None) or (ue.niveau_competence_id == niveau.id)
|
|
]
|
|
ues_impair = [ue for ue in ues if ue.semestre_idx == (2 * annee - 1)]
|
|
if len(ues_impair) > 0:
|
|
ue_impair = ues_impair[0]
|
|
if len(ues_impair) > 1:
|
|
log(
|
|
f"_niveau_ues: {len(ues)} associées au niveau {niveau} / S{2*annee-1}"
|
|
)
|
|
else:
|
|
ue_impair = None
|
|
ues_impair_possibles = [
|
|
ue
|
|
for ue in formation.ues.filter_by(
|
|
semestre_idx=2 * annee - 1, type=UE_STANDARD
|
|
)
|
|
if (ue.niveau_competence is None) or (ue.niveau_competence_id == niveau.id)
|
|
]
|
|
return {
|
|
"niveau": niveau,
|
|
"ue_pair": ue_pair,
|
|
"ues_pair": ues_pair_possibles,
|
|
"ue_impair": ue_impair,
|
|
"ues_impair": ues_impair_possibles,
|
|
}
|
|
|
|
competences = [
|
|
{
|
|
"competence": competence,
|
|
"niveaux": {annee: _niveau_ues(competence, annee) for annee in (1, 2, 3)},
|
|
}
|
|
for competence in parcour.query_competences()
|
|
]
|
|
return competences
|