############################################################################## # # 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.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//") @scodoc @permission_required(Permission.ScoView) def parcour_formation(parcour_id: int, formation_id: int) -> 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" 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) return render_template( "but/parcour_formation.j2", formation=formation, parcour=parcour, competences_parcour=competences_parcour, sco=ScoData(), ) def parcour_formation_competences(parcour: ApcParcours, formation: Formation) -> list: """ [ { 'competence' : ApcCompetence, 'niveaux' : { 1 : { ... }, 2 : { ... }, 3 : { 'niveau' : ApcNiveau, 'ue_impair' : UniteEns, 'ue_pair' : UniteEns } } } ] """ def _niveau_ues(competence: ApcCompetence, annee: int) -> dict: 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} 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_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 return { "niveau": niveau, "ue_pair": ue_pair, "ue_impair": ue_impair, } competences = [ { "competence": competence, "niveaux": {annee: _niveau_ues(competence, annee) for annee in (1, 2, 3)}, } for competence in parcour.query_competences() ] return competences