From 0e4eff154c01f52d18074506a9f715a3f5926662 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 12 Feb 2023 23:03:12 +0100 Subject: [PATCH] =?UTF-8?q?Table=20jury=20BUT:=20colonnes=20(niveaux=20de)?= =?UTF-8?q?=20comp=C3=A9tences=20par=20ann=C3=A9e=20du=20parcours.=20WIP,?= =?UTF-8?q?=20A=20OPTIMISER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/cursus_but.py | 35 ++++++++++++++++++++++++----- app/models/but_validations.py | 13 ++++++++++- app/models/formsemestre.py | 4 +++- app/static/css/scodoc.css | 19 ++++++++++++++++ app/tables/jury_recap.py | 42 ++++++++++++++++++++++++++++++----- app/tables/recap.py | 8 ++++--- 6 files changed, 104 insertions(+), 17 deletions(-) diff --git a/app/but/cursus_but.py b/app/but/cursus_but.py index 3ded0c1d4..226bf1dda 100644 --- a/app/but/cursus_but.py +++ b/app/but/cursus_but.py @@ -135,7 +135,7 @@ class EtudCursusBUT: # "{ niveau_id : meilleure validation pour ce niveau }" self.validation_par_competence_et_annee = {} - "{ competence_id : { 'BUT1' : validation_rcue, ... } }" + """{ competence_id : { 'BUT1' : validation_rcue (la "meilleure"), ... } }""" for validation_rcue in ApcValidationRCUE.query.filter_by(etud=etud): niveau = validation_rcue.niveau() if not niveau.competence.id in self.validation_par_competence_et_annee: @@ -172,12 +172,35 @@ class EtudCursusBUT: """ return { competence.id: { - annee: { - self.validation_par_competence_et_annee.get(competence.id, {}).get( - annee - ) - } + annee: self.validation_par_competence_et_annee.get( + competence.id, {} + ).get(annee) for annee in ("BUT1", "BUT2", "BUT3") } for competence in self.competences.values() } + + # XXX TODO OPTIMISATION ACCESS TABLE JURY + def to_dict_codes(self) -> dict[int, dict[str, int]]: + """ + { + competence_id : { + annee : { validation} + } + } + où validation est un petit dict avec niveau_id, etc. + """ + d = {} + for competence in self.competences.values(): + d[competence.id] = {} + for annee in ("BUT1", "BUT2", "BUT3"): + validation_rcue: ApcValidationRCUE = ( + self.validation_par_competence_et_annee.get(competence.id, {}).get( + annee + ) + ) + + d[competence.id][annee] = ( + validation_rcue.to_dict_codes() if validation_rcue else None + ) + return d diff --git a/app/models/but_validations.py b/app/models/but_validations.py index c5707c0b6..37baff430 100644 --- a/app/models/but_validations.py +++ b/app/models/but_validations.py @@ -22,7 +22,7 @@ class ApcValidationRCUE(db.Model): aka "regroupements cohérents d'UE" dans le jargon BUT. - le formsemestre est celui du semestre PAIR du niveau de compétence + Le formsemestre est celui du semestre PAIR du niveau de compétence """ __tablename__ = "apc_validation_rcue" @@ -97,6 +97,17 @@ class ApcValidationRCUE(db.Model): "niveau": None if niveau is None else niveau.to_dict_bul(), } + def to_dict_codes(self) -> dict: + "Dict avec seulement les ids et la date - pour cache table jury" + return { + "id": self.id, + "code": self.code, + "date": self.date, + "etudid": self.etudid, + "niveau_id": self.niveau().id, + "formsemestre_id": self.formsemestre_id, + } + # Attention: ce n'est pas un modèle mais une classe ordinaire: class RegroupementCoherentUE: diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py index abcc0592f..3b01ff96a 100644 --- a/app/models/formsemestre.py +++ b/app/models/formsemestre.py @@ -625,10 +625,12 @@ class FormSemestre(db.Model): titre_annee += "-" + str(self.date_fin.year) return titre_annee - def titre_formation(self): + def titre_formation(self, with_sem_idx=False): """Titre avec formation, court, pour passerelle: "BUT R&T" (méthode de formsemestre car on pourrait ajouter le semestre, ou d'autres infos, à voir) """ + if with_sem_idx and self.semestre_id > 0: + return f"{self.formation.acronyme} S{self.semestre_id}" return self.formation.acronyme def titre_mois(self) -> str: diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css index b9edff50f..b68806d84 100644 --- a/app/static/css/scodoc.css +++ b/app/static/css/scodoc.css @@ -4074,6 +4074,25 @@ table.table_recap .cursus { white-space: nowrap; } +table.table_recap td.col_rcue, +table.table_recap th.col_rcue, +table.table_recap td.cursus_but.first, +table.table_recap td.cursus_but.first { + border-left: 1px solid rgb(221, 221, 221); +} + +table.table_recap td.cursus_BUT1 { + color: #007bff; +} + +table.table_recap td.cursus_BUT2 { + color: #d39f00; +} + +table.table_recap td.cursus_BUT3 { + color: #7f00ff; +} + table.table_recap td.col_ue, table.table_recap td.col_ue_code, table.table_recap td.col_moy_gen, diff --git a/app/tables/jury_recap.py b/app/tables/jury_recap.py index cc27df4d2..78ed33b5c 100644 --- a/app/tables/jury_recap.py +++ b/app/tables/jury_recap.py @@ -12,25 +12,21 @@ import time import numpy as np from flask import g, url_for +from app.but import cursus_but from app.but import jury_but from app.but.jury_but import ( DecisionsProposeesAnnee, DecisionsProposeesRCUE, DecisionsProposeesUE, ) -from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_compat import NotesTableCompat -from app.comp import res_sem -from app.models import UniteEns +from app.models import ApcNiveau, UniteEns from app.models.etudiants import Identite -from app.scodoc.sco_exceptions import ScoNoReferentielCompetences from app.models.formsemestre import FormSemestre -from app.scodoc import html_sco_header from app.scodoc.codes_cursus import ( BUT_BARRE_RCUE, BUT_RCUE_SUFFISANT, ) -from app.scodoc import sco_formsemestre_status from app.scodoc import sco_utils as scu from app.tables.recap import RowRecap, TableRecap @@ -58,6 +54,7 @@ class TableJury(TableRecap): # Ajout colonnes spécifiques à la table jury: if self.rows: # non vide if self.res.is_apc: + self.add_but_competences() self.add_rcues() self.add_jury() self.add_groups_header() @@ -136,6 +133,39 @@ class TableJury(TableRecap): target_attrs={"class": "stdlink"}, ) + def add_but_competences(self): + "Ajoute les colonnes résultats BUT (niveaux de compétences des 3 années)" + prev_group = "cursus" + for annee in ("BUT1", "BUT2", "BUT3"): + group = f"cursus_{annee}" + self.insert_group(group, after=prev_group) + prev_group = group + self.group_titles[group] = f"Compétences {annee}" + for row in self.rows: + etud = row.etud + cursus_dict = cursus_but.EtudCursusBUT( + etud, self.res.formsemestre.formation + ).to_dict() + first = True + for competence_id in cursus_dict: + for annee in ("BUT1", "BUT2", "BUT3"): + validation_rcue = cursus_dict[competence_id][annee] + if validation_rcue: + niveau: ApcNiveau = validation_rcue.niveau() + titre = f"C{niveau.competence.numero}" # à voir (nommer les compétences...) + row.add_cell( + f"c_{competence_id}_annee", + titre, + validation_rcue.code, + group="cursus_" + annee, + classes=["recorded_code"], + column_classes=["cursus_but" + (" first" if first else "")], + target_attrs={ + "title": f"{niveau.competence.titre} niveau {niveau.ordre}" + }, + ) + first = False + class RowJury(RowRecap): "Ligne de la table saisie jury" diff --git a/app/tables/recap.py b/app/tables/recap.py index 10f5d338e..8ae435c94 100644 --- a/app/tables/recap.py +++ b/app/tables/recap.py @@ -12,8 +12,7 @@ import numpy as np from app.auth.models import User from app.comp.res_common import ResultatsSemestre -from app.models import Identite -from app.models.ues import UniteEns +from app.models import Identite, FormSemestre, UniteEns from app.scodoc.codes_cursus import UE_SPORT, DEF from app.scodoc import sco_evaluation_db from app.scodoc import sco_groups @@ -691,7 +690,10 @@ class RowRecap(tb.Row): "Ajoute résultat UE au row (colonne col_ue)" # sous-classé par JuryRow pour ajouter les codes table = self.table - table.group_titles["col_ue"] = "UEs du semestre" + formsemestre: FormSemestre = table.res.formsemestre + table.group_titles[ + "col_ue" + ] = f"UEs du S{formsemestre.semestre_id} {formsemestre.annee_scolaire()}" col_id = f"moy_ue_{ue.id}" val = ue_status["moy"] note_class = ""