forked from ScoDoc/ScoDoc
Import utilisateurs: strip champs
This commit is contained in:
parent
c94fea9f9e
commit
07c2f00277
@ -973,7 +973,7 @@ class FormSemestre(models.ScoDocModel):
|
||||
|
||||
def etudids_actifs(self) -> tuple[list[int], set[int]]:
|
||||
"""Liste les etudids inscrits (incluant DEM et DEF),
|
||||
qui ser al'index des dataframes de notes
|
||||
qui sera l'index des dataframes de notes
|
||||
et donne l'ensemble des inscrits non DEM ni DEF.
|
||||
"""
|
||||
return [inscr.etudid for inscr in self.inscriptions], {
|
||||
|
@ -140,7 +140,7 @@ def read_users_excel_file(datafile, titles=TITLES) -> list[dict]:
|
||||
for line in data[1:]:
|
||||
d = {}
|
||||
for i, field in enumerate(xls_titles):
|
||||
d[field] = line[i]
|
||||
d[field] = (line[i] or "").strip()
|
||||
users.append(d)
|
||||
return users
|
||||
|
||||
|
@ -70,13 +70,21 @@ def moduleimpl_evaluation_menu(evaluation: Evaluation, nbnotes: int = 0) -> str:
|
||||
|
||||
menu_eval = [
|
||||
{
|
||||
"title": "Saisir notes",
|
||||
"title": "Saisir les notes",
|
||||
"endpoint": "notes.saisie_notes",
|
||||
"args": {
|
||||
"evaluation_id": evaluation_id,
|
||||
},
|
||||
"enabled": can_edit_notes_ens,
|
||||
},
|
||||
{
|
||||
"title": "Saisir par fichier tableur",
|
||||
"id": "menu_saisie_tableur",
|
||||
"endpoint": "notes.saisie_notes_tableur",
|
||||
"args": {
|
||||
"evaluation_id": evaluation.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
"title": "Modifier évaluation",
|
||||
"endpoint": "notes.evaluation_edit",
|
||||
|
@ -29,12 +29,15 @@
|
||||
|
||||
Formulaire revu en juillet 2016
|
||||
"""
|
||||
import html
|
||||
import time
|
||||
import psycopg2
|
||||
|
||||
|
||||
import flask
|
||||
from flask import g, url_for, request
|
||||
from flask_login import current_user
|
||||
from flask_sqlalchemy.query import Query
|
||||
import psycopg2
|
||||
|
||||
from app import db, log
|
||||
from app.auth.models import User
|
||||
@ -75,8 +78,6 @@ import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import json_error
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
|
||||
from flask_sqlalchemy.query import Query
|
||||
|
||||
|
||||
def convert_note_from_string(
|
||||
note: str,
|
||||
@ -115,7 +116,7 @@ def convert_note_from_string(
|
||||
return note_value, invalid
|
||||
|
||||
|
||||
def _displayNote(val):
|
||||
def _display_note(val):
|
||||
"""Convert note from DB to viewable string.
|
||||
Utilisé seulement pour I/O vers formulaires (sans perte de precision)
|
||||
(Utiliser fmt_note pour les affichages)
|
||||
@ -272,7 +273,7 @@ def do_evaluation_upload_xls():
|
||||
diag.append("Notes invalides pour: " + ", ".join(etudsnames))
|
||||
raise InvalidNoteValue()
|
||||
else:
|
||||
etudids_changed, nb_suppress, etudids_with_decisions = notes_add(
|
||||
etudids_changed, nb_suppress, etudids_with_decisions, messages = notes_add(
|
||||
current_user, evaluation_id, valid_notes, comment
|
||||
)
|
||||
# news
|
||||
@ -292,9 +293,19 @@ def do_evaluation_upload_xls():
|
||||
max_frequency=30 * 60, # 30 minutes
|
||||
)
|
||||
|
||||
msg = f"""<p>{len(etudids_changed)} notes changées ({len(withoutnotes)} sans notes, {
|
||||
len(absents)} absents, {nb_suppress} note supprimées)
|
||||
msg = f"""<p>
|
||||
{len(etudids_changed)} notes changées ({len(withoutnotes)} sans notes,
|
||||
{len(absents)} absents, {nb_suppress} note supprimées)
|
||||
</p>"""
|
||||
if messages:
|
||||
msg += f"""<div class="warning">Attention :
|
||||
<ul>
|
||||
<li>{
|
||||
'</li><li>'.join(messages)
|
||||
}
|
||||
</li>
|
||||
</ul>
|
||||
</div>"""
|
||||
if etudids_with_decisions:
|
||||
msg += """<p class="warning">Important: il y avait déjà des décisions de jury
|
||||
enregistrées, qui sont peut-être à revoir suite à cette modification !</p>
|
||||
@ -322,7 +333,7 @@ def do_evaluation_set_etud_note(evaluation: Evaluation, etud: Identite, value) -
|
||||
# Convert and check value
|
||||
L, invalids, _, _, _ = _check_notes([(etud.id, value)], evaluation)
|
||||
if len(invalids) == 0:
|
||||
etudids_changed, _, _ = notes_add(
|
||||
etudids_changed, _, _, _ = notes_add(
|
||||
current_user, evaluation.id, L, "Initialisation notes"
|
||||
)
|
||||
if len(etudids_changed) == 1:
|
||||
@ -398,7 +409,9 @@ def do_evaluation_set_missing(
|
||||
)
|
||||
# ok
|
||||
comment = "Initialisation notes manquantes"
|
||||
etudids_changed, _, _ = notes_add(current_user, evaluation_id, valid_notes, comment)
|
||||
etudids_changed, _, _, _ = notes_add(
|
||||
current_user, evaluation_id, valid_notes, comment
|
||||
)
|
||||
# news
|
||||
url = url_for(
|
||||
"notes.moduleimpl_status",
|
||||
@ -456,7 +469,7 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
|
||||
)
|
||||
|
||||
if not dialog_confirmed:
|
||||
etudids_changed, nb_suppress, existing_decisions = notes_add(
|
||||
etudids_changed, nb_suppress, existing_decisions, _ = notes_add(
|
||||
current_user, evaluation_id, notes, do_it=False, check_inscription=False
|
||||
)
|
||||
msg = f"""<p>Confirmer la suppression des {nb_suppress} notes ?
|
||||
@ -477,7 +490,7 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
|
||||
)
|
||||
|
||||
# modif
|
||||
etudids_changed, nb_suppress, existing_decisions = notes_add(
|
||||
etudids_changed, nb_suppress, existing_decisions, _ = notes_add(
|
||||
current_user,
|
||||
evaluation_id,
|
||||
notes,
|
||||
@ -519,7 +532,7 @@ def notes_add(
|
||||
comment=None,
|
||||
do_it=True,
|
||||
check_inscription=True,
|
||||
) -> tuple[list[int], int, list[int]]:
|
||||
) -> tuple[list[int], int, list[int], list[str]]:
|
||||
"""
|
||||
Insert or update notes
|
||||
notes is a list of tuples (etudid,value)
|
||||
@ -528,30 +541,48 @@ def notes_add(
|
||||
Nota:
|
||||
- si la note existe deja avec valeur distincte, ajoute une entree au log (notes_notes_log)
|
||||
|
||||
Return: tuple (etudids_changed, nb_suppress, etudids_with_decision)
|
||||
Return: tuple (etudids_changed, nb_suppress, etudids_with_decision, messages)
|
||||
|
||||
messages = list de messages d'avertissement/information pour l'utilisateur
|
||||
"""
|
||||
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
now = psycopg2.Timestamp(*time.localtime()[:6])
|
||||
|
||||
# Vérifie inscription et valeur note
|
||||
inscrits = {
|
||||
messages = []
|
||||
# Vérifie inscription au module (même DEM/DEF)
|
||||
etudids_inscrits_mod = {
|
||||
x[0]
|
||||
for x in sco_groups.do_evaluation_listeetuds_groups(
|
||||
evaluation_id, getallstudents=True, include_demdef=True
|
||||
)
|
||||
}
|
||||
# Les étudiants inscrits au semestre ni DEM ni DEF
|
||||
_, etudids_actifs = evaluation.moduleimpl.formsemestre.etudids_actifs()
|
||||
# Les étudiants inscrits au semestre et ceux "actifs" (ni DEM ni DEF)
|
||||
etudids_inscrits_sem, etudids_actifs = (
|
||||
evaluation.moduleimpl.formsemestre.etudids_actifs()
|
||||
)
|
||||
for etudid, value in notes:
|
||||
if check_inscription and (
|
||||
(etudid not in inscrits) or (etudid not in etudids_actifs)
|
||||
):
|
||||
log(f"notes_add: {etudid} non inscrit ou DEM/DEF: aborting")
|
||||
raise NoteProcessError(f"étudiant {etudid} non inscrit dans ce module")
|
||||
|
||||
if check_inscription:
|
||||
msg_err, msg_warn = "", ""
|
||||
if etudid not in etudids_inscrits_sem:
|
||||
msg_err = "non inscrit au semestre"
|
||||
elif etudid not in etudids_inscrits_mod:
|
||||
msg_err = "non inscrit au module"
|
||||
elif etudid not in etudids_actifs:
|
||||
# DEM ou DEF
|
||||
msg_warn = "démissionnaire ou défaillant (note enregistrée)"
|
||||
if msg_err or msg_warn:
|
||||
etud = Identite.query.get(etudid) if isinstance(etudid, int) else None
|
||||
msg = f"étudiant {etud.nomprenom if etud else etudid} {msg_err or msg_warn}"
|
||||
if msg_err:
|
||||
log(f"notes_add: {etudid} non inscrit ou DEM/DEF: aborting")
|
||||
raise NoteProcessError(msg)
|
||||
if msg_warn:
|
||||
messages.append(msg)
|
||||
if (value is not None) and not isinstance(value, float):
|
||||
log(f"notes_add: {etudid} valeur de note invalide ({value}): aborting")
|
||||
etud = Identite.query.get(etudid) if isinstance(etudid, int) else None
|
||||
raise NoteProcessError(
|
||||
f"etudiant {etudid}: valeur de note invalide ({value})"
|
||||
f"etudiant {etud.nomprenom if etud else etudid}: valeur de note invalide ({value})"
|
||||
)
|
||||
# Recherche notes existantes
|
||||
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
|
||||
@ -566,102 +597,20 @@ def notes_add(
|
||||
etudids_with_decision = []
|
||||
try:
|
||||
for etudid, value in notes:
|
||||
changed = False
|
||||
if etudid not in notes_db:
|
||||
# nouvelle note
|
||||
if value != scu.NOTES_SUPPRESS:
|
||||
if do_it:
|
||||
args = {
|
||||
"etudid": etudid,
|
||||
"evaluation_id": evaluation_id,
|
||||
"value": value,
|
||||
"comment": comment,
|
||||
"uid": user.id,
|
||||
"date": now,
|
||||
}
|
||||
ndb.quote_dict(args)
|
||||
# Note: le conflit ci-dessous peut arriver si un autre thread
|
||||
# a modifié la base après qu'on ait lu notes_db
|
||||
cursor.execute(
|
||||
"""INSERT INTO notes_notes
|
||||
(etudid, evaluation_id, value, comment, date, uid)
|
||||
VALUES
|
||||
(%(etudid)s,%(evaluation_id)s,%(value)s,
|
||||
%(comment)s,%(date)s,%(uid)s)
|
||||
ON CONFLICT ON CONSTRAINT notes_notes_etudid_evaluation_id_key
|
||||
DO UPDATE SET etudid=%(etudid)s, evaluation_id=%(evaluation_id)s,
|
||||
value=%(value)s, comment=%(comment)s, date=%(date)s, uid=%(uid)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
changed = True
|
||||
else:
|
||||
# il y a deja une note
|
||||
oldval = notes_db[etudid]["value"]
|
||||
if type(value) != type(oldval):
|
||||
changed = True
|
||||
elif isinstance(value, float) and (
|
||||
abs(value - oldval) > scu.NOTES_PRECISION
|
||||
):
|
||||
changed = True
|
||||
elif value != oldval:
|
||||
changed = True
|
||||
if changed:
|
||||
# recopie l'ancienne note dans notes_notes_log, puis update
|
||||
if do_it:
|
||||
cursor.execute(
|
||||
"""INSERT INTO notes_notes_log
|
||||
(etudid,evaluation_id,value,comment,date,uid)
|
||||
SELECT etudid, evaluation_id, value, comment, date, uid
|
||||
FROM notes_notes
|
||||
WHERE etudid=%(etudid)s
|
||||
and evaluation_id=%(evaluation_id)s
|
||||
""",
|
||||
{"etudid": etudid, "evaluation_id": evaluation_id},
|
||||
)
|
||||
args = {
|
||||
"etudid": etudid,
|
||||
"evaluation_id": evaluation_id,
|
||||
"value": value,
|
||||
"date": now,
|
||||
"comment": comment,
|
||||
"uid": user.id,
|
||||
}
|
||||
ndb.quote_dict(args)
|
||||
if value != scu.NOTES_SUPPRESS:
|
||||
if do_it:
|
||||
cursor.execute(
|
||||
"""UPDATE notes_notes
|
||||
SET value=%(value)s, comment=%(comment)s, date=%(date)s, uid=%(uid)s
|
||||
WHERE etudid = %(etudid)s
|
||||
and evaluation_id = %(evaluation_id)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
else: # suppression ancienne note
|
||||
if do_it:
|
||||
log(
|
||||
f"""notes_add, suppress, evaluation_id={evaluation_id}, etudid={
|
||||
etudid}, oldval={oldval}"""
|
||||
)
|
||||
cursor.execute(
|
||||
"""DELETE FROM notes_notes
|
||||
WHERE etudid = %(etudid)s
|
||||
AND evaluation_id = %(evaluation_id)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
# garde trace de la suppression dans l'historique:
|
||||
args["value"] = scu.NOTES_SUPPRESS
|
||||
cursor.execute(
|
||||
"""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)
|
||||
""",
|
||||
args,
|
||||
)
|
||||
nb_suppress += 1
|
||||
changed, suppressed = _record_note(
|
||||
cursor,
|
||||
notes_db,
|
||||
etudid,
|
||||
evaluation_id,
|
||||
value,
|
||||
comment=comment,
|
||||
user=user,
|
||||
date=now,
|
||||
do_it=do_it,
|
||||
)
|
||||
if suppressed:
|
||||
nb_suppress += 1
|
||||
|
||||
if changed:
|
||||
etudids_changed.append(etudid)
|
||||
if res.etud_has_decision(etudid, include_rcues=False):
|
||||
@ -678,7 +627,108 @@ def notes_add(
|
||||
cnx.commit()
|
||||
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre.id)
|
||||
sco_cache.EvaluationCache.delete(evaluation_id)
|
||||
return etudids_changed, nb_suppress, etudids_with_decision
|
||||
return etudids_changed, nb_suppress, etudids_with_decision, messages
|
||||
|
||||
|
||||
def _record_note(
|
||||
cursor,
|
||||
notes_db,
|
||||
etudid: int,
|
||||
evaluation_id: int,
|
||||
value: float,
|
||||
comment: str = "",
|
||||
user: User = None,
|
||||
date=None,
|
||||
do_it=False,
|
||||
):
|
||||
"Enregistrement de la note en base"
|
||||
changed = False
|
||||
suppressed = False
|
||||
args = {
|
||||
"etudid": etudid,
|
||||
"evaluation_id": evaluation_id,
|
||||
"value": value,
|
||||
# convention scodoc7 quote comment:
|
||||
"comment": (html.escape(comment) if isinstance(comment, str) else comment),
|
||||
"uid": user.id,
|
||||
"date": date,
|
||||
}
|
||||
if etudid not in notes_db:
|
||||
# nouvelle note
|
||||
if value != scu.NOTES_SUPPRESS:
|
||||
if do_it:
|
||||
# Note: le conflit ci-dessous peut arriver si un autre thread
|
||||
# a modifié la base après qu'on ait lu notes_db
|
||||
cursor.execute(
|
||||
"""INSERT INTO notes_notes
|
||||
(etudid, evaluation_id, value, comment, date, uid)
|
||||
VALUES
|
||||
(%(etudid)s,%(evaluation_id)s,%(value)s,
|
||||
%(comment)s,%(date)s,%(uid)s)
|
||||
ON CONFLICT ON CONSTRAINT notes_notes_etudid_evaluation_id_key
|
||||
DO UPDATE SET etudid=%(etudid)s, evaluation_id=%(evaluation_id)s,
|
||||
value=%(value)s, comment=%(comment)s, date=%(date)s, uid=%(uid)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
changed = True
|
||||
else:
|
||||
# il y a deja une note
|
||||
oldval = notes_db[etudid]["value"]
|
||||
if type(value) != type(oldval):
|
||||
changed = True
|
||||
elif isinstance(value, float) and (abs(value - oldval) > scu.NOTES_PRECISION):
|
||||
changed = True
|
||||
elif value != oldval:
|
||||
changed = True
|
||||
if changed:
|
||||
# recopie l'ancienne note dans notes_notes_log, puis update
|
||||
if do_it:
|
||||
cursor.execute(
|
||||
"""INSERT INTO notes_notes_log
|
||||
(etudid,evaluation_id,value,comment,date,uid)
|
||||
SELECT etudid, evaluation_id, value, comment, date, uid
|
||||
FROM notes_notes
|
||||
WHERE etudid=%(etudid)s
|
||||
and evaluation_id=%(evaluation_id)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
if value != scu.NOTES_SUPPRESS:
|
||||
if do_it:
|
||||
cursor.execute(
|
||||
"""UPDATE notes_notes
|
||||
SET value=%(value)s, comment=%(comment)s, date=%(date)s, uid=%(uid)s
|
||||
WHERE etudid = %(etudid)s
|
||||
and evaluation_id = %(evaluation_id)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
else: # suppression ancienne note
|
||||
if do_it:
|
||||
log(
|
||||
f"""notes_add, suppress, evaluation_id={evaluation_id}, etudid={
|
||||
etudid}, oldval={oldval}"""
|
||||
)
|
||||
cursor.execute(
|
||||
"""DELETE FROM notes_notes
|
||||
WHERE etudid = %(etudid)s
|
||||
AND evaluation_id = %(evaluation_id)s
|
||||
""",
|
||||
args,
|
||||
)
|
||||
# garde trace de la suppression dans l'historique:
|
||||
args["value"] = scu.NOTES_SUPPRESS
|
||||
cursor.execute(
|
||||
"""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)
|
||||
""",
|
||||
args,
|
||||
)
|
||||
suppressed = True
|
||||
return changed, suppressed
|
||||
|
||||
|
||||
def saisie_notes_tableur(evaluation_id, group_ids=()):
|
||||
@ -703,7 +753,7 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
|
||||
)
|
||||
|
||||
page_title = "Saisie des notes" + (
|
||||
f"""de {evaluation.description}""" if evaluation.description else ""
|
||||
f""" de {evaluation.description}""" if evaluation.description else ""
|
||||
)
|
||||
|
||||
# Informations sur les groupes à afficher:
|
||||
@ -797,9 +847,13 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
|
||||
}">
|
||||
Revenir au tableau de bord du module</a>
|
||||
|
||||
<a class="stdlink" href="{url_for("notes.saisie_notes_tableur",
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">Charger un autre fichier de notes</a>
|
||||
|
||||
<a class="stdlink" href="{url_for("notes.saisie_notes",
|
||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||
}">Charger d'autres notes dans cette évaluation</a>
|
||||
}">Formulaire de saisie des notes</a>
|
||||
</p>"""
|
||||
)
|
||||
else:
|
||||
@ -1015,7 +1069,7 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
||||
"Autres opérations",
|
||||
[
|
||||
{
|
||||
"title": "Saisie par fichier tableur",
|
||||
"title": "Saisir par fichier tableur",
|
||||
"id": "menu_saisie_tableur",
|
||||
"endpoint": "notes.saisie_notes_tableur",
|
||||
"args": {
|
||||
@ -1126,7 +1180,7 @@ def _get_sorted_etuds(evaluation: Evaluation, etudids: list, formsemestre_id: in
|
||||
|
||||
# Note actuelle de l'étudiant:
|
||||
if etudid in notes_db:
|
||||
e["val"] = _displayNote(notes_db[etudid]["value"])
|
||||
e["val"] = _display_note(notes_db[etudid]["value"])
|
||||
comment = notes_db[etudid]["comment"]
|
||||
if comment is None:
|
||||
comment = ""
|
||||
@ -1368,7 +1422,7 @@ def save_notes(
|
||||
#
|
||||
valid_notes, _, _, _, _ = _check_notes(notes, evaluation)
|
||||
if valid_notes:
|
||||
etudids_changed, _, etudids_with_decision = notes_add(
|
||||
etudids_changed, _, etudids_with_decision, messages = notes_add(
|
||||
current_user, evaluation.id, valid_notes, comment=comment, do_it=True
|
||||
)
|
||||
ScolarNews.add(
|
||||
@ -1386,12 +1440,14 @@ def save_notes(
|
||||
etudid: get_note_history_menu(evaluation.id, etudid)
|
||||
for etudid in etudids_changed
|
||||
},
|
||||
"messages": messages,
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"etudids_changed": [],
|
||||
"etudids_with_decision": [],
|
||||
"history_menu": [],
|
||||
"messages": [],
|
||||
}
|
||||
|
||||
return result
|
||||
@ -1420,7 +1476,7 @@ def get_note_history_menu(evaluation_id: int, etudid: int) -> str:
|
||||
first = True
|
||||
for i in history:
|
||||
jt = i["date"].strftime("le %d/%m/%Y à %H:%M") + " (%s)" % i["user_name"]
|
||||
dispnote = _displayNote(i["value"])
|
||||
dispnote = _display_note(i["value"])
|
||||
if first:
|
||||
nv = "" # ne repete pas la valeur de la note courante
|
||||
else:
|
||||
|
@ -180,7 +180,7 @@ def external_ue_inscrit_et_note(
|
||||
description="note externe",
|
||||
)
|
||||
# Saisie des notes
|
||||
_, _, _ = sco_saisie_notes.notes_add(
|
||||
_, _, _, _ = sco_saisie_notes.notes_add(
|
||||
current_user,
|
||||
evaluation.id,
|
||||
list(notes_etuds.items()),
|
||||
|
@ -35,7 +35,7 @@ from flask import url_for, g, request
|
||||
from flask_login import current_user
|
||||
|
||||
|
||||
from app import db, Departement
|
||||
from app import Departement
|
||||
|
||||
from app.auth.models import Permission, Role, User, UserRole
|
||||
from app.models import ScoDocSiteConfig, USERNAME_STR_LEN
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.6.975"
|
||||
SCOVERSION = "9.6.976"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
Vérif moyennes de modules des bulletins
|
||||
et aussi moyennes modules et UE internes (via nt)
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import numpy as np
|
||||
from flask import g
|
||||
@ -107,16 +108,16 @@ def test_notes_modules(test_client):
|
||||
# --- Notes ordinaires
|
||||
note_1 = 12.0
|
||||
note_2 = 13.0
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etuds[0]["etudid"], note=note_1
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etuds[0]["etudid"], note=note_2
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etuds[1]["etudid"], note=note_1 / 2
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etuds[1]["etudid"], note=note_2 / 3
|
||||
)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -139,22 +140,20 @@ def test_notes_modules(test_client):
|
||||
)
|
||||
|
||||
# Absence à une évaluation
|
||||
_, _, _ = G.create_note(
|
||||
_ = 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
|
||||
)
|
||||
_ = G.create_note(evaluation_id=e2["evaluation_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(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etudid, note=None
|
||||
) # abs
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etudid, note=None
|
||||
) # abs
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -171,10 +170,8 @@ def test_notes_modules(test_client):
|
||||
)
|
||||
|
||||
# Note excusée EXC <-> scu.NOTES_NEUTRALISE
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etudid, note=note_1
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(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
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -190,10 +187,8 @@ def test_notes_modules(test_client):
|
||||
expected_moy_ue=note_1,
|
||||
)
|
||||
# Note en attente ATT <-> scu.NOTES_ATTENTE
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etudid, note=note_1
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(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
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -209,10 +204,10 @@ def test_notes_modules(test_client):
|
||||
expected_moy_ue=note_1,
|
||||
)
|
||||
# Neutralisation (EXC) des 2 évals
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -228,10 +223,10 @@ def test_notes_modules(test_client):
|
||||
expected_moy_ue=np.nan,
|
||||
)
|
||||
# Attente (ATT) sur les 2 evals
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etudid, note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_ATTENTE
|
||||
) # ATT
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -290,7 +285,7 @@ def test_notes_modules(test_client):
|
||||
{"etudid": etudid, "moduleimpl_id": moduleimpl_id},
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
_, _, _ = G.create_note(evaluation_id=e1["evaluation_id"], etudid=etudid, note=12.5)
|
||||
_ = G.create_note(evaluation_id=e1["evaluation_id"], etudid=etudid, note=12.5)
|
||||
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
mod_stats = nt.get_mod_stats(moduleimpl_id)
|
||||
@ -318,9 +313,7 @@ def test_notes_modules(test_client):
|
||||
description="evaluation mod 2",
|
||||
coefficient=1.0,
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_m2["evaluation_id"], etudid=etudid, note=19.5
|
||||
)
|
||||
_ = 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)
|
||||
@ -328,22 +321,20 @@ 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(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etudid, note=scu.NOTES_NEUTRALISE
|
||||
) # EXC
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_m2["evaluation_id"], etudid=etudid, note=12.5
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(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
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e2["evaluation_id"], etudid=etuds[1]["etudid"], note=11.0
|
||||
)
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e_m2["evaluation_id"], etudid=etuds[1]["etudid"], note=11.0
|
||||
)
|
||||
|
||||
@ -407,12 +398,12 @@ def test_notes_modules_att_dem(test_client):
|
||||
coefficient=coef_1,
|
||||
)
|
||||
# Attente (ATT) sur les 2 evals
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"],
|
||||
etudid=etuds[0]["etudid"],
|
||||
note=scu.NOTES_ATTENTE,
|
||||
) # ATT
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"],
|
||||
etudid=etuds[1]["etudid"],
|
||||
note=scu.NOTES_ATTENTE,
|
||||
@ -455,7 +446,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(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e1["evaluation_id"], etudid=etuds[1]["etudid"], note=None
|
||||
)
|
||||
nt = check_nt(
|
||||
|
@ -72,8 +72,8 @@ def test_notes_rattrapage(test_client):
|
||||
evaluation_type=Evaluation.EVALUATION_RATTRAPAGE,
|
||||
)
|
||||
etud = etuds[0]
|
||||
_, _, _ = G.create_note(evaluation_id=e["id"], etudid=etud["etudid"], note=12.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], note=11.0)
|
||||
_ = G.create_note(evaluation_id=e["id"], etudid=etud["etudid"], note=12.0)
|
||||
_ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], note=11.0)
|
||||
|
||||
# --- Vérifications internes structures ScoDoc
|
||||
formsemestre = db.session.get(FormSemestre, formsemestre_id)
|
||||
@ -98,23 +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_id=e_rat["id"], etudid=etud["etudid"], note=18.0)
|
||||
_ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], 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_id=e["id"], etudid=etud["etudid"], note=None
|
||||
) # abs
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], note=17.0)
|
||||
_ = G.create_note(evaluation_id=e["id"], etudid=etud["etudid"], note=None) # abs
|
||||
_ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], 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_id=e["id"], etudid=etud["etudid"], note=10.0)
|
||||
_, _, _ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], note=None)
|
||||
_ = G.create_note(evaluation_id=e["id"], etudid=etud["etudid"], note=10.0)
|
||||
_ = G.create_note(evaluation_id=e_rat["id"], etudid=etud["etudid"], note=None)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -159,18 +157,14 @@ def test_notes_rattrapage(test_client):
|
||||
assert len(mod_res.get_evaluations_completes(moduleimpl)) == 2
|
||||
|
||||
# Saisie note session 2:
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_session2["id"], etudid=etud["etudid"], note=5.0
|
||||
)
|
||||
_ = G.create_note(evaluation_id=e_session2["id"], etudid=etud["etudid"], 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_id=e_session2["id"], etudid=etud["etudid"], note=20.0
|
||||
)
|
||||
_ = G.create_note(evaluation_id=e_session2["id"], etudid=etud["etudid"], note=20.0)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
@ -178,16 +172,14 @@ def test_notes_rattrapage(test_client):
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(20.0)
|
||||
|
||||
# Met la note session2 à ABS (None)
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_session2["id"], etudid=etud["etudid"], note=None
|
||||
)
|
||||
_ = G.create_note(evaluation_id=e_session2["id"], etudid=etud["etudid"], note=None)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
# Note moyenne: zéro car ABS
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(0.0)
|
||||
# Supprime note session 2
|
||||
_, _, _ = G.create_note(
|
||||
_ = G.create_note(
|
||||
evaluation_id=e_session2["id"], etudid=etud["etudid"], note=scu.NOTES_SUPPRESS
|
||||
)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
@ -216,18 +208,14 @@ def test_notes_rattrapage(test_client):
|
||||
# Note moyenne sans bonus
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(10.0)
|
||||
# Saisie note bonus
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_bonus["id"], etudid=etud["etudid"], note=1.0
|
||||
)
|
||||
_ = G.create_note(evaluation_id=e_bonus["id"], etudid=etud["etudid"], note=1.0)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
# Note moyenne sans bonus
|
||||
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(11.0)
|
||||
# Négatif, avec clip à zéro
|
||||
_, _, _ = G.create_note(
|
||||
evaluation_id=e_bonus["id"], etudid=etud["etudid"], note=-20.0
|
||||
)
|
||||
_ = G.create_note(evaluation_id=e_bonus["id"], etudid=etud["etudid"], note=-20.0)
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(
|
||||
sem["formsemestre_id"], etud["etudid"]
|
||||
)
|
||||
|
@ -105,7 +105,7 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
|
||||
# --- Saisie toutes les notes de l'évaluation
|
||||
for idx, etud in enumerate(etuds):
|
||||
etudids_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
etudids_changed, nb_suppress, existing_decisions, messages = G.create_note(
|
||||
evaluation_id=e1.id,
|
||||
etudid=etud["etudid"],
|
||||
note=NOTES_T[idx % len(NOTES_T)],
|
||||
@ -113,6 +113,7 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
assert not existing_decisions
|
||||
assert nb_suppress == 0
|
||||
assert len(etudids_changed) == 1
|
||||
assert messages == []
|
||||
|
||||
# --- Vérifie que les notes sont prises en compte:
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(formsemestre_id, etud["etudid"])
|
||||
@ -139,11 +140,12 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
db.session.commit()
|
||||
# Saisie les notes des 5 premiers étudiants:
|
||||
for idx, etud in enumerate(etuds[:5]):
|
||||
etudids_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
etudids_changed, nb_suppress, existing_decisions, messages = G.create_note(
|
||||
evaluation_id=e2.id,
|
||||
etudid=etud["etudid"],
|
||||
note=NOTES_T[idx % len(NOTES_T)],
|
||||
)
|
||||
assert messages == []
|
||||
# Cette éval n'est pas complète
|
||||
etat = sco_evaluations.do_evaluation_etat(e2.id)
|
||||
assert etat["evalcomplete"] is False
|
||||
@ -162,11 +164,12 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
|
||||
# Saisie des notes qui manquent:
|
||||
for idx, etud in enumerate(etuds[5:]):
|
||||
etudids_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
etudids_changed, nb_suppress, existing_decisions, messages = G.create_note(
|
||||
evaluation_id=e2.id,
|
||||
etudid=etud["etudid"],
|
||||
note=NOTES_T[idx % len(NOTES_T)],
|
||||
)
|
||||
assert messages == []
|
||||
etat = sco_evaluations.do_evaluation_etat(e2.id)
|
||||
assert etat["evalcomplete"]
|
||||
assert etat["nb_att"] == 0
|
||||
|
Loading…
Reference in New Issue
Block a user