forked from ScoDoc/DocScoDoc
min/max evals sur bul. json classic. + Tests unitaires bulletin.
This commit is contained in:
parent
9dbcd2c8a2
commit
6838c970a4
@ -101,7 +101,7 @@ Certains tests ont besoin d'un département déjà créé, qui n'est pas créé
|
||||
scripts de tests:
|
||||
Lancer au préalable:
|
||||
|
||||
flask delete-dept TEST00 && flask create-dept TEST00
|
||||
flask delete-dept -fy TEST00 && flask create-dept TEST00
|
||||
|
||||
Puis dérouler les tests unitaires:
|
||||
|
||||
|
@ -435,8 +435,6 @@ def initialize_scodoc_database(erase=False, create_all=False):
|
||||
SQL tables and functions.
|
||||
If erase is True, _erase_ all database content.
|
||||
"""
|
||||
from app import models
|
||||
|
||||
# - ERASE (the truncation sql function has been defined above)
|
||||
if erase:
|
||||
truncate_database()
|
||||
|
@ -43,6 +43,7 @@ import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_edit_ue
|
||||
from app.scodoc import sco_evaluations
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups
|
||||
@ -84,13 +85,14 @@ def formsemestre_bulletinetud_published_dict(
|
||||
xml_nodate=False,
|
||||
xml_with_decisions=False, # inclue les decisions même si non publiées
|
||||
version="long",
|
||||
):
|
||||
) -> dict:
|
||||
"""Dictionnaire representant les informations _publiees_ du bulletin de notes
|
||||
Utilisé pour JSON, devrait l'être aussi pour XML. (todo)
|
||||
"""
|
||||
from app.scodoc import sco_bulletins
|
||||
|
||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
prefs = sco_preferences.SemPreferences(formsemestre_id)
|
||||
etud = Identite.query.get(etudid)
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||
|
||||
@ -158,11 +160,8 @@ def formsemestre_bulletinetud_published_dict(
|
||||
ues = nt.get_ues_stat_dict()
|
||||
modimpls = nt.get_modimpls_dict()
|
||||
nbetuds = len(nt.etud_moy_gen_ranks)
|
||||
mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
|
||||
if (
|
||||
nt.get_moduleimpls_attente()
|
||||
or sco_preferences.get_preference("bul_show_rangs", formsemestre_id) == 0
|
||||
):
|
||||
moy_gen = scu.fmt_note(nt.get_etud_moy_gen(etudid))
|
||||
if nt.get_moduleimpls_attente() or not prefs["bul_show_rangs"]:
|
||||
# n'affiche pas le rang sur le bulletin s'il y a des
|
||||
# notes en attente dans ce semestre
|
||||
rang = ""
|
||||
@ -175,7 +174,7 @@ def formsemestre_bulletinetud_published_dict(
|
||||
)
|
||||
|
||||
d["note"] = dict(
|
||||
value=mg,
|
||||
value=moy_gen,
|
||||
min=scu.fmt_note(nt.moy_min),
|
||||
max=scu.fmt_note(nt.moy_max),
|
||||
moy=scu.fmt_note(nt.moy_moy),
|
||||
@ -217,9 +216,7 @@ def formsemestre_bulletinetud_published_dict(
|
||||
value=scu.fmt_note(ue_status["cur_moy_ue"] if ue_status else ""),
|
||||
min=scu.fmt_note(ue["min"]),
|
||||
max=scu.fmt_note(ue["max"]),
|
||||
moy=scu.fmt_note(
|
||||
ue["moy"]
|
||||
), # CM : ajout pour faire apparaitre la moyenne des UE
|
||||
moy=scu.fmt_note(ue["moy"]),
|
||||
),
|
||||
rang=rang,
|
||||
effectif=effectif,
|
||||
@ -259,10 +256,7 @@ def formsemestre_bulletinetud_published_dict(
|
||||
m["note"][k] = scu.fmt_note(m["note"][k])
|
||||
|
||||
u["module"].append(m)
|
||||
if (
|
||||
sco_preferences.get_preference("bul_show_mod_rangs", formsemestre_id)
|
||||
and nt.mod_rangs is not None
|
||||
):
|
||||
if prefs["bul_show_mod_rangs"] and nt.mod_rangs is not None:
|
||||
m["rang"] = dict(
|
||||
value=nt.mod_rangs[modimpl["moduleimpl_id"]][0][etudid]
|
||||
)
|
||||
@ -274,33 +268,40 @@ def formsemestre_bulletinetud_published_dict(
|
||||
if version != "short":
|
||||
for e in evals:
|
||||
if e["visibulletin"] or version == "long":
|
||||
val = e["notes"].get(etudid, {"value": "NP"})[
|
||||
"value"
|
||||
] # NA si etud demissionnaire
|
||||
val = e["notes"].get(etudid, {"value": "NP"})["value"]
|
||||
# nb: val est NA si etud démissionnaire
|
||||
val = scu.fmt_note(val, note_max=e["note_max"])
|
||||
m["evaluation"].append(
|
||||
dict(
|
||||
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
|
||||
heure_debut=ndb.TimetoISO8601(
|
||||
e["heure_debut"], null_is_empty=True
|
||||
),
|
||||
heure_fin=ndb.TimetoISO8601(
|
||||
e["heure_fin"], null_is_empty=True
|
||||
),
|
||||
coefficient=e["coefficient"],
|
||||
evaluation_type=e["evaluation_type"],
|
||||
evaluation_id=e[
|
||||
"evaluation_id"
|
||||
], # CM : ajout pour permettre de faire le lien sur les bulletins en ligne avec l'évaluation
|
||||
description=quote_xml_attr(e["description"]),
|
||||
note=val,
|
||||
)
|
||||
eval_dict = dict(
|
||||
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
|
||||
heure_debut=ndb.TimetoISO8601(
|
||||
e["heure_debut"], null_is_empty=True
|
||||
),
|
||||
heure_fin=ndb.TimetoISO8601(
|
||||
e["heure_fin"], null_is_empty=True
|
||||
),
|
||||
coefficient=e["coefficient"],
|
||||
evaluation_type=e["evaluation_type"],
|
||||
# CM : ajout pour permettre de faire le lien sur
|
||||
# les bulletins en ligne avec l'évaluation:
|
||||
evaluation_id=e["evaluation_id"],
|
||||
description=quote_xml_attr(e["description"]),
|
||||
note=val,
|
||||
)
|
||||
if prefs["bul_show_minmax_eval"] or prefs["bul_show_moypromo"]:
|
||||
etat = sco_evaluations.do_evaluation_etat(
|
||||
e["evaluation_id"]
|
||||
)
|
||||
if prefs["bul_show_minmax_eval"]:
|
||||
eval_dict["min"] = scu.fmt_note(etat["mini"])
|
||||
eval_dict["max"] = scu.fmt_note(etat["maxi"])
|
||||
if prefs["bul_show_moypromo"]:
|
||||
eval_dict["moy"] = scu.fmt_note(etat["moy"])
|
||||
|
||||
m["evaluation"].append(eval_dict)
|
||||
|
||||
# Evaluations incomplètes ou futures:
|
||||
complete_eval_ids = set([e["evaluation_id"] for e in evals])
|
||||
if sco_preferences.get_preference(
|
||||
"bul_show_all_evals", formsemestre_id
|
||||
):
|
||||
if prefs["bul_show_all_evals"]:
|
||||
all_evals = sco_evaluation_db.do_evaluation_list(
|
||||
args={"moduleimpl_id": modimpl["moduleimpl_id"]}
|
||||
)
|
||||
@ -344,7 +345,7 @@ def formsemestre_bulletinetud_published_dict(
|
||||
)
|
||||
|
||||
# --- Absences
|
||||
if sco_preferences.get_preference("bul_show_abs", formsemestre_id):
|
||||
if prefs["bul_show_abs"]:
|
||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
||||
d["absences"] = dict(nbabs=nbabs, nbabsjust=nbabsjust)
|
||||
|
||||
@ -403,17 +404,14 @@ def dict_decision_jury(
|
||||
"""
|
||||
from app.scodoc import sco_bulletins
|
||||
|
||||
prefs = sco_preferences.SemPreferences(formsemestre.id)
|
||||
|
||||
d = {}
|
||||
if (
|
||||
sco_preferences.get_preference("bul_show_decision", formsemestre.id)
|
||||
or with_decisions
|
||||
):
|
||||
if prefs["bul_show_decision"] or with_decisions:
|
||||
infos, dpv = sco_bulletins.etud_descr_situation_semestre(
|
||||
etud.id,
|
||||
formsemestre.id,
|
||||
show_uevalid=sco_preferences.get_preference(
|
||||
"bul_show_uevalid", formsemestre.id
|
||||
),
|
||||
show_uevalid=prefs["bul_show_uevalid"],
|
||||
)
|
||||
d["situation"] = infos["situation"]
|
||||
if dpv:
|
||||
|
@ -46,11 +46,12 @@ de la forme %(XXX)s sont remplacées par la valeur de XXX, pour XXX dans:
|
||||
Balises img: actuellement interdites.
|
||||
|
||||
"""
|
||||
from flask import url_for, g
|
||||
|
||||
from reportlab.platypus import KeepTogether, Paragraph, Spacer, Table
|
||||
from reportlab.lib.units import cm, mm
|
||||
from reportlab.lib.colors import Color, blue
|
||||
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_pdf import SU, make_paras
|
||||
from app.scodoc import sco_preferences
|
||||
@ -434,7 +435,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
plusminus = pluslink
|
||||
try:
|
||||
ects_txt = str(int(ue["ects"]))
|
||||
except:
|
||||
except (ValueError, KeyError):
|
||||
ects_txt = "-"
|
||||
|
||||
t = {
|
||||
@ -602,12 +603,14 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
"rang": mod["mod_rang_txt"], # vide si pas option rang
|
||||
"note": mod["mod_moy_txt"],
|
||||
"coef": mod["mod_coef_txt"] if prefs["bul_show_coef"] else "",
|
||||
"abs": mod.get(
|
||||
"mod_abs_txt", ""
|
||||
), # absent si pas option show abs module
|
||||
"_css_row_class": "notes_bulletin_row_mod%s" % rowstyle,
|
||||
"_titre_target": "moduleimpl_status?moduleimpl_id=%s"
|
||||
% mod["moduleimpl_id"],
|
||||
# vide si pas option show abs module:
|
||||
"abs": mod.get("mod_abs_txt", ""),
|
||||
"_css_row_class": f"notes_bulletin_row_mod{rowstyle}",
|
||||
"_titre_target": url_for(
|
||||
"notes.moduleimpl_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
moduleimpl_id=mod["moduleimpl_id"],
|
||||
),
|
||||
"_titre_help": mod["mod_descr_txt"],
|
||||
"_hidden": hidden,
|
||||
"_pdf_style": pdf_style,
|
||||
|
@ -2034,7 +2034,10 @@ class BasePreferences(object):
|
||||
if modif:
|
||||
sco_cache.invalidate_formsemestre()
|
||||
|
||||
def set(self, formsemestre_id, name, value):
|
||||
def set(self, formsemestre_id: int, name: str, value: str):
|
||||
"""Set and save a preference value.
|
||||
If formsemestre_id is None, global pref.
|
||||
"""
|
||||
if not name or name[0] == "_" or name not in self.prefs_name:
|
||||
raise ValueError(f"invalid preference name: {name}")
|
||||
if formsemestre_id and name in self.prefs_only_global:
|
||||
|
@ -39,7 +39,7 @@ from flask_login import current_user
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import Evaluation, FormSemestre
|
||||
from app.models import ScolarNews
|
||||
from app.models import ModuleImpl, ScolarNews
|
||||
from app.models.etudiants import Identite
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
@ -216,7 +216,8 @@ def do_evaluation_upload_xls():
|
||||
eval_id = None
|
||||
if eval_id != evaluation_id:
|
||||
diag.append(
|
||||
f"Erreur: fichier invalide: le code d'évaluation de correspond pas ! ('{eval_id_str}' != '{evaluation_id}')"
|
||||
f"""Erreur: fichier invalide: le code d'évaluation de correspond pas ! ('{
|
||||
eval_id_str}' != '{evaluation_id}')"""
|
||||
)
|
||||
raise InvalidNoteValue()
|
||||
# --- get notes -> list (etudid, value)
|
||||
@ -238,15 +239,14 @@ def do_evaluation_upload_xls():
|
||||
ni += 1
|
||||
except:
|
||||
diag.append(
|
||||
'Erreur: Ligne invalide ! (erreur ligne %d)<br>"%s"'
|
||||
% (ni, str(lines[ni]))
|
||||
f"""Erreur: Ligne invalide ! (erreur ligne {ni})<br>{lines[ni]}"""
|
||||
)
|
||||
raise InvalidNoteValue()
|
||||
# -- check values
|
||||
L, invalids, withoutnotes, absents, _ = _check_notes(notes, E, M["module"])
|
||||
if len(invalids):
|
||||
diag.append(
|
||||
"Erreur: la feuille contient %d notes invalides</p>" % len(invalids)
|
||||
f"Erreur: la feuille contient {len(invalids)} notes invalides</p>"
|
||||
)
|
||||
if len(invalids) < 25:
|
||||
etudsnames = [
|
||||
@ -424,25 +424,34 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
|
||||
evaluation_id, by_uid=current_user.id
|
||||
)
|
||||
else:
|
||||
raise AccessDenied("Modification des notes impossible pour %s" % current_user)
|
||||
raise AccessDenied(f"Modification des notes impossible pour {current_user}")
|
||||
|
||||
notes = [(etudid, scu.NOTES_SUPPRESS) for etudid in notes_db.keys()]
|
||||
|
||||
status_url = url_for(
|
||||
"notes.moduleimpl_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
moduleimpl_id=E["moduleimpl_id"],
|
||||
)
|
||||
|
||||
if not dialog_confirmed:
|
||||
nb_changed, nb_suppress, existing_decisions = notes_add(
|
||||
current_user, evaluation_id, notes, do_it=False, check_inscription=False
|
||||
)
|
||||
msg = (
|
||||
"<p>Confirmer la suppression des %d notes ? <em>(peut affecter plusieurs groupes)</em></p>"
|
||||
% nb_suppress
|
||||
)
|
||||
msg = f"""<p>Confirmer la suppression des {nb_suppress} notes ?
|
||||
<em>(peut affecter plusieurs groupes)</em>
|
||||
</p>
|
||||
"""
|
||||
|
||||
if existing_decisions:
|
||||
msg += """<p class="warning">Important: il y a déjà des décisions de jury enregistrées, qui seront potentiellement à revoir suite à cette modification !</p>"""
|
||||
msg += """<p class="warning">Important: il y a déjà des décisions de
|
||||
jury enregistrées, qui seront potentiellement à revoir suite à
|
||||
cette modification !</p>"""
|
||||
return scu.confirm_dialog(
|
||||
msg,
|
||||
dest_url="",
|
||||
OK="Supprimer les notes",
|
||||
cancel_url="moduleimpl_status?moduleimpl_id=%s" % E["moduleimpl_id"],
|
||||
cancel_url=status_url,
|
||||
parameters={"evaluation_id": evaluation_id},
|
||||
)
|
||||
|
||||
@ -455,26 +464,28 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
|
||||
check_inscription=False,
|
||||
)
|
||||
assert nb_changed == nb_suppress
|
||||
H = ["<p>%s notes supprimées</p>" % nb_suppress]
|
||||
H = [f"""<p>{nb_suppress} notes supprimées</p>"""]
|
||||
if existing_decisions:
|
||||
H.append(
|
||||
"""<p class="warning">Important: il y avait déjà des décisions de jury enregistrées, qui sont potentiellement à revoir suite à cette modification !</p>"""
|
||||
"""<p class="warning">Important: il y avait déjà des décisions
|
||||
de jury enregistrées, qui sont potentiellement à revoir suite
|
||||
à cette modification !
|
||||
</p>"""
|
||||
)
|
||||
H += [
|
||||
'<p><a class="stdlink" href="moduleimpl_status?moduleimpl_id=%s">continuer</a>'
|
||||
% E["moduleimpl_id"]
|
||||
f"""<p><a class="stdlink" href="{status_url}">continuer</a>
|
||||
"""
|
||||
]
|
||||
# news
|
||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
||||
mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]
|
||||
mod["moduleimpl_id"] = M["moduleimpl_id"]
|
||||
mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod
|
||||
modimpl = ModuleImpl.query.get(E["moduleimpl_id"])
|
||||
ScolarNews.add(
|
||||
typ=ScolarNews.NEWS_NOTE,
|
||||
obj=M["moduleimpl_id"],
|
||||
text='Suppression des notes d\'une évaluation dans <a href="%(url)s">%(titre)s</a>'
|
||||
% mod,
|
||||
url=mod["url"],
|
||||
obj=modimpl.id,
|
||||
text=f"""Suppression des notes d'une évaluation dans
|
||||
<a class="stdlink" href="{status_url}"
|
||||
>{modimpl.module.titre or 'module sans titre'}</a>
|
||||
""",
|
||||
url=status_url,
|
||||
)
|
||||
|
||||
return html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer()
|
||||
@ -555,7 +566,7 @@ def notes_add(
|
||||
oldval = notes_db[etudid]["value"]
|
||||
if type(value) != type(oldval):
|
||||
changed = True
|
||||
elif type(value) == type(1.0) and (
|
||||
elif type(value) == float and (
|
||||
abs(value - oldval) > scu.NOTES_PRECISION
|
||||
):
|
||||
changed = True
|
||||
@ -566,10 +577,10 @@ def notes_add(
|
||||
if do_it:
|
||||
cursor.execute(
|
||||
"""INSERT INTO notes_notes_log
|
||||
(etudid,evaluation_id,value,comment,date,uid)
|
||||
(etudid,evaluation_id,value,comment,date,uid)
|
||||
SELECT etudid, evaluation_id, value, comment, date, uid
|
||||
FROM notes_notes
|
||||
WHERE etudid=%(etudid)s
|
||||
WHERE etudid=%(etudid)s
|
||||
and evaluation_id=%(evaluation_id)s
|
||||
""",
|
||||
{"etudid": etudid, "evaluation_id": evaluation_id},
|
||||
@ -588,7 +599,7 @@ def notes_add(
|
||||
cursor.execute(
|
||||
"""UPDATE notes_notes
|
||||
SET value=%(value)s, comment=%(comment)s, date=%(date)s, uid=%(uid)s
|
||||
WHERE etudid = %(etudid)s
|
||||
WHERE etudid = %(etudid)s
|
||||
and evaluation_id = %(evaluation_id)s
|
||||
""",
|
||||
aa,
|
||||
@ -609,7 +620,7 @@ def notes_add(
|
||||
# garde trace de la suppression dans l'historique:
|
||||
aa["value"] = scu.NOTES_SUPPRESS
|
||||
cursor.execute(
|
||||
"""INSERT INTO notes_notes_log (etudid,evaluation_id,value,comment,date,uid)
|
||||
"""INSERT INTO notes_notes_log (etudid,evaluation_id,value,comment,date,uid)
|
||||
VALUES (%(etudid)s, %(evaluation_id)s, %(value)s, %(comment)s, %(date)s, %(uid)s)
|
||||
""",
|
||||
aa,
|
||||
|
@ -651,7 +651,9 @@ def index_html():
|
||||
</ul>
|
||||
<h3>Référentiels de compétences</h3>
|
||||
<ul>
|
||||
<li><a class="stdlink" href="{url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept)}">Liste des référentiels chargés</a>
|
||||
<li><a class="stdlink" href="{
|
||||
url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept)
|
||||
}">Liste des référentiels chargés</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -349,6 +349,7 @@ def abort_if_false(ctx, param, value):
|
||||
|
||||
@app.cli.command()
|
||||
@click.option(
|
||||
"-y",
|
||||
"--yes",
|
||||
is_flag=True,
|
||||
callback=abort_if_false,
|
||||
|
@ -38,7 +38,7 @@ def test_client():
|
||||
u.add_role(admin_role, TestConfig.DEPT_TEST)
|
||||
db.session.add(u)
|
||||
db.session.commit()
|
||||
# Creation département de Test
|
||||
# Création département de Test
|
||||
d = models.Departement(acronym=TestConfig.DEPT_TEST)
|
||||
db.session.add(d)
|
||||
db.session.commit()
|
||||
|
@ -38,14 +38,28 @@ from app.scodoc import sco_utils as scu
|
||||
from app import log
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
|
||||
from tests.unit.setup import NOTES_T
|
||||
|
||||
random.seed(12345) # tests reproductibles
|
||||
|
||||
|
||||
NOMS_DIR = Config.SCODOC_DIR + "/tools/fakeportal/nomsprenoms"
|
||||
NOMS = [x.strip() for x in open(NOMS_DIR + "/noms.txt").readlines()]
|
||||
PRENOMS_H = [x.strip() for x in open(NOMS_DIR + "/prenoms-h.txt").readlines()]
|
||||
PRENOMS_F = [x.strip() for x in open(NOMS_DIR + "/prenoms-f.txt").readlines()]
|
||||
PRENOMS_X = [x.strip() for x in open(NOMS_DIR + "/prenoms-x.txt").readlines()]
|
||||
NOMS = [
|
||||
x.strip()
|
||||
for x in open(NOMS_DIR + "/noms.txt", encoding=scu.SCO_ENCODING).readlines()
|
||||
]
|
||||
PRENOMS_H = [
|
||||
x.strip()
|
||||
for x in open(NOMS_DIR + "/prenoms-h.txt", encoding=scu.SCO_ENCODING).readlines()
|
||||
]
|
||||
PRENOMS_F = [
|
||||
x.strip()
|
||||
for x in open(NOMS_DIR + "/prenoms-f.txt", encoding=scu.SCO_ENCODING).readlines()
|
||||
]
|
||||
PRENOMS_X = [
|
||||
x.strip()
|
||||
for x in open(NOMS_DIR + "/prenoms-x.txt", encoding=scu.SCO_ENCODING).readlines()
|
||||
]
|
||||
|
||||
|
||||
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
|
||||
@ -297,18 +311,18 @@ class ScoFake(object):
|
||||
@logging_meth
|
||||
def create_note(
|
||||
self,
|
||||
evaluation=None,
|
||||
etud=None,
|
||||
evaluation_id: int = None,
|
||||
etudid: int = None,
|
||||
note=None,
|
||||
comment=None,
|
||||
user=None, # User instance
|
||||
comment: str = None,
|
||||
user: User = None, # User instance
|
||||
):
|
||||
if user is None:
|
||||
user = self.default_user
|
||||
return sco_saisie_notes.notes_add(
|
||||
user,
|
||||
evaluation["evaluation_id"],
|
||||
[(etud["etudid"], note)],
|
||||
evaluation_id,
|
||||
[(etudid, note)],
|
||||
comment=comment,
|
||||
)
|
||||
|
||||
@ -393,24 +407,24 @@ class ScoFake(object):
|
||||
eval_list.append(e)
|
||||
return formsemestre_id, eval_list
|
||||
|
||||
def set_etud_notes_sem(
|
||||
self, sem, eval_list, etuds, notes=None, random_min=0, random_max=20
|
||||
def set_etud_notes_evals(
|
||||
self, eval_list: list[dict], etuds: list[dict], notes=None
|
||||
):
|
||||
"""Met des notes aux étudiants indiqués des evals indiquées.
|
||||
|
||||
Args:
|
||||
sem: dict
|
||||
eval_list: list of dicts
|
||||
etuds: list of dicts
|
||||
notes: liste des notes (float).
|
||||
Si non spécifié, tire au hasard dans `[random_min, random_max]`
|
||||
Si non spécifié, utilise la liste NOTES_T
|
||||
"""
|
||||
set_random = notes is None
|
||||
if notes is None:
|
||||
notes = NOTES_T
|
||||
for e in eval_list:
|
||||
if set_random:
|
||||
notes = [float(random.randint(random_min, random_max)) for _ in etuds]
|
||||
for etud, note in zip(etuds, notes):
|
||||
self.create_note(evaluation=e, etud=etud, note=note)
|
||||
for idx, etud in enumerate(etuds):
|
||||
self.create_note(
|
||||
evaluation_id=e["id"],
|
||||
etudid=etud["id"],
|
||||
note=notes[idx % len(notes)],
|
||||
)
|
||||
|
||||
def set_code_jury(
|
||||
self,
|
||||
|
@ -3,12 +3,16 @@ Quelques fonctions d'initialisation pour tests unitaires
|
||||
"""
|
||||
|
||||
from tests.unit import sco_fake_gen
|
||||
from app import db
|
||||
from app import models
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import sco_codes_parcours
|
||||
|
||||
# Valeurs des notes saisies par les tests:
|
||||
NOTES_T = [
|
||||
float(x) for x in (20, 0, 10, 13 / 7.0, 12.5, 24.0 / 11) + tuple(range(1, 19))
|
||||
]
|
||||
|
||||
|
||||
def build_formation_test(
|
||||
nb_mods=1, parcours=sco_codes_parcours.ParcoursBUT, with_ue_sport=False
|
||||
|
95
tests/unit/test_bulletin.py
Normal file
95
tests/unit/test_bulletin.py
Normal file
@ -0,0 +1,95 @@
|
||||
"""Tests unitaires : bulletins de notes
|
||||
|
||||
Utiliser comme:
|
||||
pytest tests/unit/test_sco_basic.py
|
||||
|
||||
Au besoin, créer un base de test neuve:
|
||||
./tools/create_database.sh SCODOC_TEST
|
||||
|
||||
"""
|
||||
|
||||
from app.models import FormSemestre, Identite
|
||||
|
||||
from config import TestConfig
|
||||
|
||||
import app
|
||||
from app.scodoc import sco_bulletins_json
|
||||
from app.scodoc import sco_preferences
|
||||
from tests.unit import sco_fake_gen
|
||||
from tests.unit import test_sco_basic
|
||||
|
||||
|
||||
DEPT = TestConfig.DEPT_TEST
|
||||
|
||||
|
||||
def test_bulletin(test_client):
|
||||
"""Vérifications sur les bulletins de notes"""
|
||||
G = sco_fake_gen.ScoFake(verbose=False)
|
||||
app.set_sco_dept(DEPT)
|
||||
formsemestre = test_sco_basic.run_sco_basic()
|
||||
modimpl = formsemestre.modimpls.first()
|
||||
evaluation = modimpl.evaluations.first()
|
||||
# S'assure qu'on a bien une formation classique:
|
||||
assert formsemestre.formation.is_apc() is False
|
||||
etud: Identite = formsemestre.etuds.first()
|
||||
assert etud
|
||||
# Ici on a un modimpl avec 9 inscrits, 2 evals ayant toutes leurs notes
|
||||
# Vérification des min/max évaluation sur le bulletin
|
||||
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
|
||||
formsemestre.id,
|
||||
etud.id,
|
||||
force_publishing=True,
|
||||
xml_with_decisions=True,
|
||||
)
|
||||
assert isinstance(bul, dict)
|
||||
assert bul["type"] == "classic"
|
||||
modules_res = bul["ue"][0]["module"]
|
||||
assert len(modules_res) == 1 # 1 seul module complet
|
||||
module_res = modules_res[0]
|
||||
assert modimpl.module.code == module_res["code"]
|
||||
assert len(module_res["evaluation"]) == 2
|
||||
note_eval_1 = module_res["evaluation"][0]
|
||||
assert "note" in note_eval_1
|
||||
assert "min" not in note_eval_1
|
||||
assert not sco_preferences.get_preference("bul_show_minmax_eval")
|
||||
# Change préférence pour avoir min/max évaluation
|
||||
prefs = sco_preferences.get_base_preferences()
|
||||
prefs.set(None, "bul_show_minmax_eval", True)
|
||||
assert sco_preferences.get_preference("bul_show_minmax_eval")
|
||||
# Redemande le bulletin
|
||||
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
|
||||
formsemestre.id,
|
||||
etud.id,
|
||||
force_publishing=True,
|
||||
xml_with_decisions=True,
|
||||
)
|
||||
note_eval_1 = bul["ue"][0]["module"][0]["evaluation"][0]
|
||||
assert "min" in note_eval_1
|
||||
assert "max" in note_eval_1
|
||||
min_eval_1 = float(note_eval_1["min"])
|
||||
max_eval_1 = float(note_eval_1["max"])
|
||||
# la valeur actuelle est 12.34, on s'assure qu'elle n'est pas extrême:
|
||||
assert min_eval_1 > 0
|
||||
assert max_eval_1 < 20
|
||||
|
||||
# Saisie note pour changer min/max:
|
||||
# Met le max à 20:
|
||||
G.create_note(evaluation_id=evaluation.id, etudid=etud.id, note=20.0)
|
||||
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
|
||||
formsemestre.id,
|
||||
etud.id,
|
||||
force_publishing=True,
|
||||
xml_with_decisions=True,
|
||||
)
|
||||
note_eval_1 = bul["ue"][0]["module"][0]["evaluation"][0]
|
||||
assert note_eval_1["max"] == "20.00"
|
||||
# Met le min à zero:
|
||||
G.create_note(evaluation_id=evaluation.id, etudid=etud.id, note=0.0)
|
||||
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
|
||||
formsemestre.id,
|
||||
etud.id,
|
||||
force_publishing=True,
|
||||
xml_with_decisions=True,
|
||||
)
|
||||
note_eval_1 = bul["ue"][0]["module"][0]["evaluation"][0]
|
||||
assert note_eval_1["min"] == "00.00"
|
@ -11,7 +11,6 @@ from flask import g
|
||||
import app
|
||||
from app import db
|
||||
from app.models import Departement, ScoPreference, FormSemestre, formsemestre
|
||||
from app.scodoc import notesdb as ndb
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_preferences
|
||||
from tests.unit import test_sco_basic
|
||||
|
@ -108,10 +108,14 @@ def test_notes_modules(test_client):
|
||||
# --- Notes ordinaires
|
||||
note_1 = 12.0
|
||||
note_2 = 13.0
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etuds[0], note=note_1)
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etuds[0], note=note_2)
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etuds[1], note=note_1 / 2)
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etuds[1], note=note_2 / 3)
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etuds[0]["id"], note=note_1)
|
||||
_, _, _ = G.create_note(evaluation_id=e2["id"], etudid=etuds[0]["id"], note=note_2)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["id"], etudid=etuds[1]["id"], note=note_1 / 2
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e2["id"], etudid=etuds[1]["id"], note=note_2 / 3
|
||||
)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -132,16 +136,16 @@ def test_notes_modules(test_client):
|
||||
)
|
||||
|
||||
# Absence à une évaluation
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=note_2)
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etudid, note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation_id=e2["id"], etudid=etudid, note=note_2)
|
||||
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
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etudid, note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation_id=e2["id"], etudid=etudid, note=None) # abs
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -156,8 +160,10 @@ def test_notes_modules(test_client):
|
||||
)
|
||||
|
||||
# Note excusée EXC <-> scu.NOTES_NEUTRALISE
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=note_1)
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=scu.NOTES_NEUTRALISE) # EXC
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etudid, note=note_1)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e2["id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -171,8 +177,10 @@ def test_notes_modules(test_client):
|
||||
expected_moy_ue=note_1,
|
||||
)
|
||||
# Note en attente ATT <-> scu.NOTES_ATTENTE
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=note_1)
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=scu.NOTES_ATTENTE) # ATT
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etudid, note=note_1)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e2["id"], etudid=etudid, note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -186,8 +194,12 @@ def test_notes_modules(test_client):
|
||||
expected_moy_ue=note_1,
|
||||
)
|
||||
# Neutralisation (EXC) des 2 évals
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=scu.NOTES_NEUTRALISE) # EXC
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=scu.NOTES_NEUTRALISE) # EXC
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e2["id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -201,8 +213,12 @@ def test_notes_modules(test_client):
|
||||
expected_moy_ue=np.nan,
|
||||
)
|
||||
# Attente (ATT) sur les 2 evals
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=scu.NOTES_ATTENTE) # ATT
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=scu.NOTES_ATTENTE) # ATT
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["id"], etudid=etudid, note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e2["id"], etudid=etudid, note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -261,7 +277,7 @@ def test_notes_modules(test_client):
|
||||
{"etudid": etudid, "moduleimpl_id": moduleimpl_id},
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etud, note=12.5)
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etudid, note=12.5)
|
||||
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
mod_stats = nt.get_mod_stats(moduleimpl_id)
|
||||
@ -289,7 +305,7 @@ def test_notes_modules(test_client):
|
||||
description="evaluation mod 2",
|
||||
coefficient=1.0,
|
||||
)
|
||||
_, _, _ = G.create_note(evaluation=e_m2, etud=etud, note=19.5)
|
||||
_, _, _ = G.create_note(evaluation_id=e_m2["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)
|
||||
@ -297,12 +313,16 @@ def test_notes_modules(test_client):
|
||||
# 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(evaluation=e1, etud=etud, note=scu.NOTES_NEUTRALISE) # EXC
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etud, note=scu.NOTES_NEUTRALISE) # EXC
|
||||
_, _, _ = G.create_note(evaluation=e_m2, etud=etud, note=12.5)
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etuds[1], note=11.0)
|
||||
_, _, _ = G.create_note(evaluation=e2, etud=etuds[1], note=11.0)
|
||||
_, _, _ = G.create_note(evaluation=e_m2, etud=etuds[1], note=11.0)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e2["id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
_, _, _ = G.create_note(evaluation_id=e_m2["id"], etudid=etudid, note=12.5)
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etuds[1]["id"], note=11.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e2["id"], etudid=etuds[1]["id"], note=11.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_m2["id"], etudid=etuds[1]["id"], note=11.0)
|
||||
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
@ -366,8 +386,12 @@ def test_notes_modules_att_dem(test_client):
|
||||
coefficient=coef_1,
|
||||
)
|
||||
# Attente (ATT) sur les 2 evals
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etuds[0], note=scu.NOTES_ATTENTE) # ATT
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etuds[1], note=scu.NOTES_ATTENTE) # ATT
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["id"], etudid=etuds[0]["id"], note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["id"], etudid=etuds[1]["id"], note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
# Démission du premier étudiant
|
||||
sco_formsemestre_inscriptions.do_formsemestre_demission(
|
||||
etuds[0]["etudid"],
|
||||
@ -406,7 +430,7 @@ def test_notes_modules_att_dem(test_client):
|
||||
assert note_e1 == scu.NOTES_ATTENTE # XXXX un peu contestable
|
||||
|
||||
# Saisie note ABS pour le deuxième etud
|
||||
_, _, _ = G.create_note(evaluation=e1, etud=etuds[1], note=None) # ABS
|
||||
_, _, _ = G.create_note(evaluation_id=e1["id"], etudid=etuds[1]["id"], note=None)
|
||||
nt = check_nt(
|
||||
etuds[1]["etudid"],
|
||||
sem["formsemestre_id"],
|
||||
|
@ -1,13 +1,11 @@
|
||||
"""Test calculs rattrapages
|
||||
"""
|
||||
|
||||
from flask import g
|
||||
|
||||
import app
|
||||
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.models import FormSemestre, ModuleImpl
|
||||
from app.scodoc import (
|
||||
sco_bulletins,
|
||||
sco_evaluation_db,
|
||||
@ -75,8 +73,8 @@ def test_notes_rattrapage(test_client):
|
||||
evaluation_type=scu.EVALUATION_RATTRAPAGE,
|
||||
)
|
||||
etud = etuds[0]
|
||||
_, _, _ = G.create_note(evaluation=e, etud=etud, note=12.0)
|
||||
_, _, _ = G.create_note(evaluation=e_rat, etud=etud, note=11.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e["id"], etudid=etud["id"], note=12.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["id"], note=11.0)
|
||||
|
||||
# --- Vérifications internes structures ScoDoc
|
||||
formsemestre = FormSemestre.query.get(formsemestre_id)
|
||||
@ -100,21 +98,21 @@ def test_notes_rattrapage(test_client):
|
||||
# Note moyenne: ici le ratrapage est inférieur à la note:
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(12.0)
|
||||
# rattrapage > moyenne:
|
||||
_, _, _ = G.create_note(evaluation=e_rat, etud=etud, note=18.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["id"], note=18.0)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(18.0)
|
||||
# rattrapage vs absences
|
||||
_, _, _ = G.create_note(evaluation=e, etud=etud, note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation=e_rat, etud=etud, note=17.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e["id"], etudid=etud["id"], note=None) # abs
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["id"], note=17.0)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(17.0)
|
||||
# et sans note de rattrapage
|
||||
_, _, _ = G.create_note(evaluation=e, etud=etud, note=10.0) # abs
|
||||
_, _, _ = G.create_note(evaluation=e_rat, etud=etud, note=None)
|
||||
_, _, _ = G.create_note(evaluation_id=e["id"], etudid=etud["id"], note=10.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["id"], note=None)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -156,21 +154,25 @@ def test_notes_rattrapage(test_client):
|
||||
assert len(mod_res.get_evaluations_completes(moduleimpl)) == 2
|
||||
|
||||
# Saisie note session 2:
|
||||
_, _, _ = G.create_note(evaluation=e_session2, etud=etud, note=5.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_session2["id"], etudid=etud["id"], 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)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_session2["id"], etudid=etud["id"], 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)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_session2["id"], etudid=etud["id"], note=None
|
||||
)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
|
@ -11,12 +11,11 @@ Au besoin, créer un base de test neuve:
|
||||
./tools/create_database.sh SCODOC_TEST
|
||||
|
||||
"""
|
||||
import random
|
||||
|
||||
from app.models import FormSemestreInscription, Identite
|
||||
|
||||
from config import TestConfig
|
||||
from tests.unit import sco_fake_gen
|
||||
from tests.unit.setup import NOTES_T
|
||||
|
||||
import app
|
||||
from app import db
|
||||
@ -33,7 +32,6 @@ from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_formsemestre_validation
|
||||
from app.scodoc import sco_cursus_dut
|
||||
from app.scodoc import sco_saisie_notes
|
||||
from app.scodoc import sco_utils as scu
|
||||
|
||||
DEPT = TestConfig.DEPT_TEST
|
||||
|
||||
@ -47,9 +45,10 @@ def test_sco_basic(test_client):
|
||||
run_sco_basic()
|
||||
|
||||
|
||||
def run_sco_basic(verbose=False):
|
||||
def run_sco_basic(verbose=False) -> FormSemestre:
|
||||
"""Scénario de base: création formation, semestre, étudiants, notes,
|
||||
décisions jury
|
||||
Renvoie le formsemestre créé.
|
||||
"""
|
||||
G = sco_fake_gen.ScoFake(verbose=verbose)
|
||||
|
||||
@ -91,11 +90,11 @@ def run_sco_basic(verbose=False):
|
||||
)
|
||||
assert q.count() == 1
|
||||
ins = q.first()
|
||||
assert ins.etape == None
|
||||
assert ins.etape is None
|
||||
assert ins.etat == "I"
|
||||
assert ins.parcour == None
|
||||
assert ins.parcour is None
|
||||
|
||||
# --- Creation évaluation
|
||||
# --- Création évaluation
|
||||
e = G.create_evaluation(
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
jour="01/01/2020",
|
||||
@ -104,10 +103,13 @@ def run_sco_basic(verbose=False):
|
||||
)
|
||||
|
||||
# --- Saisie toutes les notes de l'évaluation
|
||||
for etud in etuds:
|
||||
for idx, etud in enumerate(etuds):
|
||||
nb_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
evaluation=e, etud=etud, note=float(random.randint(0, 20))
|
||||
evaluation_id=e["id"], etudid=etud["id"], note=NOTES_T[idx % len(NOTES_T)]
|
||||
)
|
||||
assert not existing_decisions
|
||||
assert nb_suppress == 0
|
||||
assert nb_changed == 1
|
||||
|
||||
# --- Vérifie que les notes sont prises en compte:
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(formsemestre_id, etud["etudid"])
|
||||
@ -132,13 +134,13 @@ def run_sco_basic(verbose=False):
|
||||
coefficient=1.0,
|
||||
)
|
||||
# Saisie les notes des 5 premiers étudiants:
|
||||
for etud in etuds[:5]:
|
||||
for idx, etud in enumerate(etuds[:5]):
|
||||
nb_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
evaluation=e2, etud=etud, note=float(random.randint(0, 20))
|
||||
evaluation_id=e2["id"], etudid=etud["id"], note=NOTES_T[idx % len(NOTES_T)]
|
||||
)
|
||||
# Cette éval n'est pas complète
|
||||
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
|
||||
assert etat["evalcomplete"] == False
|
||||
assert etat["evalcomplete"] is False
|
||||
# la première éval est toujours complète:
|
||||
etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
|
||||
assert etat["evalcomplete"]
|
||||
@ -147,14 +149,14 @@ def run_sco_basic(verbose=False):
|
||||
e2["publish_incomplete"] = True
|
||||
sco_evaluation_db.do_evaluation_edit(e2)
|
||||
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
|
||||
assert etat["evalcomplete"] == False
|
||||
assert etat["evalcomplete"] is False
|
||||
assert etat["nb_att"] == 0 # il n'y a pas de notes (explicitement) en attente
|
||||
assert etat["evalattente"] # mais l'eval est en attente (prise en compte immédiate)
|
||||
|
||||
# Saisie des notes qui manquent:
|
||||
for etud in etuds[5:]:
|
||||
for idx, etud in enumerate(etuds[5:]):
|
||||
nb_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
evaluation=e2, etud=etud, note=float(random.randint(0, 20))
|
||||
evaluation_id=e2["id"], etudid=etud["id"], note=NOTES_T[idx % len(NOTES_T)]
|
||||
)
|
||||
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
|
||||
assert etat["evalcomplete"]
|
||||
@ -173,7 +175,10 @@ def run_sco_basic(verbose=False):
|
||||
assert f'{etat["nb_inscrits"]} notes changées' in ans
|
||||
etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
|
||||
assert etat["evalcomplete"]
|
||||
# --- Saisie absences
|
||||
|
||||
# -----------------------
|
||||
# --- Saisie absences ---
|
||||
# -----------------------
|
||||
etudid = etuds[0]["etudid"]
|
||||
|
||||
_ = sco_abs_views.doSignaleAbsence(
|
||||
@ -188,8 +193,8 @@ def run_sco_basic(verbose=False):
|
||||
)
|
||||
|
||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
||||
assert nbabs == 6, "incorrect nbabs (%d)" % nbabs
|
||||
assert nbabsjust == 2, "incorrect nbabsjust (%s)" % nbabsjust
|
||||
assert nbabs == 6, f"incorrect nbabs ({nbabs})"
|
||||
assert nbabsjust == 2, f"incorrect nbabsjust ({nbabsjust})"
|
||||
|
||||
# --- Permission saisie notes et décisions de jury, avec ou sans démission ou défaillance
|
||||
# on n'a pas encore saisi de décisions
|
||||
@ -227,7 +232,7 @@ def run_sco_basic(verbose=False):
|
||||
for ue_id in dec_ues:
|
||||
assert dec_ues[ue_id]["code"] in {"ADM", "CMP"}
|
||||
|
||||
# ---- Suppression étudiant, vérification inscription
|
||||
# ---- Suppression d'un étudiant, vérification inscription
|
||||
# (permet de tester les cascades)
|
||||
etud = Identite.query.get(etuds[0]["id"])
|
||||
assert etud is not None
|
||||
@ -239,3 +244,4 @@ def run_sco_basic(verbose=False):
|
||||
etudid=etudid, formsemestre_id=formsemestre_id
|
||||
)
|
||||
assert q.count() == 0
|
||||
return formsemestre
|
||||
|
Loading…
Reference in New Issue
Block a user