# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2022 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 # ############################################################################## """Rapport sur réussite en BUT pour enquête 2022 - statistiques decisions """ from collections import defaultdict from flask import request from app.but import jury_but from app.comp import res_sem from app.comp.res_compat import NotesTableCompat from app.models import FormSemestre from app.models.etudiants import Identite import app.scodoc.sco_utils as scu from app.scodoc import html_sco_header from app.scodoc import sco_codes_parcours from app.scodoc.sco_exceptions import ScoValueError from app.scodoc import sco_preferences import sco_version from app.scodoc.gen_tables import GenTable # Titres, ordonnés INDICATEUR_NAMES = { "nb_inscr": "Inscrits initiaux", "nb_dem": "Démissions", "nb_def": "Défaillants", "nb_actifs": "Inscrits finals", "nb_nar": "NAR", "nb_passe_manque_rcue": "Passant avec RCUE non validé", "nb_red_avec_rcue": "Redoublant avec au moins un RCUE validé", "nb_red_sans_rcue": "Redoublant sans avoir validé aucun RCUE", "nb_valide_tt_rcue": "Validant tous les RCUE de l'année", } def formsemestre_but_indicateurs(formsemestre_id: int, format="html"): """Page avec tableau indicateurs enquête ADIUT BUT 2022""" formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) indicateurs_by_bac = but_indicateurs_by_bac(formsemestre) # finalement on fait une table avec en ligne # les indicateurs, et en colonne les bacs bacs = sorted(indicateurs_by_bac.keys()) rows = [] for indicateur, titre_indicateur in INDICATEUR_NAMES.items(): row = {bac: indicateurs_by_bac[bac][indicateur] for bac in bacs} row["titre_indicateur"] = titre_indicateur rows.append(row) tab = GenTable( titles={bac: bac for bac in bacs}, columns_ids=["titre_indicateur"] + bacs, rows=rows, html_sortable=False, preferences=sco_preferences.SemPreferences(formsemestre_id), filename=scu.make_filename(f"Indicateurs_BUT_{formsemestre.titre_annee()}"), origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}", html_caption="Indicateurs BUT annuels.", base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}", ) title = "Indicateurs suivi annuel BUT" t = tab.make_page( title=f"""

{title}

""", format=format, with_html_headers=False, ) if format != "html": return t H = [ html_sco_header.sco_header(page_title=title), t, """

""", html_sco_header.sco_footer(), ] return "\n".join(H) def but_indicateurs_by_bac(formsemestre: FormSemestre) -> dict[str:dict]: """ L'enquête ADIUT porte sur le nombre de - inscrits - ayant validé tous les RCUE - passant en BUT2 sans avoir validé tous les RCUE - redoublants avec au moins une RCUE - redoublants sans aucune RCUE - NAR - défaillants - démissionnaires, le tout découpé en FI/FA et suivant le type de bac : général/techno/pro/autre. Le semestre est FI ou FA, donc on ne traite pas ce point. On suppose qu'on est sur un semestre PAIR de BUT, dont les décisions de jury ont déjà été saisies. """ if not formsemestre.formation.is_apc(): raise ScoValueError( "Ce rapport doit être généré à partir d'une formation par compétences (BUT)." ) if formsemestre.semestre_id % 2: raise ScoValueError("Ce rapport doit être généré à partir d'un semestre PAIR.") # Le semestre suivant (pour compter les passages) next_sem_idx = formsemestre.semestre_id + 1 res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) etuds = formsemestre.get_inscrits(include_demdef=True) decisions_annee = { etud.id: jury_but.DecisionsProposeesAnnee(etud, formsemestre) for etud in etuds if res.get_etud_etat(etud.id) == scu.INSCRIT } # Ventilation par bac etuds_by_bac = defaultdict(list) # bac : etuds for etud in etuds: adm = etud.admission.first() bac = adm.get_bac().abbrev() if adm else "?" etuds_by_bac[bac].append(etud) indicateurs_by_bac = {} for bac in etuds_by_bac: indicateurs_by_bac[bac] = _indicateurs_enquete_but( res, etuds_by_bac[bac], decisions_annee, next_sem_idx ) indicateurs_by_bac["Total"] = _indicateurs_enquete_but( res, etuds, decisions_annee, next_sem_idx ) return indicateurs_by_bac def _indicateurs_enquete_but( res: NotesTableCompat, etuds: list[Identite], decisions_annee: dict[jury_but.DecisionsProposeesAnnee], next_sem_idx: int, ) -> dict: """Calcule les indicateurs de l'enquête ADIUT 2022""" indicateurs = { "nb_inscr": len(etuds), "nb_actifs": len( [etud for etud in etuds if res.get_etud_etat(etud.id) == scu.INSCRIT] ), "nb_def": len( [etud for etud in etuds if res.get_etud_etat(etud.id) == scu.DEF] ), "nb_dem": len( [etud for etud in etuds if res.get_etud_etat(etud.id) == scu.DEMISSION] ), "nb_nar": len( [ True for deca in decisions_annee.values() if deca.code_valide == sco_codes_parcours.NAR ] ), # Redoublants sans aucune RCUE "nb_red_sans_rcue": len( [ True for deca in decisions_annee.values() if (deca.nb_rcue_valides == 0) and (next_sem_idx not in deca.get_autorisations_passage()) ] ), # Redoublants avec au moins une RCUE "nb_red_avec_rcue": len( [ True for deca in decisions_annee.values() if (deca.nb_rcue_valides > 0) and (next_sem_idx not in deca.get_autorisations_passage()) ] ), # Passant (en BUT2) sans avoir validé tous les RCUE "nb_passe_manque_rcue": len( [ True for deca in decisions_annee.values() if (deca.nb_rcue_valides < deca.nb_competences) and (next_sem_idx in deca.get_autorisations_passage()) ] ), # Ayant validé tous les RCUE "nb_valide_tt_rcue": len( [ True for deca in decisions_annee.values() if (deca.nb_rcue_valides >= deca.nb_competences) ] ), } return indicateurs