From 3bc60c268a372d18a17894109cb218750b4bef45 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 13 Nov 2022 14:22:47 +0100 Subject: [PATCH] FIX: calcul notes moyennes avec rattrapages ou session 2 + test unitaire --- app/comp/moy_mod.py | 22 +++++--- tests/unit/test_notes_rattrapage.py | 87 +++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/app/comp/moy_mod.py b/app/comp/moy_mod.py index 425f2b4e1..5d6e80aaf 100644 --- a/app/comp/moy_mod.py +++ b/app/comp/moy_mod.py @@ -35,14 +35,15 @@ moyenne générale d'une UE. """ import dataclasses from dataclasses import dataclass + import numpy as np import pandas as pd from app import db -from app.models import ModuleImpl, Evaluation, EvaluationUEPoids +from app.models import Evaluation, EvaluationUEPoids, ModuleImpl +from app.scodoc import sco_cache from app.scodoc import sco_utils as scu from app.scodoc.sco_codes_parcours import UE_SPORT -from app.scodoc import sco_cache from app.scodoc.sco_exceptions import ScoBugCatcher from app.scodoc.sco_utils import ModuleType @@ -217,12 +218,19 @@ class ModuleImplResults: ] def get_evaluations_coefs(self, moduleimpl: ModuleImpl) -> np.array: - """Coefficients des évaluations, met à zéro ceux des évals incomplètes. + """Coefficients des évaluations. + Les coefs des évals incomplètes et non "normales" (session 2, rattrapage) + sont zéro. Résultat: 2d-array of floats, shape (nb_evals, 1) """ return ( np.array( - [e.coefficient for e in moduleimpl.evaluations], + [ + e.coefficient + if e.evaluation_type == scu.EVALUATION_NORMALE + else 0.0 + for e in moduleimpl.evaluations + ], dtype=float, ) * self.evaluations_completes @@ -236,8 +244,8 @@ class ModuleImplResults: ] def get_eval_notes_sur_20(self, moduleimpl: ModuleImpl) -> np.array: - """Les notes des évaluations, - remplace les ATT, EXC, ABS, NaN par zéro et mets les notes sur 20. + """Les notes de toutes les évaluations du module, complètes ou non. + Remplace les ATT, EXC, ABS, NaN par zéro et mets les notes sur 20. Résultat: 2d array of floats, shape nb_etuds x nb_evaluations """ return np.where( @@ -368,7 +376,7 @@ class ModuleImplResultsAPC(ModuleImplResults): etuds_moy_module = np.where( etuds_use_rattrapage, notes_rat_ues, etuds_moy_module ) - # Serie indiquant que l'étudiant utilise une note de rattarage sur l'une des UE: + # Serie indiquant que l'étudiant utilise une note de rattrapage sur l'une des UE: self.etuds_use_rattrapage = pd.Series( etuds_use_rattrapage.any(axis=1), index=self.evals_notes.index ) diff --git a/tests/unit/test_notes_rattrapage.py b/tests/unit/test_notes_rattrapage.py index aaa9e740d..07a6763ff 100644 --- a/tests/unit/test_notes_rattrapage.py +++ b/tests/unit/test_notes_rattrapage.py @@ -1,15 +1,22 @@ """Test calculs rattrapages """ -from config import TestConfig -from tests.unit import sco_fake_gen - from flask import g import app -from app.scodoc import sco_bulletins -from app.scodoc import sco_formsemestre +from app.but.bulletin_but import * +from app.comp import res_sem +from app.comp.res_but import ResultatsSemestreBUT +from app.models import ModuleImpl +from app.scodoc import ( + sco_bulletins, + sco_evaluation_db, + sco_formsemestre, + sco_saisie_notes, +) from app.scodoc import sco_utils as scu +from config import TestConfig +from tests.unit import sco_fake_gen DEPT = TestConfig.DEPT_TEST @@ -70,6 +77,19 @@ def test_notes_rattrapage(test_client): etud = etuds[0] _, _, _ = G.create_note(evaluation=e, etud=etud, note=12.0) _, _, _ = G.create_note(evaluation=e_rat, etud=etud, note=11.0) + + # --- Vérifications internes structures ScoDoc + formsemestre = FormSemestre.query.get(formsemestre_id) + res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre) + mod_res = res.modimpls_results[moduleimpl_id] + moduleimpl = ModuleImpl.query.get(moduleimpl_id) + # retrouve l'éval. de rattrapage: + eval_rat = mod_res.get_evaluation_rattrapage(moduleimpl) + assert eval_rat.id == e_rat["id"] + # Les deux évaluations sont considérées comme complètes: + assert len(mod_res.get_evaluations_completes(moduleimpl)) == 2 + + # --- Vérification sur bulletin b = sco_bulletins.formsemestre_bulletinetud_dict( sem["formsemestre_id"], etud["etudid"] ) @@ -99,3 +119,60 @@ def test_notes_rattrapage(test_client): sem["formsemestre_id"], etud["etudid"] ) assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(10.0) + + # Supprime toutes les notes de l'évaluation de rattrapage: + sco_saisie_notes.evaluation_suppress_alln(e_rat["id"], dialog_confirmed=True) + b = sco_bulletins.formsemestre_bulletinetud_dict( + sem["formsemestre_id"], etud["etudid"] + ) + # Vérifie structure du bulletin: + assert b["etudid"] == etud["etudid"] + assert len(b["ues"][0]["modules"][0]["evaluations"]) == 1 # reste une eval normale + assert len(b["ues"][0]["modules"]) == 1 + # Note moyenne: reviens à 10/20 + assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(10.0) + # Supprime l'évaluation de rattrapage: + sco_evaluation_db.do_evaluation_delete(e_rat["id"]) + b = sco_bulletins.formsemestre_bulletinetud_dict( + sem["formsemestre_id"], etud["etudid"] + ) + assert len(b["ues"][0]["modules"][0]["evaluations"]) == 1 # reste une eval normale + + # Création évaluation session 2: + e_session2 = G.create_evaluation( + moduleimpl_id=moduleimpl_id, + jour="02/01/2020", + description="evaluation session 2", + coefficient=1.0, + evaluation_type=scu.EVALUATION_SESSION2, + ) + + res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre) + mod_res = res.modimpls_results[moduleimpl_id] + # retrouve l'éval. de session 2: + eval_session2 = mod_res.get_evaluation_session2(moduleimpl) + assert eval_session2.id == e_session2["id"] + # Les deux évaluations sont considérées comme complètes: + assert len(mod_res.get_evaluations_completes(moduleimpl)) == 2 + + # Saisie note session 2: + _, _, _ = G.create_note(evaluation=e_session2, etud=etud, note=5.0) + b = sco_bulletins.formsemestre_bulletinetud_dict( + sem["formsemestre_id"], etud["etudid"] + ) + # Note moyenne: utilise session 2 même si inférieure + assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(5.0) + + _, _, _ = G.create_note(evaluation=e_session2, etud=etud, note=20.0) + b = sco_bulletins.formsemestre_bulletinetud_dict( + sem["formsemestre_id"], etud["etudid"] + ) + # Note moyenne: utilise session 2 même si inférieure + assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(20.0) + + _, _, _ = G.create_note(evaluation=e_session2, etud=etud, note=None) + b = sco_bulletins.formsemestre_bulletinetud_dict( + sem["formsemestre_id"], etud["etudid"] + ) + # Note moyenne: revient à note normale + assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(10.0)