forked from ScoDoc/ScoDoc
Edition des évaluations, nettoyage code, fix #799. Tests OK.
This commit is contained in:
parent
ee601071f5
commit
bc5292b165
@ -91,7 +91,7 @@ class Evaluation(models.ScoDocModel):
|
||||
evaluation_type=None,
|
||||
numero=None,
|
||||
**kw, # ceci pour absorber les éventuel arguments excedentaires
|
||||
):
|
||||
) -> "Evaluation":
|
||||
"""Create an evaluation. Check permission and all arguments.
|
||||
Ne crée pas les poids vers les UEs.
|
||||
Add to session, do not commit.
|
||||
@ -103,7 +103,7 @@ class Evaluation(models.ScoDocModel):
|
||||
args = locals()
|
||||
del args["cls"]
|
||||
del args["kw"]
|
||||
check_convert_evaluation_args(moduleimpl, args)
|
||||
check_and_convert_evaluation_args(args, moduleimpl)
|
||||
# Check numeros
|
||||
Evaluation.moduleimpl_evaluation_renumber(moduleimpl, only_if_unumbered=True)
|
||||
if not "numero" in args or args["numero"] is None:
|
||||
@ -254,15 +254,6 @@ class Evaluation(models.ScoDocModel):
|
||||
|
||||
return e_dict
|
||||
|
||||
def convert_dict_fields(self, args: dict) -> dict:
|
||||
"""Convert fields in the given dict. No other side effect.
|
||||
returns: dict to store in model's db.
|
||||
"""
|
||||
check_convert_evaluation_args(self.moduleimpl, args)
|
||||
if args.get("numero") is None:
|
||||
args["numero"] = Evaluation.get_max_numero(self.moduleimpl.id) + 1
|
||||
return args
|
||||
|
||||
@classmethod
|
||||
def get_evaluation(
|
||||
cls, evaluation_id: int | str, dept_id: int = None
|
||||
@ -568,7 +559,7 @@ def evaluation_enrich_dict(e: Evaluation, e_dict: dict):
|
||||
return e_dict
|
||||
|
||||
|
||||
def check_convert_evaluation_args(moduleimpl: "ModuleImpl", data: dict):
|
||||
def check_and_convert_evaluation_args(data: dict, moduleimpl: "ModuleImpl"):
|
||||
"""Check coefficient, dates and duration, raises exception if invalid.
|
||||
Convert date and time strings to date and time objects.
|
||||
|
||||
@ -608,7 +599,7 @@ def check_convert_evaluation_args(moduleimpl: "ModuleImpl", data: dict):
|
||||
if coef < 0:
|
||||
raise ScoValueError("invalid coefficient value (must be positive or null)")
|
||||
data["coefficient"] = coef
|
||||
# --- date de l'évaluation
|
||||
# --- date de l'évaluation dans le semestre ?
|
||||
formsemestre = moduleimpl.formsemestre
|
||||
date_debut = data.get("date_debut", None)
|
||||
if date_debut:
|
||||
|
@ -31,96 +31,15 @@
|
||||
import flask
|
||||
from flask import url_for, g
|
||||
from flask_login import current_user
|
||||
import sqlalchemy as sa
|
||||
|
||||
from app import db, log
|
||||
|
||||
from app.models import Evaluation
|
||||
from app.models.evaluations import check_convert_evaluation_args
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.sco_exceptions import AccessDenied
|
||||
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_moduleimpl
|
||||
|
||||
|
||||
_evaluationEditor = ndb.EditableTable(
|
||||
"notes_evaluation",
|
||||
"evaluation_id",
|
||||
(
|
||||
"evaluation_id",
|
||||
"moduleimpl_id",
|
||||
"date_debut",
|
||||
"date_fin",
|
||||
"description",
|
||||
"note_max",
|
||||
"coefficient",
|
||||
"visibulletin",
|
||||
"publish_incomplete",
|
||||
"evaluation_type",
|
||||
"numero",
|
||||
),
|
||||
sortkey="numero, date_debut desc", # plus recente d'abord
|
||||
output_formators={
|
||||
"numero": ndb.int_null_is_zero,
|
||||
},
|
||||
input_formators={
|
||||
"visibulletin": bool,
|
||||
"publish_incomplete": bool,
|
||||
"evaluation_type": int,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def get_evaluations_dict(args: dict) -> list[dict]:
|
||||
"""Liste evaluations, triées numero (or most recent date first).
|
||||
Fonction de transition pour ancien code ScoDoc7.
|
||||
|
||||
Ajoute les champs:
|
||||
'duree' : '2h30'
|
||||
'matin' : 1 (commence avant 12:00) ou 0
|
||||
'apresmidi' : 1 (termine après 12:00) ou 0
|
||||
'descrheure' : ' de 15h00 à 16h30'
|
||||
"""
|
||||
# calcule duree (chaine de car.) de chaque evaluation et ajoute jour_iso, matin, apresmidi
|
||||
return [
|
||||
e.to_dict()
|
||||
for e in Evaluation.query.filter_by(**args).order_by(
|
||||
sa.desc(Evaluation.numero), sa.desc(Evaluation.date_debut)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def do_evaluation_list_in_formsemestre(formsemestre_id):
|
||||
"list evaluations in this formsemestre"
|
||||
mods = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id)
|
||||
evals = []
|
||||
for modimpl in mods:
|
||||
evals += get_evaluations_dict(args={"moduleimpl_id": modimpl["moduleimpl_id"]})
|
||||
return evals
|
||||
|
||||
|
||||
def do_evaluation_edit(args):
|
||||
"edit an evaluation"
|
||||
evaluation_id = args["evaluation_id"]
|
||||
evaluation: Evaluation = db.session.get(Evaluation, evaluation_id)
|
||||
if evaluation is None:
|
||||
raise ValueError("evaluation inexistante !")
|
||||
|
||||
if not evaluation.moduleimpl.can_edit_evaluation(current_user):
|
||||
raise AccessDenied(
|
||||
f"Modification évaluation impossible pour {current_user.get_nomplogin()}"
|
||||
)
|
||||
args["moduleimpl_id"] = evaluation.moduleimpl.id
|
||||
check_convert_evaluation_args(evaluation.moduleimpl, args)
|
||||
|
||||
cnx = ndb.GetDBConnexion()
|
||||
_evaluationEditor.edit(cnx, args)
|
||||
# inval cache pour ce semestre
|
||||
sco_cache.invalidate_formsemestre(
|
||||
formsemestre_id=evaluation.moduleimpl.formsemestre_id
|
||||
)
|
||||
|
||||
|
||||
# ancien _notes_getall
|
||||
|
@ -31,14 +31,12 @@ import datetime
|
||||
import time
|
||||
|
||||
import flask
|
||||
from flask import url_for, render_template
|
||||
from flask import g
|
||||
from flask import g, render_template, request, url_for
|
||||
from flask_login import current_user
|
||||
from flask import request
|
||||
|
||||
from app import db
|
||||
from app.models import Evaluation, Module, ModuleImpl
|
||||
from app.models.evaluations import heure_to_time
|
||||
from app.models.evaluations import heure_to_time, check_and_convert_evaluation_args
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
@ -383,6 +381,8 @@ def evaluation_create_form(
|
||||
raise ScoValueError("Date (j/m/a) invalide") from exc
|
||||
else:
|
||||
date_debut = None
|
||||
args["date_debut"] = date_debut
|
||||
args["date_fin"] = date_debut # même jour
|
||||
args.pop("jour", None)
|
||||
if date_debut and args.get("heure_debut"):
|
||||
try:
|
||||
@ -415,6 +415,7 @@ def evaluation_create_form(
|
||||
args["blocked_until"] = None
|
||||
#
|
||||
if edit:
|
||||
check_and_convert_evaluation_args(args, modimpl)
|
||||
evaluation.from_dict(args)
|
||||
else:
|
||||
# création d'une evaluation
|
||||
|
@ -31,6 +31,7 @@ import flask
|
||||
from flask import url_for, flash, redirect
|
||||
from flask import g, request
|
||||
from flask_login import current_user
|
||||
import sqlalchemy as sa
|
||||
|
||||
from app import db
|
||||
from app.auth.models import User
|
||||
@ -63,8 +64,6 @@ from app.scodoc import html_sco_header
|
||||
from app.scodoc import codes_cursus
|
||||
from app.scodoc import sco_compute_moy
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_edit_ue
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups_copy
|
||||
from app.scodoc import sco_modalites
|
||||
@ -1113,7 +1112,8 @@ def formsemestre_delete_moduleimpls(formsemestre_id, module_ids_to_del):
|
||||
f"""<b>impossible de supprimer {module.code} ({module.titre or ""})
|
||||
car il y a {nb_evals} évaluations définies
|
||||
(<a href="{
|
||||
url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
|
||||
url_for("notes.moduleimpl_status",
|
||||
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
|
||||
}" class="stdlink">supprimez-les d\'abord</a>)</b>"""
|
||||
]
|
||||
ok = False
|
||||
@ -1233,7 +1233,11 @@ def formsemestre_clone(formsemestre_id):
|
||||
return "".join(H) + msg + tf[1] + html_sco_header.sco_footer()
|
||||
elif tf[0] == -1: # cancel
|
||||
return flask.redirect(
|
||||
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||
url_for(
|
||||
"notes.formsemestre_status",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
)
|
||||
else:
|
||||
resp = User.get_user_from_nomplogin(tf[2]["responsable_id"])
|
||||
@ -1356,9 +1360,9 @@ def do_formsemestre_clone(
|
||||
return formsemestre_id
|
||||
|
||||
|
||||
def formsemestre_delete(formsemestre_id):
|
||||
def formsemestre_delete(formsemestre_id: int) -> str | flask.Response:
|
||||
"""Delete a formsemestre (affiche avertissements)"""
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
H = [
|
||||
html_sco_header.html_sem_header("Suppression du semestre"),
|
||||
"""<div class="ue_warning"><span>Attention !</span>
|
||||
@ -1376,17 +1380,18 @@ Ceci n'est possible que si :
|
||||
</ol>
|
||||
</div>""",
|
||||
]
|
||||
|
||||
evals = sco_evaluation_db.do_evaluation_list_in_formsemestre(formsemestre_id)
|
||||
if evals:
|
||||
evaluations = (
|
||||
Evaluation.query.join(ModuleImpl)
|
||||
.filter_by(formsemestre_id=formsemestre.id)
|
||||
.all()
|
||||
)
|
||||
if evaluations:
|
||||
H.append(
|
||||
f"""<p class="warning">Attention: il y a {len(evals)} évaluations
|
||||
f"""<p class="warning">Attention: il y a {len(evaluations)} évaluations
|
||||
dans ce semestre
|
||||
(sa suppression entrainera l'effacement définif des notes) !</p>"""
|
||||
)
|
||||
submit_label = (
|
||||
f"Confirmer la suppression (du semestre et des {len(evals)} évaluations !)"
|
||||
)
|
||||
submit_label = f"Confirmer la suppression (du semestre et des {len(evaluations)} évaluations !)"
|
||||
else:
|
||||
submit_label = "Confirmer la suppression du semestre"
|
||||
tf = TrivialFormulator(
|
||||
@ -1413,8 +1418,10 @@ Ceci n'est possible que si :
|
||||
)
|
||||
else:
|
||||
H.append(tf[1])
|
||||
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
elif tf[0] == -1: # cancel
|
||||
|
||||
if tf[0] == -1: # cancel
|
||||
return flask.redirect(
|
||||
url_for(
|
||||
"notes.formsemestre_status",
|
||||
@ -1422,10 +1429,9 @@ Ceci n'est possible que si :
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
)
|
||||
else:
|
||||
return flask.redirect(
|
||||
"formsemestre_delete2?formsemestre_id=" + str(formsemestre_id)
|
||||
)
|
||||
return flask.redirect(
|
||||
"formsemestre_delete2?formsemestre_id=" + str(formsemestre_id)
|
||||
)
|
||||
|
||||
|
||||
def formsemestre_delete2(formsemestre_id, dialog_confirmed=False):
|
||||
@ -1486,106 +1492,165 @@ def formsemestre_has_decisions_or_compensations(
|
||||
return False, ""
|
||||
|
||||
|
||||
def do_formsemestre_delete(formsemestre_id):
|
||||
def do_formsemestre_delete(formsemestre_id: int):
|
||||
"""delete formsemestre, and all its moduleimpls.
|
||||
No checks, no warnings: erase all !
|
||||
"""
|
||||
cnx = ndb.GetDBConnexion()
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||
|
||||
sco_cache.EvaluationCache.invalidate_sem(formsemestre_id)
|
||||
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
sco_cache.EvaluationCache.invalidate_sem(formsemestre.id)
|
||||
titre_sem = formsemestre.titre_annee()
|
||||
# --- Destruction des modules de ce semestre
|
||||
mods = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id)
|
||||
for mod in mods:
|
||||
for modimpl in formsemestre.modimpls:
|
||||
# evaluations
|
||||
evals = sco_evaluation_db.get_evaluations_dict(
|
||||
args={"moduleimpl_id": mod["moduleimpl_id"]}
|
||||
)
|
||||
for e in evals:
|
||||
ndb.SimpleQuery(
|
||||
"DELETE FROM notes_notes WHERE evaluation_id=%(evaluation_id)s",
|
||||
e,
|
||||
for e in modimpl.evaluations:
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"""DELETE FROM notes_notes WHERE evaluation_id=:evaluation_id"""
|
||||
),
|
||||
{"evaluation_id": e.id},
|
||||
)
|
||||
ndb.SimpleQuery(
|
||||
"DELETE FROM notes_notes_log WHERE evaluation_id=%(evaluation_id)s",
|
||||
e,
|
||||
)
|
||||
ndb.SimpleQuery(
|
||||
"DELETE FROM notes_evaluation WHERE id=%(evaluation_id)s",
|
||||
e,
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"""DELETE FROM notes_notes_log WHERE evaluation_id=:evaluation_id"""
|
||||
),
|
||||
{"evaluation_id": e.id},
|
||||
)
|
||||
|
||||
sco_moduleimpl.do_moduleimpl_delete(
|
||||
mod["moduleimpl_id"], formsemestre_id=formsemestre_id
|
||||
)
|
||||
db.session.delete(e)
|
||||
db.session.delete(modimpl)
|
||||
# --- Desinscription des etudiants
|
||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||
req = "DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
|
||||
# --- Suppression des evenements
|
||||
req = "DELETE FROM scolar_events WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text("DELETE FROM scolar_events WHERE formsemestre_id=:formsemestre_id"),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des appreciations
|
||||
req = "DELETE FROM notes_appreciations WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_appreciations WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Supression des validations (!!!)
|
||||
req = "DELETE FROM scolar_formsemestre_validation WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM scolar_formsemestre_validation WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Supression des references a ce semestre dans les compensations:
|
||||
req = "UPDATE scolar_formsemestre_validation SET compense_formsemestre_id=NULL WHERE compense_formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"""UPDATE scolar_formsemestre_validation
|
||||
SET compense_formsemestre_id=NULL
|
||||
WHERE compense_formsemestre_id=:formsemestre_id"""
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des autorisations
|
||||
req = "DELETE FROM scolar_autorisation_inscription WHERE origin_formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM scolar_autorisation_inscription WHERE origin_formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des coefs d'UE capitalisées
|
||||
req = "DELETE FROM notes_formsemestre_uecoef WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_formsemestre_uecoef WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des item du menu custom
|
||||
req = "DELETE FROM notes_formsemestre_custommenu WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_formsemestre_custommenu WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des formules
|
||||
req = "DELETE FROM notes_formsemestre_ue_computation_expr WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_formsemestre_ue_computation_expr WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des preferences
|
||||
req = "DELETE FROM sco_prefs WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text("DELETE FROM sco_prefs WHERE formsemestre_id=:formsemestre_id"),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Suppression des groupes et partitions
|
||||
req = """DELETE FROM group_membership
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"""
|
||||
DELETE FROM group_membership
|
||||
WHERE group_id IN
|
||||
(SELECT gm.group_id FROM group_membership gm, partition p, group_descr gd
|
||||
WHERE gm.group_id = gd.id AND gd.partition_id = p.id
|
||||
AND p.formsemestre_id=%(formsemestre_id)s)
|
||||
AND p.formsemestre_id=:formsemestre_id)
|
||||
"""
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
req = """DELETE FROM group_descr
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"""
|
||||
DELETE FROM group_descr
|
||||
WHERE id IN
|
||||
(SELECT gd.id FROM group_descr gd, partition p
|
||||
WHERE gd.partition_id = p.id
|
||||
AND p.formsemestre_id=%(formsemestre_id)s)
|
||||
AND p.formsemestre_id=:formsemestre_id)
|
||||
"""
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
req = "DELETE FROM partition WHERE formsemestre_id=%(formsemestre_id)s"
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
db.session.execute(
|
||||
sa.text("DELETE FROM partition WHERE formsemestre_id=:formsemestre_id"),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Responsables
|
||||
req = """DELETE FROM notes_formsemestre_responsables
|
||||
WHERE formsemestre_id=%(formsemestre_id)s"""
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_formsemestre_responsables WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Etapes
|
||||
req = """DELETE FROM notes_formsemestre_etapes
|
||||
WHERE formsemestre_id=%(formsemestre_id)s"""
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_formsemestre_etapes WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- SemSets
|
||||
db.session.execute(
|
||||
sa.text(
|
||||
"DELETE FROM notes_semset_formsemestre WHERE formsemestre_id=:formsemestre_id"
|
||||
),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Dispenses d'UE
|
||||
req = """DELETE FROM "dispenseUE" WHERE formsemestre_id=%(formsemestre_id)s"""
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
db.session.execute(
|
||||
sa.text("""DELETE FROM "dispenseUE" WHERE formsemestre_id=:formsemestre_id"""),
|
||||
{"formsemestre_id": formsemestre_id},
|
||||
)
|
||||
# --- Destruction du semestre
|
||||
sco_formsemestre._formsemestreEditor.delete(cnx, formsemestre_id)
|
||||
db.session.delete(formsemestre)
|
||||
|
||||
# news
|
||||
ScolarNews.add(
|
||||
typ=ScolarNews.NEWS_SEM,
|
||||
obj=formsemestre_id,
|
||||
text="Suppression du semestre %(titre)s" % sem,
|
||||
text=f"Suppression du semestre {titre_sem}",
|
||||
max_frequency=0,
|
||||
)
|
||||
|
||||
|
@ -91,7 +91,9 @@ def do_moduleimpl_delete(oid, formsemestre_id=None):
|
||||
) # > moduleimpl_delete
|
||||
|
||||
|
||||
def moduleimpl_list(moduleimpl_id=None, formsemestre_id=None, module_id=None):
|
||||
def moduleimpl_list(
|
||||
moduleimpl_id=None, formsemestre_id=None, module_id=None
|
||||
) -> list[dict]:
|
||||
"list moduleimpls"
|
||||
args = locals()
|
||||
cnx = ndb.GetDBConnexion()
|
||||
|
@ -48,20 +48,17 @@ from wtforms import (
|
||||
HiddenField,
|
||||
SelectMultipleField,
|
||||
)
|
||||
from app.models import ModuleImpl
|
||||
from app.models import Evaluation, ModuleImpl
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app import ScoValueError
|
||||
from app.scodoc import html_sco_header, sco_preferences
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_evaluations
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_excel
|
||||
from app.scodoc.sco_excel import ScoExcelBook, COLORS
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_moduleimpl
|
||||
from app.scodoc import sco_permissions_check
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc import sco_etud
|
||||
import sco_version
|
||||
@ -138,11 +135,7 @@ class PlacementForm(FlaskForm):
|
||||
|
||||
def set_evaluation_infos(self, evaluation_id):
|
||||
"""Initialise les données du formulaire avec les données de l'évaluation."""
|
||||
eval_data = sco_evaluation_db.get_evaluations_dict(
|
||||
{"evaluation_id": evaluation_id}
|
||||
)
|
||||
if not eval_data:
|
||||
raise ScoValueError("invalid evaluation_id")
|
||||
_ = Evaluation.get_evaluation(evaluation_id) # check exist ?
|
||||
self.groups_tree, self.has_groups, self.nb_groups = _get_group_info(
|
||||
evaluation_id
|
||||
)
|
||||
@ -239,14 +232,12 @@ class PlacementRunner:
|
||||
self.groups_ids = [
|
||||
gid if gid != TOUS else form.tous_id for gid in form["groups"].data
|
||||
]
|
||||
self.eval_data = sco_evaluation_db.get_evaluations_dict(
|
||||
{"evaluation_id": self.evaluation_id}
|
||||
)[0]
|
||||
self.evaluation = Evaluation.get_evaluation(self.evaluation_id)
|
||||
self.groups = sco_groups.listgroups(self.groups_ids)
|
||||
self.gr_title_filename = sco_groups.listgroups_filename(self.groups)
|
||||
# gr_title = sco_groups.listgroups_abbrev(d['groups'])
|
||||
self.current_user = current_user
|
||||
self.moduleimpl_id = self.eval_data["moduleimpl_id"]
|
||||
self.moduleimpl_id = self.evaluation.moduleimpl_id
|
||||
self.moduleimpl: ModuleImpl = ModuleImpl.query.get_or_404(self.moduleimpl_id)
|
||||
# TODO: à revoir pour utiliser modèle ModuleImpl
|
||||
self.moduleimpl_data = sco_moduleimpl.moduleimpl_list(
|
||||
@ -260,20 +251,25 @@ class PlacementRunner:
|
||||
)
|
||||
self.evalname = "%s-%s" % (
|
||||
self.module_data["code"] or "?",
|
||||
ndb.DateDMYtoISO(self.eval_data["jour"]),
|
||||
(
|
||||
self.evaluation.date_debut.strftime("%Y-%m-%d_%Hh%M")
|
||||
if self.evaluation.date_debut
|
||||
else ""
|
||||
),
|
||||
)
|
||||
if self.eval_data["description"]:
|
||||
self.evaltitre = self.eval_data["description"]
|
||||
if self.evaluation.description:
|
||||
self.evaltitre = self.evaluation.description
|
||||
else:
|
||||
self.evaltitre = "évaluation du %s" % self.eval_data["jour"]
|
||||
self.evaltitre = f"""évaluation{
|
||||
self.evaluation.date_debut.strftime(' du %d/%m/%Y à %Hh%M')
|
||||
if self.evaluation.date_debut else ''}"""
|
||||
self.desceval = [ # une liste de chaines: description de l'evaluation
|
||||
"%s" % self.sem["titreannee"],
|
||||
self.sem["titreannee"],
|
||||
"Module : %s - %s"
|
||||
% (self.module_data["code"] or "?", self.module_data["abbrev"] or ""),
|
||||
"Surveillants : %s" % self.surveillants,
|
||||
"Batiment : %(batiment)s - Salle : %(salle)s" % self.__dict__,
|
||||
"Controle : %s (coef. %g)"
|
||||
% (self.evaltitre, self.eval_data["coefficient"]),
|
||||
"Controle : %s (coef. %g)" % (self.evaltitre, self.evaluation.coefficient),
|
||||
]
|
||||
self.styles = None
|
||||
self.plan = None
|
||||
@ -339,10 +335,10 @@ class PlacementRunner:
|
||||
|
||||
def _production_pdf(self):
|
||||
pdf_title = "<br>".join(self.desceval)
|
||||
pdf_title += (
|
||||
"\nDate : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s"
|
||||
% self.eval_data
|
||||
)
|
||||
pdf_title += f"""\nDate : {self.evaluation.date_debut.strftime("%d/%m/%Y")
|
||||
if self.evaluation.date_debut else '-'
|
||||
} - Horaire : {self.evaluation.heure_debut()} à {self.evaluation.heure_fin()
|
||||
}"""
|
||||
filename = "placement_%(evalname)s_%(gr_title_filename)s" % self.__dict__
|
||||
titles = {
|
||||
"nom": "Nom",
|
||||
@ -489,8 +485,10 @@ class PlacementRunner:
|
||||
worksheet.append_blank_row()
|
||||
worksheet.append_single_cell_row(desceval, self.styles["titres"])
|
||||
worksheet.append_single_cell_row(
|
||||
"Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s"
|
||||
% self.eval_data,
|
||||
f"""Date : {self.evaluation.date_debut.strftime("%d/%m/%Y")
|
||||
if self.evaluation.date_debut else '-'
|
||||
} - Horaire : {self.evaluation.heure_debut()} à {self.evaluation.heure_fin()
|
||||
}""",
|
||||
self.styles["titres"],
|
||||
)
|
||||
|
||||
|
@ -48,16 +48,15 @@ Opérations:
|
||||
import datetime
|
||||
from flask import request
|
||||
|
||||
from app.models import FormSemestre
|
||||
from app.models import Evaluation, FormSemestre
|
||||
from app.scodoc.intervals import intervalmap
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_moduleimpl
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_users
|
||||
import sco_version
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
import sco_version
|
||||
|
||||
# deux notes (de même uid) sont considérées comme de la même opération si
|
||||
# elles sont séparées de moins de 2*tolerance:
|
||||
@ -149,10 +148,8 @@ def list_operations(evaluation_id):
|
||||
|
||||
def evaluation_list_operations(evaluation_id):
|
||||
"""Page listing operations on evaluation"""
|
||||
E = sco_evaluation_db.get_evaluations_dict({"evaluation_id": evaluation_id})[0]
|
||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
||||
|
||||
Ops = list_operations(evaluation_id)
|
||||
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
operations = list_operations(evaluation_id)
|
||||
|
||||
columns_ids = ("datestr", "user_name", "nb_notes", "comment")
|
||||
titles = {
|
||||
@ -164,11 +161,14 @@ def evaluation_list_operations(evaluation_id):
|
||||
tab = GenTable(
|
||||
titles=titles,
|
||||
columns_ids=columns_ids,
|
||||
rows=Ops,
|
||||
rows=operations,
|
||||
html_sortable=False,
|
||||
html_title="<h2>Opérations sur l'évaluation %s du %s</h2>"
|
||||
% (E["description"], E["jour"]),
|
||||
preferences=sco_preferences.SemPreferences(M["formsemestre_id"]),
|
||||
html_title=f"""<h2>Opérations sur l'évaluation {evaluation.description} {
|
||||
evaluation.date_debut.strftime("du %d/%m/%Y") if evaluation.date_debut else "(sans date)"
|
||||
}</h2>""",
|
||||
preferences=sco_preferences.SemPreferences(
|
||||
evaluation.moduleimpl.formsemestre_id
|
||||
),
|
||||
)
|
||||
return tab.make_page()
|
||||
|
||||
|
@ -13,7 +13,7 @@ Au besoin, créer un base de test neuve:
|
||||
"""
|
||||
import datetime
|
||||
|
||||
from app.models import FormSemestreInscription, Identite
|
||||
from app.models import Evaluation, FormSemestreInscription, Identite, ModuleImpl
|
||||
|
||||
from config import TestConfig
|
||||
from tests.unit import sco_fake_gen
|
||||
@ -29,7 +29,6 @@ from app.scodoc import sco_bulletins
|
||||
from app.scodoc import codes_cursus
|
||||
from app.scodoc import sco_assiduites as scass
|
||||
from app.scodoc import sco_evaluations
|
||||
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
|
||||
@ -81,7 +80,7 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
module_id=module_id,
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
|
||||
moduleimpl: ModuleImpl = db.session.get(ModuleImpl, moduleimpl_id)
|
||||
# --- Inscription des étudiants
|
||||
for etud in etuds:
|
||||
G.inscrit_etudiant(formsemestre_id, etud)
|
||||
@ -97,17 +96,18 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
assert ins.parcour is None
|
||||
|
||||
# --- Création évaluation
|
||||
e = G.create_evaluation(
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
e1 = Evaluation.create(
|
||||
moduleimpl=moduleimpl,
|
||||
date_debut=datetime.datetime(2020, 1, 1),
|
||||
description="evaluation test",
|
||||
coefficient=1.0,
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
# --- Saisie toutes les notes de l'évaluation
|
||||
for idx, etud in enumerate(etuds):
|
||||
etudids_changed, nb_suppress, existing_decisions = G.create_note(
|
||||
evaluation_id=e["evaluation_id"],
|
||||
evaluation_id=e1.id,
|
||||
etudid=etud["etudid"],
|
||||
note=NOTES_T[idx % len(NOTES_T)],
|
||||
)
|
||||
@ -118,7 +118,7 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
# --- Vérifie que les notes sont prises en compte:
|
||||
b = sco_bulletins.formsemestre_bulletinetud_dict(formsemestre_id, etud["etudid"])
|
||||
# Toute les notes sont saisies, donc eval complète
|
||||
etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
|
||||
etat = sco_evaluations.do_evaluation_etat(e1.id)
|
||||
assert etat["evalcomplete"]
|
||||
assert etat["nb_inscrits"] == len(etuds)
|
||||
assert etat["nb_notes"] == len(etuds)
|
||||
@ -131,30 +131,32 @@ def run_sco_basic(verbose=False, dept=None) -> FormSemestre:
|
||||
)
|
||||
|
||||
# --- Une autre évaluation
|
||||
e2 = G.create_evaluation(
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
e2 = Evaluation.create(
|
||||
moduleimpl=moduleimpl,
|
||||
date_debut=datetime.datetime(2020, 1, 2),
|
||||
description="evaluation test 2",
|
||||
coefficient=1.0,
|
||||
)
|
||||
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(
|
||||
evaluation_id=e2["evaluation_id"],
|
||||
evaluation_id=e2.id,
|
||||
etudid=etud["etudid"],
|
||||
note=NOTES_T[idx % len(NOTES_T)],
|
||||
)
|
||||
# Cette éval n'est pas complète
|
||||
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
|
||||
etat = sco_evaluations.do_evaluation_etat(e2.id)
|
||||
assert etat["evalcomplete"] is False
|
||||
# la première éval est toujours complète:
|
||||
etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
|
||||
etat = sco_evaluations.do_evaluation_etat(e1.id)
|
||||
assert etat["evalcomplete"]
|
||||
|
||||
# Modifie l'évaluation 2 pour "prise en compte immédiate"
|
||||
e2["publish_incomplete"] = True
|
||||
sco_evaluation_db.do_evaluation_edit(e2)
|
||||
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
|
||||
e2.publish_incomplete = True
|
||||
db.session.add(e2)
|
||||
db.session.flush()
|
||||
etat = sco_evaluations.do_evaluation_etat(e2.id)
|
||||
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)
|
||||
@ -162,26 +164,26 @@ 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(
|
||||
evaluation_id=e2["evaluation_id"],
|
||||
evaluation_id=e2.id,
|
||||
etudid=etud["etudid"],
|
||||
note=NOTES_T[idx % len(NOTES_T)],
|
||||
)
|
||||
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
|
||||
etat = sco_evaluations.do_evaluation_etat(e2.id)
|
||||
assert etat["evalcomplete"]
|
||||
assert etat["nb_att"] == 0
|
||||
assert not etat["evalattente"] # toutes les notes sont présentes
|
||||
|
||||
# --- Suppression des notes
|
||||
sco_saisie_notes.evaluation_suppress_alln(e["evaluation_id"], dialog_confirmed=True)
|
||||
etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
|
||||
sco_saisie_notes.evaluation_suppress_alln(e1.id, dialog_confirmed=True)
|
||||
etat = sco_evaluations.do_evaluation_etat(e1.id)
|
||||
assert etat["nb_notes"] == 0
|
||||
assert not etat["evalcomplete"]
|
||||
# --- Saisie des notes manquantes
|
||||
ans = sco_saisie_notes.do_evaluation_set_missing(
|
||||
e["evaluation_id"], 12.34, dialog_confirmed=True
|
||||
e1.id, 12.34, dialog_confirmed=True
|
||||
)
|
||||
assert f'{etat["nb_inscrits"]} notes changées' in ans
|
||||
etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
|
||||
etat = sco_evaluations.do_evaluation_etat(e1.id)
|
||||
assert etat["evalcomplete"]
|
||||
|
||||
# -----------------------
|
||||
|
Loading…
Reference in New Issue
Block a user