forked from ScoDoc/ScoDoc
Nettoyage code + exception save note
This commit is contained in:
parent
e9113d0932
commit
af1e46ba82
@ -306,12 +306,12 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
|||||||
|
|
||||||
return ues_ids
|
return ues_ids
|
||||||
|
|
||||||
def etud_has_decision(self, etudid):
|
def etud_has_decision(self, etudid) -> bool:
|
||||||
"""True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre.
|
"""True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre.
|
||||||
prend aussi en compte les autorisations de passage.
|
prend aussi en compte les autorisations de passage.
|
||||||
Sous-classée en BUT pour les RCUEs et années.
|
Sous-classée en BUT pour les RCUEs et années.
|
||||||
"""
|
"""
|
||||||
return (
|
return bool(
|
||||||
super().etud_has_decision(etudid)
|
super().etud_has_decision(etudid)
|
||||||
or ApcValidationAnnee.query.filter_by(
|
or ApcValidationAnnee.query.filter_by(
|
||||||
formsemestre_id=self.formsemestre.id, etudid=etudid
|
formsemestre_id=self.formsemestre.id, etudid=etudid
|
||||||
|
@ -283,12 +283,12 @@ class NotesTableCompat(ResultatsSemestre):
|
|||||||
]
|
]
|
||||||
return etudids
|
return etudids
|
||||||
|
|
||||||
def etud_has_decision(self, etudid):
|
def etud_has_decision(self, etudid) -> bool:
|
||||||
"""True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre.
|
"""True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre.
|
||||||
prend aussi en compte les autorisations de passage.
|
prend aussi en compte les autorisations de passage.
|
||||||
Sous-classée en BUT pour les RCUEs et années.
|
Sous-classée en BUT pour les RCUEs et années.
|
||||||
"""
|
"""
|
||||||
return (
|
return bool(
|
||||||
self.get_etud_decisions_ue(etudid)
|
self.get_etud_decisions_ue(etudid)
|
||||||
or self.get_etud_decision_sem(etudid)
|
or self.get_etud_decision_sem(etudid)
|
||||||
or ScolarAutorisationInscription.query.filter_by(
|
or ScolarAutorisationInscription.query.filter_by(
|
||||||
|
@ -145,6 +145,18 @@ class Evaluation(db.Model):
|
|||||||
db.session.add(copy)
|
db.session.add(copy)
|
||||||
return copy
|
return copy
|
||||||
|
|
||||||
|
def is_matin(self) -> bool:
|
||||||
|
"Evaluation ayant lieu le matin (faux si pas de date)"
|
||||||
|
heure_debut_dt = self.heure_debut or datetime.time(8, 00)
|
||||||
|
# 8:00 au cas ou pas d'heure (note externe?)
|
||||||
|
return bool(self.jour) and heure_debut_dt < datetime.time(12, 00)
|
||||||
|
|
||||||
|
def is_apresmidi(self) -> bool:
|
||||||
|
"Evaluation ayant lieu l'après midi (faux si pas de date)"
|
||||||
|
heure_debut_dt = self.heure_debut or datetime.time(8, 00)
|
||||||
|
# 8:00 au cas ou pas d'heure (note externe?)
|
||||||
|
return bool(self.jour) and heure_debut_dt >= datetime.time(12, 00)
|
||||||
|
|
||||||
def set_default_poids(self) -> bool:
|
def set_default_poids(self) -> bool:
|
||||||
"""Initialize les poids bvers les UE à leurs valeurs par défaut
|
"""Initialize les poids bvers les UE à leurs valeurs par défaut
|
||||||
C'est à dire à 1 si le coef. module/UE est non nul, 0 sinon.
|
C'est à dire à 1 si le coef. module/UE est non nul, 0 sinon.
|
||||||
|
@ -255,9 +255,8 @@ def do_evaluation_get_all_notes(
|
|||||||
"""Toutes les notes pour une evaluation: { etudid : { 'value' : value, 'date' : date ... }}
|
"""Toutes les notes pour une evaluation: { etudid : { 'value' : value, 'date' : date ... }}
|
||||||
Attention: inclut aussi les notes des étudiants qui ne sont plus inscrits au module.
|
Attention: inclut aussi les notes des étudiants qui ne sont plus inscrits au module.
|
||||||
"""
|
"""
|
||||||
do_cache = (
|
# pas de cache pour (rares) appels via undo_notes ou specifiant un enseignant
|
||||||
filter_suppressed and table == "notes_notes" and (by_uid is None)
|
do_cache = filter_suppressed and table == "notes_notes" and (by_uid is None)
|
||||||
) # pas de cache pour (rares) appels via undo_notes ou specifiant un enseignant
|
|
||||||
if do_cache:
|
if do_cache:
|
||||||
r = sco_cache.EvaluationCache.get(evaluation_id)
|
r = sco_cache.EvaluationCache.get(evaluation_id)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
|
@ -433,7 +433,7 @@ def excel_simple_table(
|
|||||||
return ws.generate()
|
return ws.generate()
|
||||||
|
|
||||||
|
|
||||||
def excel_feuille_saisie(e, titreannee, description, lines):
|
def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, lines):
|
||||||
"""Genere feuille excel pour saisie des notes.
|
"""Genere feuille excel pour saisie des notes.
|
||||||
E: evaluation (dict)
|
E: evaluation (dict)
|
||||||
lines: liste de tuples
|
lines: liste de tuples
|
||||||
@ -512,18 +512,20 @@ def excel_feuille_saisie(e, titreannee, description, lines):
|
|||||||
# description evaluation
|
# description evaluation
|
||||||
ws.append_single_cell_row(scu.unescape_html(description), style_titres)
|
ws.append_single_cell_row(scu.unescape_html(description), style_titres)
|
||||||
ws.append_single_cell_row(
|
ws.append_single_cell_row(
|
||||||
"Evaluation du %s (coef. %g)" % (e["jour"], e["coefficient"]), style
|
"Evaluation du %s (coef. %g)"
|
||||||
|
% (evaluation.jour or "sans date", evaluation.coefficient or 0.0),
|
||||||
|
style,
|
||||||
)
|
)
|
||||||
# ligne blanche
|
# ligne blanche
|
||||||
ws.append_blank_row()
|
ws.append_blank_row()
|
||||||
# code et titres colonnes
|
# code et titres colonnes
|
||||||
ws.append_row(
|
ws.append_row(
|
||||||
[
|
[
|
||||||
ws.make_cell("!%s" % e["evaluation_id"], style_ro),
|
ws.make_cell("!%s" % evaluation.id, style_ro),
|
||||||
ws.make_cell("Nom", style_titres),
|
ws.make_cell("Nom", style_titres),
|
||||||
ws.make_cell("Prénom", style_titres),
|
ws.make_cell("Prénom", style_titres),
|
||||||
ws.make_cell("Groupe", style_titres),
|
ws.make_cell("Groupe", style_titres),
|
||||||
ws.make_cell("Note sur %g" % e["note_max"], style_titres),
|
ws.make_cell("Note sur %g" % (evaluation.note_max or 0.0), style_titres),
|
||||||
ws.make_cell("Remarque", style_titres),
|
ws.make_cell("Remarque", style_titres),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ from app.auth.models import User
|
|||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import Evaluation, FormSemestre
|
from app.models import Evaluation, FormSemestre
|
||||||
from app.models import ModuleImpl, ScolarNews
|
from app.models import ModuleImpl, NotesNotes, ScolarNews
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc.sco_utils import ModuleType
|
from app.scodoc.sco_utils import ModuleType
|
||||||
@ -50,7 +50,8 @@ from app.scodoc.sco_exceptions import (
|
|||||||
AccessDenied,
|
AccessDenied,
|
||||||
InvalidNoteValue,
|
InvalidNoteValue,
|
||||||
NoteProcessError,
|
NoteProcessError,
|
||||||
ScoGenError,
|
ScoBugCatcher,
|
||||||
|
ScoException,
|
||||||
ScoInvalidParamError,
|
ScoInvalidParamError,
|
||||||
ScoValueError,
|
ScoValueError,
|
||||||
)
|
)
|
||||||
@ -63,7 +64,6 @@ from app.scodoc import sco_edit_module
|
|||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_excel
|
from app.scodoc import sco_excel
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_groups_view
|
from app.scodoc import sco_groups_view
|
||||||
@ -526,9 +526,8 @@ def notes_add(
|
|||||||
- si la note existe deja avec valeur distincte, ajoute une entree au log (notes_notes_log)
|
- si la note existe deja avec valeur distincte, ajoute une entree au log (notes_notes_log)
|
||||||
Return tuple (nb_changed, nb_suppress, existing_decisions)
|
Return tuple (nb_changed, nb_suppress, existing_decisions)
|
||||||
"""
|
"""
|
||||||
now = psycopg2.Timestamp(
|
now = psycopg2.Timestamp(*time.localtime()[:6])
|
||||||
*time.localtime()[:6]
|
|
||||||
) # datetime.datetime.now().isoformat()
|
|
||||||
# Verifie inscription et valeur note
|
# Verifie inscription et valeur note
|
||||||
inscrits = {
|
inscrits = {
|
||||||
x[0]
|
x[0]
|
||||||
@ -550,11 +549,11 @@ def notes_add(
|
|||||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
nb_changed = 0
|
nb_changed = 0
|
||||||
nb_suppress = 0
|
nb_suppress = 0
|
||||||
E = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})[0]
|
evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
|
||||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
formsemestre: FormSemestre = evaluation.moduleimpl.formsemestre
|
||||||
existing_decisions = (
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
[]
|
# etudids pour lesquels il y a une decision de jury et que la note change:
|
||||||
) # etudids pour lesquels il y a une decision de jury et que la note change
|
etudids_with_existing_decision = []
|
||||||
try:
|
try:
|
||||||
for etudid, value in notes:
|
for etudid, value in notes:
|
||||||
changed = False
|
changed = False
|
||||||
@ -571,20 +570,29 @@ def notes_add(
|
|||||||
"date": now,
|
"date": now,
|
||||||
}
|
}
|
||||||
ndb.quote_dict(aa)
|
ndb.quote_dict(aa)
|
||||||
cursor.execute(
|
try:
|
||||||
"""INSERT INTO notes_notes
|
cursor.execute(
|
||||||
(etudid, evaluation_id, value, comment, date, uid)
|
"""INSERT INTO notes_notes
|
||||||
VALUES (%(etudid)s,%(evaluation_id)s,%(value)s,%(comment)s,%(date)s,%(uid)s)
|
(etudid, evaluation_id, value, comment, date, uid)
|
||||||
""",
|
VALUES (%(etudid)s,%(evaluation_id)s,%(value)s,%(comment)s,%(date)s,%(uid)s)
|
||||||
aa,
|
""",
|
||||||
)
|
aa,
|
||||||
|
)
|
||||||
|
except psycopg2.errors.UniqueViolation as exc:
|
||||||
|
# XXX ne devrait pas arriver mais bug possible ici (non reproductible)
|
||||||
|
existing_note = NotesNotes.query.filter_by(
|
||||||
|
evaluation_id=evaluation_id, etudid=etudid
|
||||||
|
).first()
|
||||||
|
raise ScoBugCatcher(
|
||||||
|
f"dup: existing={existing_note}"
|
||||||
|
) from exc
|
||||||
changed = True
|
changed = True
|
||||||
else:
|
else:
|
||||||
# il y a deja une note
|
# il y a deja une note
|
||||||
oldval = notes_db[etudid]["value"]
|
oldval = notes_db[etudid]["value"]
|
||||||
if type(value) != type(oldval):
|
if type(value) != type(oldval):
|
||||||
changed = True
|
changed = True
|
||||||
elif type(value) == float and (
|
elif isinstance(value, float) and (
|
||||||
abs(value - oldval) > scu.NOTES_PRECISION
|
abs(value - oldval) > scu.NOTES_PRECISION
|
||||||
):
|
):
|
||||||
changed = True
|
changed = True
|
||||||
@ -646,26 +654,21 @@ def notes_add(
|
|||||||
nb_suppress += 1
|
nb_suppress += 1
|
||||||
if changed:
|
if changed:
|
||||||
nb_changed += 1
|
nb_changed += 1
|
||||||
if has_existing_decision(M, E, etudid):
|
if res.etud_has_decision(etudid):
|
||||||
existing_decisions.append(etudid)
|
etudids_with_existing_decision.append(etudid)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
log("*** exception in notes_add")
|
log("*** exception in notes_add")
|
||||||
if do_it:
|
if do_it:
|
||||||
cnx.rollback() # abort
|
cnx.rollback() # abort
|
||||||
# inval cache
|
# inval cache
|
||||||
sco_cache.invalidate_formsemestre(
|
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre.id)
|
||||||
formsemestre_id=M["formsemestre_id"]
|
|
||||||
) # > modif notes (exception)
|
|
||||||
sco_cache.EvaluationCache.delete(evaluation_id)
|
sco_cache.EvaluationCache.delete(evaluation_id)
|
||||||
raise # XXX
|
raise ScoException from exc
|
||||||
raise ScoGenError("Erreur enregistrement note: merci de ré-essayer") from exc
|
|
||||||
if do_it:
|
if do_it:
|
||||||
cnx.commit()
|
cnx.commit()
|
||||||
sco_cache.invalidate_formsemestre(
|
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre.id)
|
||||||
formsemestre_id=M["formsemestre_id"]
|
|
||||||
) # > modif notes
|
|
||||||
sco_cache.EvaluationCache.delete(evaluation_id)
|
sco_cache.EvaluationCache.delete(evaluation_id)
|
||||||
return nb_changed, nb_suppress, existing_decisions
|
return nb_changed, nb_suppress, etudids_with_existing_decision
|
||||||
|
|
||||||
|
|
||||||
def saisie_notes_tableur(evaluation_id, group_ids=()):
|
def saisie_notes_tableur(evaluation_id, group_ids=()):
|
||||||
@ -868,35 +871,35 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
|
|||||||
|
|
||||||
def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
||||||
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
||||||
evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})
|
evaluation: Evaluation = Evaluation.query.get(evaluation_id)
|
||||||
if not evals:
|
if not evaluation:
|
||||||
raise ScoValueError("invalid evaluation_id")
|
raise ScoValueError("invalid evaluation_id")
|
||||||
eval_dict = evals[0]
|
modimpl = evaluation.moduleimpl
|
||||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=eval_dict["moduleimpl_id"])[0]
|
formsemestre = modimpl.formsemestre
|
||||||
formsemestre_id = M["formsemestre_id"]
|
mod_responsable = sco_users.user_info(modimpl.responsable_id)
|
||||||
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]
|
if evaluation.jour:
|
||||||
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
|
indication_date = evaluation.jour.isoformat()
|
||||||
mod_responsable = sco_users.user_info(M["responsable_id"])
|
|
||||||
if eval_dict["jour"]:
|
|
||||||
indication_date = ndb.DateDMYtoISO(eval_dict["jour"])
|
|
||||||
else:
|
else:
|
||||||
indication_date = scu.sanitize_filename(eval_dict["description"])[:12]
|
indication_date = scu.sanitize_filename(evaluation.description or "")[:12]
|
||||||
eval_name = "%s-%s" % (Mod["code"], indication_date)
|
eval_name = "%s-%s" % (evaluation.moduleimpl.module.code, indication_date)
|
||||||
|
|
||||||
if eval_dict["description"]:
|
if evaluation.description:
|
||||||
evaltitre = "%s du %s" % (eval_dict["description"], eval_dict["jour"])
|
evaltitre = "%s du %s" % (
|
||||||
|
evaluation.description,
|
||||||
|
evaluation.jour.strftime("%d/%m/%Y"),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
evaltitre = "évaluation du %s" % eval_dict["jour"]
|
evaltitre = "évaluation du %s" % evaluation.jour.strftime("%d/%m/%Y")
|
||||||
description = "%s en %s (%s) resp. %s" % (
|
description = "%s en %s (%s) resp. %s" % (
|
||||||
evaltitre,
|
evaltitre,
|
||||||
Mod["abbrev"] or "",
|
evaluation.moduleimpl.module.abbrev or "",
|
||||||
Mod["code"] or "",
|
evaluation.moduleimpl.module.code,
|
||||||
mod_responsable["prenomnom"],
|
mod_responsable["prenomnom"],
|
||||||
)
|
)
|
||||||
|
|
||||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||||
group_ids=group_ids,
|
group_ids=group_ids,
|
||||||
formsemestre_id=formsemestre_id,
|
formsemestre_id=formsemestre.id,
|
||||||
select_all_when_unspecified=True,
|
select_all_when_unspecified=True,
|
||||||
etat=None,
|
etat=None,
|
||||||
)
|
)
|
||||||
@ -919,15 +922,15 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
|||||||
# une liste de liste de chaines: lignes de la feuille de calcul
|
# une liste de liste de chaines: lignes de la feuille de calcul
|
||||||
L = []
|
L = []
|
||||||
|
|
||||||
etuds = _get_sorted_etuds(eval_dict, etudids, formsemestre_id)
|
etuds = _get_sorted_etuds(evaluation, etudids, formsemestre.id)
|
||||||
for e in etuds:
|
for e in etuds:
|
||||||
etudid = e["etudid"]
|
etudid = e["etudid"]
|
||||||
groups = sco_groups.get_etud_groups(etudid, formsemestre_id)
|
groups = sco_groups.get_etud_groups(etudid, formsemestre.id)
|
||||||
grc = sco_groups.listgroups_abbrev(groups)
|
grc = sco_groups.listgroups_abbrev(groups)
|
||||||
|
|
||||||
L.append(
|
L.append(
|
||||||
[
|
[
|
||||||
"%s" % etudid,
|
str(etudid),
|
||||||
e["nom"].upper(),
|
e["nom"].upper(),
|
||||||
e["prenom"].lower().capitalize(),
|
e["prenom"].lower().capitalize(),
|
||||||
e["inscr"]["etat"],
|
e["inscr"]["etat"],
|
||||||
@ -939,29 +942,9 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
|||||||
|
|
||||||
filename = "notes_%s_%s" % (eval_name, gr_title_filename)
|
filename = "notes_%s_%s" % (eval_name, gr_title_filename)
|
||||||
xls = sco_excel.excel_feuille_saisie(
|
xls = sco_excel.excel_feuille_saisie(
|
||||||
eval_dict, sem["titreannee"], description, lines=L
|
evaluation, formsemestre.titre_annee(), description, lines=L
|
||||||
)
|
)
|
||||||
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
||||||
# return sco_excel.send_excel_file(xls, filename)
|
|
||||||
|
|
||||||
|
|
||||||
def has_existing_decision(M, E, etudid):
|
|
||||||
"""Verifie s'il y a une validation pour cet etudiant dans ce semestre ou UE
|
|
||||||
Si oui, return True
|
|
||||||
"""
|
|
||||||
formsemestre_id = M["formsemestre_id"]
|
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
|
||||||
if nt.get_etud_decision_sem(etudid):
|
|
||||||
return True
|
|
||||||
dec_ues = nt.get_etud_decisions_ue(etudid)
|
|
||||||
if dec_ues:
|
|
||||||
mod = sco_edit_module.module_list({"module_id": M["module_id"]})[0]
|
|
||||||
ue_id = mod["ue_id"]
|
|
||||||
if ue_id in dec_ues:
|
|
||||||
return True # decision pour l'UE a laquelle appartient cette evaluation
|
|
||||||
|
|
||||||
return False # pas de decision de jury affectee par cette note
|
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
@ -973,20 +956,18 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
|||||||
if not isinstance(evaluation_id, int):
|
if not isinstance(evaluation_id, int):
|
||||||
raise ScoInvalidParamError()
|
raise ScoInvalidParamError()
|
||||||
group_ids = [int(group_id) for group_id in (group_ids or [])]
|
group_ids = [int(group_id) for group_id in (group_ids or [])]
|
||||||
evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})
|
evaluation: Evaluation = Evaluation.query.get(evaluation_id)
|
||||||
if not evals:
|
if evaluation is None:
|
||||||
raise ScoValueError("évaluation inexistante")
|
raise ScoValueError("évaluation inexistante")
|
||||||
E = evals[0]
|
modimpl = evaluation.moduleimpl
|
||||||
M = sco_moduleimpl.moduleimpl_withmodule_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
|
||||||
formsemestre_id = M["formsemestre_id"]
|
|
||||||
moduleimpl_status_url = url_for(
|
moduleimpl_status_url = url_for(
|
||||||
"notes.moduleimpl_status",
|
"notes.moduleimpl_status",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
moduleimpl_id=E["moduleimpl_id"],
|
moduleimpl_id=evaluation.moduleimpl_id,
|
||||||
)
|
)
|
||||||
# Check access
|
# Check access
|
||||||
# (admin, respformation, and responsable_id)
|
# (admin, respformation, and responsable_id)
|
||||||
if not sco_permissions_check.can_edit_notes(current_user, E["moduleimpl_id"]):
|
if not sco_permissions_check.can_edit_notes(current_user, evaluation.moduleimpl_id):
|
||||||
return f"""
|
return f"""
|
||||||
{html_sco_header.sco_header()}
|
{html_sco_header.sco_header()}
|
||||||
<h2>Modification des notes impossible pour {current_user.user_name}</h2>
|
<h2>Modification des notes impossible pour {current_user.user_name}</h2>
|
||||||
@ -1001,16 +982,16 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
|||||||
# Informations sur les groupes à afficher:
|
# Informations sur les groupes à afficher:
|
||||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||||
group_ids=group_ids,
|
group_ids=group_ids,
|
||||||
formsemestre_id=formsemestre_id,
|
formsemestre_id=modimpl.formsemestre_id,
|
||||||
select_all_when_unspecified=True,
|
select_all_when_unspecified=True,
|
||||||
etat=None,
|
etat=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
if E["description"]:
|
page_title = (
|
||||||
page_title = 'Saisie "%s"' % E["description"]
|
f'Saisie "{evaluation.description}"'
|
||||||
else:
|
if evaluation.description
|
||||||
page_title = "Saisie des notes"
|
else "Saisie des notes"
|
||||||
|
)
|
||||||
# HTML page:
|
# HTML page:
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
html_sco_header.sco_header(
|
||||||
@ -1036,19 +1017,19 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
|||||||
"id": "menu_saisie_tableur",
|
"id": "menu_saisie_tableur",
|
||||||
"endpoint": "notes.saisie_notes_tableur",
|
"endpoint": "notes.saisie_notes_tableur",
|
||||||
"args": {
|
"args": {
|
||||||
"evaluation_id": E["evaluation_id"],
|
"evaluation_id": evaluation.id,
|
||||||
"group_ids": groups_infos.group_ids,
|
"group_ids": groups_infos.group_ids,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Voir toutes les notes du module",
|
"title": "Voir toutes les notes du module",
|
||||||
"endpoint": "notes.evaluation_listenotes",
|
"endpoint": "notes.evaluation_listenotes",
|
||||||
"args": {"moduleimpl_id": E["moduleimpl_id"]},
|
"args": {"moduleimpl_id": evaluation.moduleimpl_id},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Effacer toutes les notes de cette évaluation",
|
"title": "Effacer toutes les notes de cette évaluation",
|
||||||
"endpoint": "notes.evaluation_suppress_alln",
|
"endpoint": "notes.evaluation_suppress_alln",
|
||||||
"args": {"evaluation_id": E["evaluation_id"]},
|
"args": {"evaluation_id": evaluation.id},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
alone=True,
|
alone=True,
|
||||||
@ -1077,7 +1058,9 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Le formulaire de saisie des notes:
|
# Le formulaire de saisie des notes:
|
||||||
form = _form_saisie_notes(E, M, groups_infos, destination=moduleimpl_status_url)
|
form = _form_saisie_notes(
|
||||||
|
evaluation, modimpl, groups_infos, destination=moduleimpl_status_url
|
||||||
|
)
|
||||||
if form is None:
|
if form is None:
|
||||||
return flask.redirect(moduleimpl_status_url)
|
return flask.redirect(moduleimpl_status_url)
|
||||||
H.append(form)
|
H.append(form)
|
||||||
@ -1101,10 +1084,9 @@ def saisie_notes(evaluation_id: int, group_ids: list = None):
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def _get_sorted_etuds(eval_dict: dict, etudids: list, formsemestre_id: int):
|
def _get_sorted_etuds(evaluation: Evaluation, etudids: list, formsemestre_id: int):
|
||||||
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
|
# Notes existantes
|
||||||
eval_dict["evaluation_id"]
|
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation.id)
|
||||||
) # Notes existantes
|
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
etuds = []
|
etuds = []
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
@ -1123,17 +1105,17 @@ def _get_sorted_etuds(eval_dict: dict, etudids: list, formsemestre_id: int):
|
|||||||
e["groups"] = sco_groups.get_etud_groups(etudid, formsemestre_id)
|
e["groups"] = sco_groups.get_etud_groups(etudid, formsemestre_id)
|
||||||
|
|
||||||
# Information sur absence (tenant compte de la demi-journée)
|
# Information sur absence (tenant compte de la demi-journée)
|
||||||
jour_iso = ndb.DateDMYtoISO(eval_dict["jour"])
|
jour_iso = evaluation.jour.isoformat() if evaluation.jour else ""
|
||||||
warn_abs_lst = []
|
warn_abs_lst = []
|
||||||
if eval_dict["matin"]:
|
if evaluation.is_matin():
|
||||||
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=1)
|
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=True)
|
||||||
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=1)
|
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=True)
|
||||||
if nbabs:
|
if nbabs:
|
||||||
if nbabsjust:
|
if nbabsjust:
|
||||||
warn_abs_lst.append("absent justifié le matin !")
|
warn_abs_lst.append("absent justifié le matin !")
|
||||||
else:
|
else:
|
||||||
warn_abs_lst.append("absent le matin !")
|
warn_abs_lst.append("absent le matin !")
|
||||||
if eval_dict["apresmidi"]:
|
if evaluation.is_apresmidi():
|
||||||
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0)
|
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0)
|
||||||
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
|
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
|
||||||
if nbabs:
|
if nbabs:
|
||||||
@ -1169,35 +1151,38 @@ def _get_sorted_etuds(eval_dict: dict, etudids: list, formsemestre_id: int):
|
|||||||
return etuds
|
return etuds
|
||||||
|
|
||||||
|
|
||||||
def _form_saisie_notes(E, M, groups_infos, destination=""):
|
def _form_saisie_notes(
|
||||||
|
evaluation: Evaluation, modimpl: ModuleImpl, groups_infos, destination=""
|
||||||
|
):
|
||||||
"""Formulaire HTML saisie des notes dans l'évaluation E du moduleimpl M
|
"""Formulaire HTML saisie des notes dans l'évaluation E du moduleimpl M
|
||||||
pour les groupes indiqués.
|
pour les groupes indiqués.
|
||||||
|
|
||||||
On charge tous les étudiants, ne seront montrés que ceux
|
On charge tous les étudiants, ne seront montrés que ceux
|
||||||
des groupes sélectionnés grace a un filtre en javascript.
|
des groupes sélectionnés grace a un filtre en javascript.
|
||||||
"""
|
"""
|
||||||
evaluation_id = E["evaluation_id"]
|
formsemestre_id = modimpl.formsemestre_id
|
||||||
formsemestre_id = M["formsemestre_id"]
|
formsemestre: FormSemestre = evaluation.moduleimpl.formsemestre
|
||||||
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
etudids = [
|
etudids = [
|
||||||
x[0]
|
x[0]
|
||||||
for x in sco_groups.do_evaluation_listeetuds_groups(
|
for x in sco_groups.do_evaluation_listeetuds_groups(
|
||||||
evaluation_id, getallstudents=True, include_demdef=True
|
evaluation.id, getallstudents=True, include_demdef=True
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if not etudids:
|
if not etudids:
|
||||||
return '<div class="ue_warning"><span>Aucun étudiant sélectionné !</span></div>'
|
return '<div class="ue_warning"><span>Aucun étudiant sélectionné !</span></div>'
|
||||||
|
|
||||||
# Decisions de jury existantes ?
|
# Décisions de jury existantes ?
|
||||||
decisions_jury = {etudid: has_existing_decision(M, E, etudid) for etudid in etudids}
|
decisions_jury = {etudid: res.etud_has_decision(etudid) for etudid in etudids}
|
||||||
# Nb de decisions de jury (pour les inscrits à l'évaluation):
|
|
||||||
|
# Nb de décisions de jury (pour les inscrits à l'évaluation):
|
||||||
nb_decisions = sum(decisions_jury.values())
|
nb_decisions = sum(decisions_jury.values())
|
||||||
|
|
||||||
etuds = _get_sorted_etuds(E, etudids, formsemestre_id)
|
etuds = _get_sorted_etuds(evaluation, etudids, formsemestre_id)
|
||||||
|
|
||||||
# Build form:
|
# Build form:
|
||||||
descr = [
|
descr = [
|
||||||
("evaluation_id", {"default": evaluation_id, "input_type": "hidden"}),
|
("evaluation_id", {"default": evaluation.id, "input_type": "hidden"}),
|
||||||
("formsemestre_id", {"default": formsemestre_id, "input_type": "hidden"}),
|
("formsemestre_id", {"default": formsemestre_id, "input_type": "hidden"}),
|
||||||
(
|
(
|
||||||
"group_ids",
|
"group_ids",
|
||||||
@ -1207,7 +1192,7 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
("comment", {"size": 44, "title": "Commentaire", "return_focus_next": True}),
|
("comment", {"size": 44, "title": "Commentaire", "return_focus_next": True}),
|
||||||
("changed", {"default": "0", "input_type": "hidden"}), # changed in JS
|
("changed", {"default": "0", "input_type": "hidden"}), # changed in JS
|
||||||
]
|
]
|
||||||
if M["module"]["module_type"] in (
|
if modimpl.module.module_type in (
|
||||||
ModuleType.STANDARD,
|
ModuleType.STANDARD,
|
||||||
ModuleType.RESSOURCE,
|
ModuleType.RESSOURCE,
|
||||||
ModuleType.SAE,
|
ModuleType.SAE,
|
||||||
@ -1220,11 +1205,11 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
"title": "Notes ",
|
"title": "Notes ",
|
||||||
"cssclass": "formnote_bareme",
|
"cssclass": "formnote_bareme",
|
||||||
"readonly": True,
|
"readonly": True,
|
||||||
"default": " / %g" % E["note_max"],
|
"default": " / %g" % evaluation.note_max,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif M["module"]["module_type"] == ModuleType.MALUS:
|
elif modimpl.module.module_type == ModuleType.MALUS:
|
||||||
descr.append(
|
descr.append(
|
||||||
(
|
(
|
||||||
"s3",
|
"s3",
|
||||||
@ -1238,7 +1223,7 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid module type (%s)" % M["module"]["module_type"]) # bug
|
raise ValueError(f"invalid module type ({modimpl.module.module_type})") # bug
|
||||||
|
|
||||||
initvalues = {}
|
initvalues = {}
|
||||||
for e in etuds:
|
for e in etuds:
|
||||||
@ -1248,7 +1233,7 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
if disabled:
|
if disabled:
|
||||||
classdem = " etud_dem"
|
classdem = " etud_dem"
|
||||||
etud_classes.append("etud_dem")
|
etud_classes.append("etud_dem")
|
||||||
disabled_attr = 'disabled="%d"' % disabled
|
disabled_attr = f'disabled="{disabled}"'
|
||||||
else:
|
else:
|
||||||
classdem = ""
|
classdem = ""
|
||||||
disabled_attr = ""
|
disabled_attr = ""
|
||||||
@ -1265,18 +1250,17 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Historique des saisies de notes:
|
# Historique des saisies de notes:
|
||||||
if not disabled:
|
explanation = (
|
||||||
explanation = (
|
""
|
||||||
'<span id="hist_%s">' % etudid
|
if disabled
|
||||||
+ get_note_history_menu(evaluation_id, etudid)
|
else f"""<span id="hist_{etudid}">{
|
||||||
+ "</span>"
|
get_note_history_menu(evaluation.id, etudid)
|
||||||
)
|
}</span>"""
|
||||||
else:
|
)
|
||||||
explanation = ""
|
|
||||||
explanation = e["absinfo"] + explanation
|
explanation = e["absinfo"] + explanation
|
||||||
|
|
||||||
# Lien modif decision de jury:
|
# Lien modif decision de jury:
|
||||||
explanation += '<span id="jurylink_%s" class="jurylink"></span>' % etudid
|
explanation += f'<span id="jurylink_{etudid}" class="jurylink"></span>'
|
||||||
|
|
||||||
# Valeur actuelle du champ:
|
# Valeur actuelle du champ:
|
||||||
initvalues["note_" + str(etudid)] = e["val"]
|
initvalues["note_" + str(etudid)] = e["val"]
|
||||||
@ -1330,7 +1314,7 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
H.append(tf.getform()) # check and init
|
H.append(tf.getform()) # check and init
|
||||||
H.append(
|
H.append(
|
||||||
f"""<a href="{url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept,
|
f"""<a href="{url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept,
|
||||||
moduleimpl_id=M["moduleimpl_id"])
|
moduleimpl_id=modimpl.id)
|
||||||
}" class="btn btn-primary">Terminer</a>
|
}" class="btn btn-primary">Terminer</a>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@ -1345,7 +1329,7 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
Mettre les notes manquantes à
|
Mettre les notes manquantes à
|
||||||
<input type="text" size="5" name="value"/>
|
<input type="text" size="5" name="value"/>
|
||||||
<input type="submit" value="OK"/>
|
<input type="submit" value="OK"/>
|
||||||
<input type="hidden" name="evaluation_id" value="{evaluation_id}"/>
|
<input type="hidden" name="evaluation_id" value="{evaluation.id}"/>
|
||||||
<input class="group_ids_str" type="hidden" name="group_ids_str" value="{
|
<input class="group_ids_str" type="hidden" name="group_ids_str" value="{
|
||||||
",".join([str(x) for x in groups_infos.group_ids])
|
",".join([str(x) for x in groups_infos.group_ids])
|
||||||
}"/>
|
}"/>
|
||||||
@ -1364,10 +1348,8 @@ def _form_saisie_notes(E, M, groups_infos, destination=""):
|
|||||||
|
|
||||||
def save_note(etudid=None, evaluation_id=None, value=None, comment=""):
|
def save_note(etudid=None, evaluation_id=None, value=None, comment=""):
|
||||||
"""Enregistre une note (ajax)"""
|
"""Enregistre une note (ajax)"""
|
||||||
authuser = current_user
|
|
||||||
log(
|
log(
|
||||||
"save_note: evaluation_id=%s etudid=%s uid=%s value=%s"
|
f"save_note: evaluation_id={evaluation_id} etudid={etudid} uid={current_user} value={value}"
|
||||||
% (evaluation_id, etudid, authuser, value)
|
|
||||||
)
|
)
|
||||||
E = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})[0]
|
E = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})[0]
|
||||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
||||||
@ -1380,13 +1362,13 @@ def save_note(etudid=None, evaluation_id=None, value=None, comment=""):
|
|||||||
)
|
)
|
||||||
result = {"nbchanged": 0} # JSON
|
result = {"nbchanged": 0} # JSON
|
||||||
# Check access: admin, respformation, or responsable_id
|
# Check access: admin, respformation, or responsable_id
|
||||||
if not sco_permissions_check.can_edit_notes(authuser, E["moduleimpl_id"]):
|
if not sco_permissions_check.can_edit_notes(current_user, E["moduleimpl_id"]):
|
||||||
result["status"] = "unauthorized"
|
result["status"] = "unauthorized"
|
||||||
else:
|
else:
|
||||||
L, _, _, _, _ = _check_notes([(etudid, value)], E, Mod)
|
L, _, _, _, _ = _check_notes([(etudid, value)], E, Mod)
|
||||||
if L:
|
if L:
|
||||||
nbchanged, _, existing_decisions = notes_add(
|
nbchanged, _, existing_decisions = notes_add(
|
||||||
authuser, evaluation_id, L, comment=comment, do_it=True
|
current_user, evaluation_id, L, comment=comment, do_it=True
|
||||||
)
|
)
|
||||||
ScolarNews.add(
|
ScolarNews.add(
|
||||||
typ=ScolarNews.NEWS_NOTE,
|
typ=ScolarNews.NEWS_NOTE,
|
||||||
|
Loading…
Reference in New Issue
Block a user