1
0
forked from ScoDoc/ScoDoc

Ajoute ECTS acquis sur TableJury et cursus_etud BUT

This commit is contained in:
Emmanuel Viennet 2024-07-05 14:12:00 +02:00
parent 427672b396
commit bf77b9112f
7 changed files with 37 additions and 13 deletions

View File

@ -207,6 +207,10 @@ class EtudCursusBUT:
# slow, utile pour affichage fiche # slow, utile pour affichage fiche
return annee in [n.annee for n in self.competences[competence_id].niveaux] return annee in [n.annee for n in self.competences[competence_id].niveaux]
def get_ects_acquis(self) -> int:
"Nombre d'ECTS validés par etud dans le BUT de ce référentiel"
return but_ects_valides(self.etud, self.formation.referentiel_competence.id)
def load_validation_by_niveau(self) -> dict[int, list[ApcValidationRCUE]]: def load_validation_by_niveau(self) -> dict[int, list[ApcValidationRCUE]]:
"""Cherche les validations de jury enregistrées pour chaque niveau """Cherche les validations de jury enregistrées pour chaque niveau
Résultat: { niveau_id : [ ApcValidationRCUE ] } Résultat: { niveau_id : [ ApcValidationRCUE ] }
@ -378,7 +382,7 @@ class FormSemestreCursusBUT:
# "cache { competence_id : competence }" # "cache { competence_id : competence }"
def but_ects_valides(etud: Identite, referentiel_competence_id: int) -> float: def but_ects_valides(etud: Identite, referentiel_competence_id: int) -> int:
"""Nombre d'ECTS validés par etud dans le BUT de référentiel indiqué. """Nombre d'ECTS validés par etud dans le BUT de référentiel indiqué.
Ne prend que les UE associées à des niveaux de compétences, Ne prend que les UE associées à des niveaux de compétences,
et ne les compte qu'une fois même en cas de redoublement avec re-validation. et ne les compte qu'une fois même en cas de redoublement avec re-validation.
@ -398,7 +402,7 @@ def but_ects_valides(etud: Identite, referentiel_competence_id: int) -> float:
if v.code in CODES_UE_VALIDES: if v.code in CODES_UE_VALIDES:
ects_dict[key] = v.ue.ects ects_dict[key] = v.ue.ects
return sum(ects_dict.values()) if ects_dict else 0.0 return int(sum(ects_dict.values())) if ects_dict else 0
def etud_ues_de_but1_non_validees( def etud_ues_de_but1_non_validees(

View File

@ -322,7 +322,7 @@ class NotesTableCompat(ResultatsSemestre):
validations = self.get_formsemestre_validations() validations = self.get_formsemestre_validations()
return validations.decisions_jury_ues.get(etudid, None) return validations.decisions_jury_ues.get(etudid, None)
def get_etud_ects_valides(self, etudid: int, decisions_ues: dict = False) -> 0: def get_etud_ects_valides(self, etudid: int, decisions_ues: dict = False) -> int:
"""Le total des ECTS validés (et enregistrés) par l'étudiant dans ce semestre. """Le total des ECTS validés (et enregistrés) par l'étudiant dans ce semestre.
NB: avant jury, rien d'enregistré, donc zéro ECTS. NB: avant jury, rien d'enregistré, donc zéro ECTS.
Optimisation: si decisions_ues est passé, l'utilise, sinon appelle get_etud_decisions_ue() Optimisation: si decisions_ues est passé, l'utilise, sinon appelle get_etud_decisions_ue()
@ -330,8 +330,8 @@ class NotesTableCompat(ResultatsSemestre):
if decisions_ues is False: if decisions_ues is False:
decisions_ues = self.get_etud_decisions_ue(etudid) decisions_ues = self.get_etud_decisions_ue(etudid)
if not decisions_ues: if not decisions_ues:
return 0.0 return 0
return sum([d.get("ects", 0.0) for d in decisions_ues.values()]) return int(sum(d.get("ects", 0) for d in decisions_ues.values()))
def get_etud_decision_sem(self, etudid: int) -> dict: def get_etud_decision_sem(self, etudid: int) -> dict:
"""Decision du jury semestre prise pour cet etudiant, ou None s'il n'y en pas eu. """Decision du jury semestre prise pour cet etudiant, ou None s'il n'y en pas eu.

View File

@ -247,10 +247,11 @@ def _build_decisions_rcue_list(decisions_rcue: dict) -> list[str]:
# où validation est {'code': 'CMP', 'niveau': {'annee': 'BUT3', 'competence': {}, ... } # où validation est {'code': 'CMP', 'niveau': {'annee': 'BUT3', 'competence': {}, ... }
validation_by_competence = defaultdict(list) validation_by_competence = defaultdict(list)
for validation in decisions_rcue: for validation in decisions_rcue:
competence_id = ( if validation:
validation.get("niveau", {}).get("competence", {}).get("id_orebut") competence_id = (
) validation.get("niveau", {}).get("competence", {}).get("id_orebut")
validation_by_competence[competence_id].append(validation) )
validation_by_competence[competence_id].append(validation)
# Tri des listes de validation par numéro de compétence # Tri des listes de validation par numéro de compétence
validations_niveaux = sorted( validations_niveaux = sorted(
validation_by_competence.values(), validation_by_competence.values(),

View File

@ -8,9 +8,11 @@
""" """
import collections import collections
import time
import numpy as np import numpy as np
from flask import g, url_for from flask import g, url_for
from app import log
from app.but import cursus_but from app.but import cursus_but
from app.but import jury_but from app.but import jury_but
from app.but.jury_but import DecisionsProposeesRCUE from app.but.jury_but import DecisionsProposeesRCUE
@ -33,10 +35,12 @@ class TableJury(TableRecap):
- les RCUEs (moyenne et code décision) - les RCUEs (moyenne et code décision)
Pour toutes les formations: Pour toutes les formations:
- les codes de décisions jury sur les UEs - les codes de décisions jury sur les UEs
- les ECTS acquis dans le parcours
- le lien de saisie ou modif de la décision de jury - le lien de saisie ou modif de la décision de jury
""" """
def __init__(self, *args, row_class: str = None, read_only=True, **kwargs): def __init__(self, *args, row_class: str = None, read_only=True, **kwargs):
t0 = time.time()
super().__init__( super().__init__(
*args, row_class=row_class or RowJury, finalize=False, **kwargs *args, row_class=row_class or RowJury, finalize=False, **kwargs
) )
@ -55,6 +59,7 @@ class TableJury(TableRecap):
self.add_groups_header() self.add_groups_header()
# Termine la table # Termine la table
self.finalize() self.finalize()
log(f"Built TableJury for {self.res.formsemestre} in {time.time() - t0}s")
def add_rcues(self): def add_rcues(self):
"""Ajoute les colonnes indiquant le nb de RCUEs et chaque RCUE """Ajoute les colonnes indiquant le nb de RCUEs et chaque RCUE
@ -75,7 +80,7 @@ class TableJury(TableRecap):
self.freq_codes_annuels["total"] = len(self.rows) self.freq_codes_annuels["total"] = len(self.rows)
def add_jury(self): def add_jury(self):
"""Ajoute la colonne code jury et le lien. """Ajoute la colonne code jury, ECTS et le lien.
- Le code jury est celui du semestre: cette colonne n'est montrée - Le code jury est celui du semestre: cette colonne n'est montrée
que pour les formations classiques, ce code n'est pas utilisé en BUT. que pour les formations classiques, ce code n'est pas utilisé en BUT.
- En BUT, on donne la décision de jury annuelle. - En BUT, on donne la décision de jury annuelle.
@ -138,6 +143,20 @@ class TableJury(TableRecap):
group="jury_code_sem", group="jury_code_sem",
classes=["recorded_code"], classes=["recorded_code"],
) )
# ECTS acquis en BUT
if res.formsemestre.formation.referentiel_competence_id:
row.add_cell(
"ects_acquis",
"ECTS",
# res.get_etud_ects_valides(etud.id),
# cette recherche augmente de 10% le temps de contsruction de la table
cursus_but.but_ects_valides(
etud, res.formsemestre.formation.referentiel_competence_id
),
group="jury_code_sem",
classes=["recorded_code"],
target_attrs={"title": "crédits validés en BUT"},
)
# Lien saisie ou visu jury # Lien saisie ou visu jury
a_saisir = (not res.validations) or (not res.validations.has_decision(etud)) a_saisir = (not res.validations) or (not res.validations.has_decision(etud))
row.add_cell( row.add_cell(

View File

@ -661,7 +661,7 @@ class RowRecap(tb.Row):
# Ajoute bulle sur titre du pied de table: # Ajoute bulle sur titre du pied de table:
cell = table.foot_title_row.cells.get("moy_gen") cell = table.foot_title_row.cells.get("moy_gen")
if cell: if cell:
table.foot_title_row.cells["moy_gen"].target_attrs["title"] = ( cell.target_attrs["title"] = (
"Moyenne générale indicative" "Moyenne générale indicative"
if res.is_apc if res.is_apc
else "Moyenne générale du semestre" else "Moyenne générale du semestre"

View File

@ -1,7 +1,7 @@
{# Affichage cursus BUT fiche étudiant #} {# Affichage cursus BUT fiche étudiant #}
<div class="cursus_but"> <div class="cursus_but">
<div class="cb_head"></div> <div class="cb_head">{{cursus.get_ects_acquis()}} ECTS</div>
<div class="cb_head">BUT 1</div> <div class="cb_head">BUT 1</div>
<div class="cb_head">BUT 2</div> <div class="cb_head">BUT 2</div>
<div class="cb_head">BUT 3</div> <div class="cb_head">BUT 3</div>

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "9.6.987" SCOVERSION = "9.6.988"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"