ScoDoc/tests/unit/test_notes_modules.py

474 lines
16 KiB
Python
Raw Normal View History

2021-10-30 23:27:27 +02:00
"""Test calculs moyennes de modules
Vérif moyennes de modules des bulletins
et aussi moyennes modules et UE internes (via nt)
2021-10-30 23:27:27 +02:00
"""
2023-08-25 17:58:57 +02:00
import datetime
2022-11-12 17:28:05 +01:00
import numpy as np
from flask import g
2021-10-30 23:27:27 +02:00
from config import TestConfig
from tests.unit import sco_fake_gen
import app
from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre
2022-01-15 21:36:06 +01:00
from app.scodoc import sco_bulletins, sco_formsemestre
from app.scodoc import sco_formsemestre_inscriptions
2021-10-30 23:27:27 +02:00
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_utils as scu
DEPT = TestConfig.DEPT_TEST
def check_nt(
etudid,
formsemestre_id,
ue_id,
moduleimpl_id,
expected_moy_ue=False,
expected_mod_moy=False,
):
"""Vérification bas niveau: vérif resultat avec l'API internet "nt"
(peut changer dans le futur, ne pas utiliser hors ScoDoc !)
ne vérifie que les valeurs expected non False
"""
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
mod_moy = nt.get_etud_mod_moy(moduleimpl_id, etudid)
if expected_moy_ue is not False:
ue_status = nt.get_etud_ue_status(etudid, ue_id)
2022-11-12 17:28:05 +01:00
if np.isnan(expected_moy_ue):
assert np.isnan(ue_status["moy"])
else:
assert expected_moy_ue == ue_status["moy"]
if expected_mod_moy is not False:
2022-11-12 17:28:05 +01:00
if not isinstance(expected_mod_moy, str) and np.isnan(expected_mod_moy):
assert np.isnan(mod_moy)
else:
assert expected_mod_moy == mod_moy
return nt
2021-10-30 23:27:27 +02:00
def test_notes_modules(test_client):
"""Test calcul des moyennes de modules et d'UE
Création étudiant, formation, semestre, inscription etudiant,
création evaluation, saisie de notes.
2021-10-30 23:27:27 +02:00
Vérifie calcul moyenne avec absences (ABS), excuse (EXC), attente (ATT)
"""
app.set_sco_dept(DEPT)
G = sco_fake_gen.ScoFake(verbose=False)
etuds = [G.create_etud(code_nip=None) for i in range(2)] # 2 étudiants
2021-10-30 23:27:27 +02:00
2022-01-15 21:36:06 +01:00
formation_id = G.create_formation(acronyme="")
ue_id = G.create_ue(formation_id=formation_id, acronyme="TST1", titre="ue test")
matiere_id = G.create_matiere(ue_id=ue_id, titre="matière test")
coef_mod_1 = 1.5
2022-01-15 21:36:06 +01:00
module_id = G.create_module(
matiere_id=matiere_id,
2021-10-30 23:27:27 +02:00
code="TSM1",
coefficient=coef_mod_1,
2021-10-30 23:27:27 +02:00
titre="module test",
)
# --- Mise place d'un semestre
2022-01-15 21:36:06 +01:00
formsemestre_id = G.create_formsemestre(
formation_id=formation_id,
2021-10-30 23:27:27 +02:00
semestre_id=1,
date_debut="01/01/2020",
date_fin="30/06/2020",
)
2022-01-15 21:36:06 +01:00
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
moduleimpl_id = G.create_moduleimpl(
module_id=module_id,
formsemestre_id=formsemestre_id,
2021-10-30 23:27:27 +02:00
)
# --- Inscription des étudiants
for etud in etuds:
2022-01-15 21:36:06 +01:00
G.inscrit_etudiant(formsemestre_id, etud)
2021-10-30 23:27:27 +02:00
etud = etuds[0]
etudid = etud["etudid"]
2021-10-30 23:27:27 +02:00
# --- Creation évaluations: e1, e2
coef_1 = 1.0
coef_2 = 2.0
e1 = G.create_evaluation(
moduleimpl_id=moduleimpl_id,
2023-08-25 17:58:57 +02:00
date_debut=datetime.datetime(2020, 1, 1),
2021-10-30 23:27:27 +02:00
description="evaluation 1",
coefficient=coef_1,
)
e2 = G.create_evaluation(
moduleimpl_id=moduleimpl_id,
2023-08-25 17:58:57 +02:00
date_debut=datetime.datetime(2020, 1, 1),
2021-10-30 23:27:27 +02:00
description="evaluation 2",
coefficient=coef_2,
)
# --- Notes ordinaires
note_1 = 12.0
note_2 = 13.0
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etuds[0]["etudid"], note=note_1
)
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e2["evaluation_id"], etudid=etuds[0]["etudid"], note=note_2
2022-12-06 13:06:50 +01:00
)
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etuds[1]["etudid"], note=note_1 / 2
2022-12-06 13:06:50 +01:00
)
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e2["evaluation_id"], etudid=etuds[1]["etudid"], note=note_2 / 3
)
2021-10-30 23:27:27 +02:00
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"]) == 2
assert len(b["ues"][0]["modules"]) == 1
# Note moyenne:
note_th = (coef_1 * note_1 + coef_2 * note_2) / (coef_1 + coef_2)
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(note_th)
check_nt(
etudid,
formsemestre_id,
ue_id,
moduleimpl_id,
expected_mod_moy=note_th,
expected_moy_ue=note_th,
)
2021-10-30 23:27:27 +02:00
# Absence à une évaluation
2023-08-25 17:58:57 +02:00
_, _, _ = G.create_note(
evaluation_id=e1["evaluation_id"], etudid=etudid, note=None
) # abs
_, _, _ = G.create_note(
evaluation_id=e2["evaluation_id"], etudid=etudid, note=note_2
)
2021-10-30 23:27:27 +02:00
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
note_th = (coef_1 * 0.0 + coef_2 * note_2) / (coef_1 + coef_2)
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(note_th)
# Absences aux deux évaluations
2023-08-25 17:58:57 +02:00
_, _, _ = G.create_note(
evaluation_id=e1["evaluation_id"], etudid=etudid, note=None
) # abs
_, _, _ = G.create_note(
evaluation_id=e2["evaluation_id"], etudid=etudid, note=None
) # abs
2021-10-30 23:27:27 +02:00
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(0.0)
check_nt(
etudid,
formsemestre_id,
ue_id,
moduleimpl_id,
expected_mod_moy=0.0,
expected_moy_ue=0.0,
)
2021-10-30 23:27:27 +02:00
# Note excusée EXC <-> scu.NOTES_NEUTRALISE
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etudid, note=note_1
)
_, _, _ = G.create_note(
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
) # EXC
2021-10-30 23:27:27 +02:00
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(note_1)
check_nt(
etudid,
formsemestre_id,
ue_id,
moduleimpl_id,
expected_mod_moy=note_1,
expected_moy_ue=note_1,
)
2021-10-30 23:27:27 +02:00
# Note en attente ATT <-> scu.NOTES_ATTENTE
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etudid, note=note_1
)
_, _, _ = G.create_note(
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_ATTENTE
) # ATT
2021-10-30 23:27:27 +02:00
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(note_1)
check_nt(
etudid,
formsemestre_id,
ue_id,
moduleimpl_id,
expected_mod_moy=note_1,
expected_moy_ue=note_1,
)
2021-10-30 23:27:27 +02:00
# Neutralisation (EXC) des 2 évals
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
) # EXC
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
) # EXC
2021-10-30 23:27:27 +02:00
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
2022-11-12 17:28:05 +01:00
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == "~"
check_nt(
etudid,
sem["formsemestre_id"],
2022-01-15 21:36:06 +01:00
ue_id,
moduleimpl_id,
2022-11-12 17:28:05 +01:00
expected_mod_moy=np.nan,
expected_moy_ue=np.nan,
)
# Attente (ATT) sur les 2 evals
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etudid, note=scu.NOTES_ATTENTE
) # ATT
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_ATTENTE
) # ATT
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
2022-11-12 17:28:05 +01:00
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == "~"
check_nt(
etudid,
sem["formsemestre_id"],
2022-01-15 21:36:06 +01:00
ue_id,
moduleimpl_id,
2022-11-12 17:28:05 +01:00
expected_mod_moy=np.nan,
expected_moy_ue=np.nan,
)
2021-10-30 23:27:27 +02:00
# Non inscrit
# - désinscrit notre étudiant:
inscr = sco_moduleimpl.do_moduleimpl_inscription_list(
2022-01-15 21:36:06 +01:00
moduleimpl_id=moduleimpl_id, etudid=etud["etudid"]
2021-10-30 23:27:27 +02:00
)
assert len(inscr) == 1
oid = inscr[0]["moduleimpl_inscription_id"]
sco_moduleimpl.do_moduleimpl_inscription_delete(
2022-01-15 21:36:06 +01:00
oid, formsemestre_id=sem["formsemestre_id"]
2021-10-30 23:27:27 +02:00
)
# -
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
assert b["ues"] == [] # inscrit à aucune UE !
check_nt(
etudid,
formsemestre_id,
ue_id,
moduleimpl_id,
expected_mod_moy="NI",
2022-11-12 17:28:05 +01:00
expected_moy_ue=np.nan,
)
# --- Maintenant avec 2 modules dans l'UE
coef_mod_2 = 2.1
2022-01-15 21:36:06 +01:00
module_id2 = G.create_module(
matiere_id=matiere_id,
code="TSM2",
coefficient=coef_mod_2,
titre="module test 2",
)
2022-01-15 21:36:06 +01:00
moduleimpl_id2 = G.create_moduleimpl(
module_id=module_id2,
formsemestre_id=formsemestre_id,
)
2022-11-12 17:28:05 +01:00
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
# Pour prendre en compte l'ajout au vol d'un moduleimpl:
del formsemestre.modimpls_sorted
# Re-inscription au premier module de l'UE
sco_moduleimpl.do_moduleimpl_inscription_create(
2022-01-15 21:36:06 +01:00
{"etudid": etudid, "moduleimpl_id": moduleimpl_id},
formsemestre_id=formsemestre_id,
)
2023-08-25 17:58:57 +02:00
_, _, _ = G.create_note(evaluation_id=e1["evaluation_id"], etudid=etudid, note=12.5)
2022-11-12 17:28:05 +01:00
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
2022-11-12 17:28:05 +01:00
mod_stats = nt.get_mod_stats(moduleimpl_id)
assert mod_stats["nb_missing"] == 0
assert mod_stats["nb_notes"] == 2
ue_status = nt.get_etud_ue_status(etudid, ue_id)
assert not ue_status["was_capitalized"]
# Inscription au deuxième module de l'UE
sco_moduleimpl.do_moduleimpl_inscription_create(
2022-01-15 21:36:06 +01:00
{"etudid": etudid, "moduleimpl_id": moduleimpl_id2},
formsemestre_id=formsemestre_id,
)
sco_moduleimpl.do_moduleimpl_inscription_create(
2022-01-15 21:36:06 +01:00
{"etudid": etuds[1]["etudid"], "moduleimpl_id": moduleimpl_id2},
formsemestre_id=formsemestre_id,
)
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
ue_status = nt.get_etud_ue_status(etudid, ue_id)
2022-11-12 17:28:05 +01:00
# Note dans module 2:
e_m2 = G.create_evaluation(
2022-01-15 21:36:06 +01:00
moduleimpl_id=moduleimpl_id2,
2023-08-25 17:58:57 +02:00
date_debut=datetime.datetime(2020, 1, 1),
description="evaluation mod 2",
coefficient=1.0,
)
2023-08-25 17:58:57 +02:00
_, _, _ = G.create_note(
evaluation_id=e_m2["evaluation_id"], etudid=etudid, note=19.5
)
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
ue_status = nt.get_etud_ue_status(etudid, ue_id)
2021-11-06 10:58:56 +01:00
# Moyenne d'UE si l'un des modules est EXC ("NA")
# 2 modules, notes EXC dans le premier, note valide n dans le second
# la moyenne de l'UE doit être n
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
) # EXC
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
) # EXC
2022-12-06 13:06:50 +01:00
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e_m2["evaluation_id"], etudid=etudid, note=12.5
)
_, _, _ = G.create_note(
evaluation_id=e1["evaluation_id"], etudid=etuds[1]["etudid"], note=11.0
2022-12-06 13:06:50 +01:00
)
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e2["evaluation_id"], etudid=etuds[1]["etudid"], note=11.0
2022-12-06 13:06:50 +01:00
)
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e_m2["evaluation_id"], etudid=etuds[1]["etudid"], note=11.0
2022-12-06 13:06:50 +01:00
)
2022-11-12 17:28:05 +01:00
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"]
)
assert b["ues"][0]["ue_status"]["cur_moy_ue"] == 12.5
assert b["ues"][0]["ue_status"]["moy"] == 12.5
b2 = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etuds[1]["etudid"]
)
assert b2["ues"][0]["ue_status"]["cur_moy_ue"] == 11.0
assert b2["ues"][0]["ue_status"]["moy"] == 11
def test_notes_modules_att_dem(test_client):
"""Scénario dit "lyonnais":
Des étudiants, des notes, plusieurs étudiants avec notes ATT (ici notes éval en "attente"),
démission d'un étudiant qui avait ATT. Passage des autres ATT en EXC ou ABS.
On va tester avec un module, une éval, deux étudiants
"""
app.set_sco_dept(DEPT)
G = sco_fake_gen.ScoFake(verbose=False)
etuds = [G.create_etud(code_nip=None) for i in range(2)] # 2 étudiants
2022-01-15 21:36:06 +01:00
formation_id = G.create_formation(acronyme="")
ue_id = G.create_ue(formation_id=formation_id, acronyme="TST1", titre="ue test")
matiere_id = G.create_matiere(ue_id=ue_id, titre="matière test")
coef_mod_1 = 1.5
2022-01-15 21:36:06 +01:00
module_id = G.create_module(
matiere_id=matiere_id,
code="TSM1",
coefficient=coef_mod_1,
titre="module test",
)
#
# --------------------------------
#
2022-01-15 21:36:06 +01:00
formsemestre_id = G.create_formsemestre(
formation_id=formation_id,
semestre_id=1,
date_debut="01/01/2020",
date_fin="30/06/2020",
)
2022-01-15 21:36:06 +01:00
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
formsemestre_id = sem["formsemestre_id"]
2022-01-15 21:36:06 +01:00
moduleimpl_id = G.create_moduleimpl(
module_id=module_id,
formsemestre_id=formsemestre_id,
)
# --- Inscription des étudiants
for etud in etuds:
2022-01-15 21:36:06 +01:00
G.inscrit_etudiant(formsemestre_id, etud)
# --- Creation évaluation: e1
coef_1 = 1.0
e1 = G.create_evaluation(
moduleimpl_id=moduleimpl_id,
2023-08-25 17:58:57 +02:00
date_debut=datetime.datetime(2020, 1, 1),
description="evaluation 1",
coefficient=coef_1,
)
# Attente (ATT) sur les 2 evals
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"],
etudid=etuds[0]["etudid"],
note=scu.NOTES_ATTENTE,
) # ATT
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"],
etudid=etuds[1]["etudid"],
note=scu.NOTES_ATTENTE,
) # ATT
# Démission du premier étudiant
sco_formsemestre_inscriptions.do_formsemestre_demission(
etuds[0]["etudid"],
sem["formsemestre_id"],
event_date="02/01/2020",
)
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etuds[0]["etudid"]
)
assert b["etud_etat"] == "D"
assert b["nb_demissions"] == 1
2022-11-12 17:28:05 +01:00
# bulletin de l'étudiant non demissionnaire:
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etuds[1]["etudid"]
)
assert b["etud_etat"] == "I"
assert b["nb_demissions"] == 1
assert len(b["ues"]) == 1
nt = check_nt(
etuds[1]["etudid"],
sem["formsemestre_id"],
ue_id,
moduleimpl_id,
2022-11-12 17:28:05 +01:00
expected_mod_moy=np.nan,
expected_moy_ue=np.nan,
)
2022-11-12 17:28:05 +01:00
note_e1 = nt.modimpls_results[moduleimpl_id].evals_notes[e1["evaluation_id"]][
etuds[1]["etudid"]
]
assert note_e1 == scu.NOTES_ATTENTE
note_e1 = nt.modimpls_results[moduleimpl_id].evals_notes[e1["evaluation_id"]][
etuds[0]["etudid"]
]
assert note_e1 == scu.NOTES_ATTENTE # XXXX un peu contestable
# Saisie note ABS pour le deuxième etud
2022-12-06 13:06:50 +01:00
_, _, _ = G.create_note(
2023-08-25 17:58:57 +02:00
evaluation_id=e1["evaluation_id"], etudid=etuds[1]["etudid"], note=None
2022-12-06 13:06:50 +01:00
)
nt = check_nt(
etuds[1]["etudid"],
sem["formsemestre_id"],
ue_id,
moduleimpl_id,
expected_mod_moy=0.0,
expected_moy_ue=0.0,
)
2022-11-12 17:28:05 +01:00
note_e1 = nt.modimpls_results[moduleimpl_id].evals_notes[e1["evaluation_id"]][
etuds[1]["etudid"]
]
assert note_e1 == scu.NOTES_ABSENCE