1
0
forked from ScoDoc/ScoDoc

Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into bul_but

This commit is contained in:
Emmanuel Viennet 2023-08-30 15:59:18 +02:00
commit 2227c85250
11 changed files with 188 additions and 179 deletions

View File

@ -273,5 +273,5 @@ def evaluation_delete(evaluation_id: int):
sco_saisie_notes.evaluation_suppress_alln( sco_saisie_notes.evaluation_suppress_alln(
evaluation_id=evaluation_id, dialog_confirmed=True evaluation_id=evaluation_id, dialog_confirmed=True
) )
sco_evaluation_db.do_evaluation_delete(evaluation_id) evaluation.delete()
return "ok" return "ok"

View File

@ -141,6 +141,44 @@ class Evaluation(db.Model):
n = 0 # the only one n = 0 # the only one
return n return n
def delete(self):
"delete evaluation (commit) (check permission)"
from app.scodoc import sco_evaluation_db
modimpl: ModuleImpl = self.moduleimpl
if not modimpl.can_edit_evaluation(current_user):
raise AccessDenied(
f"Modification évaluation impossible pour {current_user.get_nomplogin()}"
)
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
self.id
) # { etudid : value }
notes = [x["value"] for x in notes_db.values()]
if notes:
raise ScoValueError(
"Impossible de supprimer cette évaluation: il reste des notes"
)
log(f"deleting evaluation {self}")
db.session.delete(self)
db.session.commit()
# inval cache pour ce semestre
sco_cache.invalidate_formsemestre(formsemestre_id=modimpl.formsemestre_id)
# news
url = url_for(
"notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept,
moduleimpl_id=modimpl.id,
)
ScolarNews.add(
typ=ScolarNews.NEWS_NOTE,
obj=modimpl.id,
text=f"""Suppression d'une évaluation dans <a href="{
url
}">{modimpl.module.titre}</a>""",
url=url,
)
def to_dict(self) -> dict: def to_dict(self) -> dict:
"Représentation dict (riche, compat ScoDoc 7)" "Représentation dict (riche, compat ScoDoc 7)"
e_dict = dict(self.__dict__) e_dict = dict(self.__dict__)

View File

@ -118,6 +118,32 @@ class ModuleImpl(db.Model):
return False return False
def can_edit_notes(self, user: "User", allow_ens=True) -> bool:
"""True if authuser can enter or edit notes in this module.
If allow_ens, grant access to all ens in this module
Si des décisions de jury ont déjà été saisies dans ce semestre,
seul le directeur des études peut saisir des notes (et il ne devrait pas).
"""
# was sco_permissions_check.can_edit_notes
from app.scodoc import sco_cursus_dut
if not self.formsemestre.etat:
return False # semestre verrouillé
is_dir_etud = user.id in (u.id for u in self.formsemestre.responsables)
can_edit_all_notes = user.has_permission(Permission.ScoEditAllNotes)
if sco_cursus_dut.formsemestre_has_decisions(self.formsemestre_id):
# il y a des décisions de jury dans ce semestre !
return can_edit_all_notes or is_dir_etud
if (
not can_edit_all_notes
and user.id != self.responsable_id
and not is_dir_etud
):
# enseignant (chargé de TD) ?
return allow_ens and user.id in (ens.id for ens in self.enseignants)
return True
def can_change_ens_by(self, user: User, raise_exc=False) -> bool: def can_change_ens_by(self, user: User, raise_exc=False) -> bool:
"""Check if user can modify module resp. """Check if user can modify module resp.
If raise_exc, raises exception (AccessDenied or ScoLockedSemError) if not. If raise_exc, raises exception (AccessDenied or ScoLockedSemError) if not.

View File

@ -28,19 +28,17 @@
"""Gestion évaluations (ScoDoc7, code en voie de modernisation) """Gestion évaluations (ScoDoc7, code en voie de modernisation)
""" """
import pprint
import flask import flask
from flask import url_for, g from flask import url_for, g
from flask_login import current_user from flask_login import current_user
from app import db, log from app import db, log
from app.models import Evaluation, ModuleImpl, ScolarNews from app.models import Evaluation
from app.models.evaluations import check_convert_evaluation_args from app.models.evaluations import check_convert_evaluation_args
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError from app.scodoc.sco_exceptions import AccessDenied
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_moduleimpl from app.scodoc import sco_moduleimpl
@ -119,42 +117,6 @@ def do_evaluation_edit(args):
) )
def do_evaluation_delete(evaluation_id):
"delete evaluation"
evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
modimpl: ModuleImpl = evaluation.moduleimpl
if not modimpl.can_edit_evaluation(current_user):
raise AccessDenied(
f"Modification évaluation impossible pour {current_user.get_nomplogin()}"
)
notes_db = do_evaluation_get_all_notes(evaluation_id) # { etudid : value }
notes = [x["value"] for x in notes_db.values()]
if notes:
raise ScoValueError(
"Impossible de supprimer cette évaluation: il reste des notes"
)
log(f"deleting evaluation {evaluation}")
db.session.delete(evaluation)
db.session.commit()
# inval cache pour ce semestre
sco_cache.invalidate_formsemestre(formsemestre_id=modimpl.formsemestre_id)
# news
url = url_for(
"notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept,
moduleimpl_id=modimpl.id,
)
ScolarNews.add(
typ=ScolarNews.NEWS_NOTE,
obj=modimpl.id,
text=f"""Suppression d'une évaluation dans <a href="{
url
}">{modimpl.module.titre}</a>""",
url=url,
)
# ancien _notes_getall # ancien _notes_getall
def do_evaluation_get_all_notes( def do_evaluation_get_all_notes(
evaluation_id, table="notes_notes", filter_suppressed=True, by_uid=None evaluation_id, table="notes_notes", filter_suppressed=True, by_uid=None

View File

@ -30,16 +30,17 @@
import collections import collections
import datetime import datetime
import operator import operator
import time
from flask import url_for from flask import url_for
from flask import g from flask import g
from flask_login import current_user from flask_login import current_user
from flask import request from flask import request
from app import db
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 FormSemestre from app.models import Evaluation, FormSemestre
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
@ -645,78 +646,64 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True):
"""HTML description of evaluation, for page headers """HTML description of evaluation, for page headers
edit_in_place: allow in-place editing when permitted (not implemented) edit_in_place: allow in-place editing when permitted (not implemented)
""" """
E = sco_evaluation_db.get_evaluation_dict({"evaluation_id": evaluation_id})[0] evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
moduleimpl_id = E["moduleimpl_id"] modimpl = evaluation.moduleimpl
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] responsable: User = db.session.get(User, modimpl.responsable_id)
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0] resp_nomprenom = responsable.get_prenomnom()
formsemestre_id = M["formsemestre_id"] resp_nomcomplet = responsable.get_nomcomplet()
u = sco_users.user_info(M["responsable_id"]) can_edit = modimpl.can_edit_notes(current_user, allow_ens=False)
resp = u["prenomnom"]
nomcomplet = u["nomcomplet"]
can_edit = sco_permissions_check.can_edit_notes(
current_user, moduleimpl_id, allow_ens=False
)
link = ( mod_descr = f"""<a class="stdlink" href="{url_for("notes.moduleimpl_status",
'<span class="evallink"><a class="stdlink" href="evaluation_listenotes?moduleimpl_id=%s">voir toutes les notes du module</a></span>' scodoc_dept=g.scodoc_dept,
% moduleimpl_id moduleimpl_id=modimpl.id,
) )}">{modimpl.module.code or ""} {modimpl.module.abbrev or modimpl.module.titre or "?"}</a>
mod_descr = ( <span class="resp">(resp. <a title="{resp_nomcomplet}">{resp_nomprenom}</a>)</span>
'<a href="moduleimpl_status?moduleimpl_id=%s">%s %s</a> <span class="resp">(resp. <a title="%s">%s</a>)</span> %s' <span class="evallink"><a class="stdlink"
% ( href="{url_for(
moduleimpl_id, "notes.evaluation_listenotes",
Mod["code"] or "", scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
Mod["titre"] or "?", }">voir toutes les notes du module</a></span>
nomcomplet, """
resp,
link,
)
)
etit = E["description"] or "" eval_titre = f' "{evaluation.description}"' if evaluation.description else ""
if etit: if modimpl.module.module_type == ModuleType.MALUS:
etit = ' "' + etit + '"' eval_titre += ' <span class="eval_malus">(points de malus)</span>'
if Mod["module_type"] == ModuleType.MALUS:
etit += ' <span class="eval_malus">(points de malus)</span>'
H = [ H = [
'<span class="eval_title">Évaluation%s</span><p><b>Module : %s</b></p>' f"""<span class="eval_title">Évaluation{eval_titre}</span>
% (etit, mod_descr) <p><b>Module : {mod_descr}</b>
</p>"""
] ]
if Mod["module_type"] == ModuleType.MALUS: if modimpl.module.module_type == ModuleType.MALUS:
# Indique l'UE # Indique l'UE
ue = sco_edit_ue.ue_list(args={"ue_id": Mod["ue_id"]})[0] ue = modimpl.module.ue
H.append("<p><b>UE : %(acronyme)s</b></p>" % ue) H.append(f"<p><b>UE : {ue.acronyme}</b></p>")
# store min/max values used by JS client-side checks: # store min/max values used by JS client-side checks:
H.append( H.append(
'<span id="eval_note_min" class="sco-hidden">-20.</span><span id="eval_note_max" class="sco-hidden">20.</span>' """<span id="eval_note_min" class="sco-hidden">-20.</span>
<span id="eval_note_max" class="sco-hidden">20.</span>"""
) )
else: else:
# date et absences (pas pour evals de malus) # date et absences (pas pour evals de malus)
if E["jour"]: if evaluation.date_debut is not None:
jour = E["jour"] H.append(f"<p>Réalisée le <b>{evaluation.descr_date()}</b> ")
H.append("<p>Réalisée le <b>%s</b> " % (jour)) group_id = sco_groups.get_default_group(modimpl.formsemestre_id)
if E["heure_debut"] != E["heure_fin"]:
H.append("de %s à %s " % (E["heure_debut"], E["heure_fin"]))
group_id = sco_groups.get_default_group(formsemestre_id)
H.append( H.append(
f"""<span class="noprint"><a href="{url_for( f"""<span class="evallink"><a class="stdlink" href="{url_for(
'assiduites.get_etat_abs_date', 'assiduites.etat_abs_date',
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
group_ids=group_id, group_ids=group_id,
desc=E["description"], desc=evaluation.description or "",
jour=E["jour"], date_debut=evaluation.date_debut.isoformat(),
heure_debut=E["heure_debut"], date_fin=evaluation.date_fin.isoformat(),
heure_fin=E["heure_fin"],
) )
}">(absences ce jour)</a></span>""" }">absences ce jour</a></span>"""
) )
else: else:
jour = "<em>pas de date</em>" H.append("<p><em>sans date</em> ")
H.append("<p>Réalisée le <b>%s</b> " % (jour))
H.append( H.append(
'</p><p>Coefficient dans le module: <b>%s</b>, notes sur <span id="eval_note_max">%g</span> ' f"""</p><p>Coefficient dans le module: <b>{evaluation.coefficient or "0"}</b>,
% (E["coefficient"], E["note_max"]) notes sur <span id="eval_note_max">{(evaluation.note_max or 0):g}</span> """
) )
H.append('<span id="eval_note_min" class="sco-hidden">0.</span>') H.append('<span id="eval_note_min" class="sco-hidden">0.</span>')
if can_edit: if can_edit:
@ -730,7 +717,7 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True):
if link_saisie: if link_saisie:
H.append( H.append(
f""" f"""
<a class="stdlink" href="{url_for( <a style="margin-left: 12px;" class="stdlink" href="{url_for(
"notes.saisie_notes", scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id) "notes.saisie_notes", scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)
}">saisie des notes</a> }">saisie des notes</a>
""" """

View File

@ -50,7 +50,6 @@ from app.scodoc import htmlutils
from app.scodoc import sco_cal from app.scodoc import sco_cal
from app.scodoc import sco_compute_moy from app.scodoc import sco_compute_moy
from app.scodoc import sco_evaluations from app.scodoc import sco_evaluations
from app.scodoc import sco_evaluation_db
from app.scodoc import sco_formsemestre_status from app.scodoc import sco_formsemestre_status
from app.scodoc import sco_groups from app.scodoc import sco_groups
from app.scodoc import sco_moduleimpl from app.scodoc import sco_moduleimpl
@ -59,19 +58,15 @@ from app.tables import list_etuds
# menu evaluation dans moduleimpl # menu evaluation dans moduleimpl
def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str: def moduleimpl_evaluation_menu(evaluation: Evaluation, nbnotes: int = 0) -> str:
"Menu avec actions sur une evaluation" "Menu avec actions sur une evaluation"
E = sco_evaluation_db.get_evaluation_dict({"evaluation_id": evaluation_id})[0] modimpl: ModuleImpl = evaluation.moduleimpl
modimpl = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] group_id = sco_groups.get_default_group(modimpl.formsemestre_id)
evaluation_id = evaluation.id
can_edit_notes = modimpl.can_edit_notes(current_user, allow_ens=False)
can_edit_notes_ens = modimpl.can_edit_notes(current_user)
group_id = sco_groups.get_default_group(modimpl["formsemestre_id"]) if can_edit_notes and nbnotes != 0:
if (
sco_permissions_check.can_edit_notes(
current_user, E["moduleimpl_id"], allow_ens=False
)
and nbnotes != 0
):
sup_label = "Supprimer évaluation impossible (il y a des notes)" sup_label = "Supprimer évaluation impossible (il y a des notes)"
else: else:
sup_label = "Supprimer évaluation" sup_label = "Supprimer évaluation"
@ -83,9 +78,7 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
"args": { "args": {
"evaluation_id": evaluation_id, "evaluation_id": evaluation_id,
}, },
"enabled": sco_permissions_check.can_edit_notes( "enabled": can_edit_notes_ens,
current_user, E["moduleimpl_id"]
),
}, },
{ {
"title": "Modifier évaluation", "title": "Modifier évaluation",
@ -93,9 +86,7 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
"args": { "args": {
"evaluation_id": evaluation_id, "evaluation_id": evaluation_id,
}, },
"enabled": sco_permissions_check.can_edit_notes( "enabled": can_edit_notes,
current_user, E["moduleimpl_id"], allow_ens=False
),
}, },
{ {
"title": sup_label, "title": sup_label,
@ -103,10 +94,7 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
"args": { "args": {
"evaluation_id": evaluation_id, "evaluation_id": evaluation_id,
}, },
"enabled": nbnotes == 0 "enabled": nbnotes == 0 and can_edit_notes,
and sco_permissions_check.can_edit_notes(
current_user, E["moduleimpl_id"], allow_ens=False
),
}, },
{ {
"title": "Supprimer toutes les notes", "title": "Supprimer toutes les notes",
@ -114,9 +102,7 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
"args": { "args": {
"evaluation_id": evaluation_id, "evaluation_id": evaluation_id,
}, },
"enabled": sco_permissions_check.can_edit_notes( "enabled": can_edit_notes,
current_user, E["moduleimpl_id"], allow_ens=False
),
}, },
{ {
"title": "Afficher les notes", "title": "Afficher les notes",
@ -132,21 +118,18 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
"args": { "args": {
"evaluation_id": evaluation_id, "evaluation_id": evaluation_id,
}, },
"enabled": sco_permissions_check.can_edit_notes( "enabled": can_edit_notes_ens,
current_user, E["moduleimpl_id"]
),
}, },
{ {
"title": "Absences ce jour", "title": "Absences ce jour",
"endpoint": "assiduites.get_etat_abs_date", "endpoint": "assiduites.etat_abs_date",
"args": { "args": {
"group_ids": group_id, "group_ids": group_id,
"desc": E["description"], "desc": evaluation.description or "",
"jour": E["jour"], "date_debut": evaluation.date_debut.isoformat(),
"heure_debut": E["heure_debut"], "date_fin": evaluation.date_fin.isoformat(),
"heure_fin": E["heure_fin"],
}, },
"enabled": E["jour"], "enabled": evaluation.date_debut is not None,
}, },
{ {
"title": "Vérifier notes vs absents", "title": "Vérifier notes vs absents",
@ -154,7 +137,7 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
"args": { "args": {
"evaluation_id": evaluation_id, "evaluation_id": evaluation_id,
}, },
"enabled": nbnotes > 0 and E["jour"], "enabled": nbnotes > 0 and evaluation.date_debut is not None,
}, },
] ]
@ -714,7 +697,7 @@ def _ligne_evaluation(
if can_edit_notes: if can_edit_notes:
H.append( H.append(
moduleimpl_evaluation_menu( moduleimpl_evaluation_menu(
evaluation.id, evaluation,
nbnotes=etat["nb_notes"], nbnotes=etat["nb_notes"],
) )
) )

View File

@ -1315,7 +1315,7 @@ a.smallbutton {
} }
span.evallink { span.evallink {
font-size: 80%; margin-left: 16px;
font-weight: normal; font-weight: normal;
} }

View File

@ -1,8 +1,8 @@
import datetime import datetime
from flask import g, request, render_template from flask import g, request, render_template
from flask import abort, url_for from flask import abort, url_for
from flask_login import current_user
from app import db from app import db
from app.comp import res_sem from app.comp import res_sem
@ -25,14 +25,16 @@ from app.views import ScoData
# --------------- # ---------------
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import safehtml
from app.scodoc import sco_moduleimpl from app.scodoc import sco_moduleimpl
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_groups_view from app.scodoc import sco_groups_view
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_find_etud from app.scodoc import sco_find_etud
from flask_login import current_user
from app.scodoc import sco_utils as scu
from app.scodoc import sco_assiduites as scass from app.scodoc import sco_assiduites as scass
from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import ScoValueError
from app.tables.visu_assiduites import TableAssi, etuds_sorted_from_ids from app.tables.visu_assiduites import TableAssi, etuds_sorted_from_ids
@ -731,17 +733,23 @@ def visu_assiduites_group():
).build() ).build()
@bp.route("/EtatAbsencesDate") @bp.route("/etat_abs_date")
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
def get_etat_abs_date(): def etat_abs_date():
infos_date = { """date_debut, date_fin en ISO"""
"jour": request.args.get("jour"), date_debut_str = request.args.get("date_debut")
"heure_debut": request.args.get("heure_debut"), date_fin_str = request.args.get("date_fin")
"heure_fin": request.args.get("heure_fin"), title = request.args.get("desc")
"title": request.args.get("desc"),
}
group_ids: list[int] = request.args.get("group_ids", None) group_ids: list[int] = request.args.get("group_ids", None)
try:
date_debut = datetime.datetime.fromisoformat(date_debut_str)
except ValueError as exc:
raise ScoValueError("date_debut invalide") from exc
try:
date_fin = datetime.datetime.fromisoformat(date_fin_str)
except ValueError as exc:
raise ScoValueError("date_fin invalide") from exc
if group_ids is None: if group_ids is None:
group_ids = [] group_ids = []
else: else:
@ -754,14 +762,6 @@ def get_etat_abs_date():
sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0] sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
for m in groups_infos.members for m in groups_infos.members
] ]
date_debut = scu.is_iso_formated(
f"{infos_date['jour']}T{infos_date['heure_debut'].replace('h',':')}", True
)
date_fin = scu.is_iso_formated(
f"{infos_date['jour']}T{infos_date['heure_fin'].replace('h',':')}", True
)
assiduites: Assiduite = Assiduite.query.filter( assiduites: Assiduite = Assiduite.query.filter(
Assiduite.etudid.in_([e["etudid"] for e in etuds]) Assiduite.etudid.in_([e["etudid"] for e in etuds])
) )
@ -791,7 +791,7 @@ def get_etat_abs_date():
etudiants = list(sorted(etudiants, key=lambda x: x["nom"])) etudiants = list(sorted(etudiants, key=lambda x: x["nom"]))
header: str = html_sco_header.sco_header( header: str = html_sco_header.sco_header(
page_title=infos_date["title"], page_title=safehtml.html_to_safe_html(title),
init_qtip=True, init_qtip=True,
) )

View File

@ -1656,30 +1656,37 @@ sco_publish(
@scodoc7func @scodoc7func
def evaluation_delete(evaluation_id): def evaluation_delete(evaluation_id):
"""Form delete evaluation""" """Form delete evaluation"""
El = sco_evaluation_db.get_evaluation_dict(args={"evaluation_id": evaluation_id}) evaluation: Evaluation = (
if not El: Evaluation.query.filter_by(id=evaluation_id)
raise ScoValueError("Evaluation inexistante ! (%s)" % evaluation_id) .join(ModuleImpl)
E = El[0] .join(FormSemestre)
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] .filter_by(dept_id=g.scodoc_dept_id)
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0] .first_or_404()
tit = "Suppression de l'évaluation %(description)s (%(jour)s)" % E )
etat = sco_evaluations.do_evaluation_etat(evaluation_id)
tit = f"""Suppression de l'évaluation {evaluation.description or ""} ({evaluation.descr_date()})"""
etat = sco_evaluations.do_evaluation_etat(evaluation.id)
H = [ H = [
html_sco_header.html_sem_header(tit, with_h2=False), f"""
"""<h2 class="formsemestre">Module <tt>%(code)s</tt> %(titre)s</h2>""" % Mod, {html_sco_header.html_sem_header(tit, with_h2=False)}
"""<h3>%s</h3>""" % tit, <h2 class="formsemestre">Module <tt>{evaluation.moduleimpl.module.code}</tt>
"""<p class="help">Opération <span class="redboldtext">irréversible</span>. Si vous supprimez l'évaluation, vous ne pourrez pas retrouver les notes associées.</p>""", {evaluation.moduleimpl.module.titre_str()}</h2>
<h3>{tit}</h3>
<p class="help">Opération <span class="redboldtext">irréversible</span>.
Si vous supprimez l'évaluation, vous ne pourrez pas retrouver les notes associées.
</p>
""",
] ]
warning = False warning = False
if etat["nb_notes_total"]: if etat["nb_notes_total"]:
warning = True warning = True
nb_desinscrits = etat["nb_notes_total"] - etat["nb_notes"] nb_desinscrits = etat["nb_notes_total"] - etat["nb_notes"]
H.append( H.append(
"""<div class="ue_warning"><span>Il y a %s notes""" % etat["nb_notes_total"] f"""<div class="ue_warning"><span>Il y a {etat["nb_notes_total"]} notes"""
) )
if nb_desinscrits: if nb_desinscrits:
H.append( H.append(
""" (dont %s d'étudiants qui ne sont plus inscrits)""" % nb_desinscrits """ (dont {nb_desinscrits} d'étudiants qui ne sont plus inscrits)"""
) )
H.append(""" dans l'évaluation</span>""") H.append(""" dans l'évaluation</span>""")
if etat["nb_notes"] == 0: if etat["nb_notes"] == 0:
@ -1689,8 +1696,13 @@ def evaluation_delete(evaluation_id):
if etat["nb_notes"]: if etat["nb_notes"]:
H.append( H.append(
"""<p>Suppression impossible (effacer les notes d'abord)</p><p><a class="stdlink" href="moduleimpl_status?moduleimpl_id=%s">retour au tableau de bord du module</a></p></div>""" f"""<p>Suppression impossible (effacer les notes d'abord)</p>
% E["moduleimpl_id"] <p><a class="stdlink" href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=evaluation.moduleimpl_id)
}">retour au tableau de bord du module</a>
</p>
</div>"""
) )
return "\n".join(H) + html_sco_header.sco_footer() return "\n".join(H) + html_sco_header.sco_footer()
if warning: if warning:
@ -1700,7 +1712,7 @@ def evaluation_delete(evaluation_id):
request.base_url, request.base_url,
scu.get_request_args(), scu.get_request_args(),
(("evaluation_id", {"input_type": "hidden"}),), (("evaluation_id", {"input_type": "hidden"}),),
initvalues=E, initvalues={"evaluation_id": evaluation.id},
submitlabel="Confirmer la suppression", submitlabel="Confirmer la suppression",
cancelbutton="Annuler", cancelbutton="Annuler",
) )
@ -1711,17 +1723,17 @@ def evaluation_delete(evaluation_id):
url_for( 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,
) )
) )
else: else:
sco_evaluation_db.do_evaluation_delete(E["evaluation_id"]) evaluation.delete()
return ( return (
"\n".join(H) "\n".join(H)
+ f"""<p>OK, évaluation supprimée.</p> + f"""<p>OK, évaluation supprimée.</p>
<p><a class="stdlink" href="{ <p><a class="stdlink" href="{
url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, url_for("notes.moduleimpl_status", scodoc_dept=g.scodoc_dept,
moduleimpl_id=E["moduleimpl_id"]) moduleimpl_id=evaluation.moduleimpl_id)
}">Continuer</a></p>""" }">Continuer</a></p>"""
+ html_sco_header.sco_footer() + html_sco_header.sco_footer()
) )

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "9.6.15" SCOVERSION = "9.6.16"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"

View File

@ -6,10 +6,9 @@ import app
from app import db from app import db
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
from app.models import FormSemestre, ModuleImpl from app.models import Evaluation, FormSemestre, ModuleImpl
from app.scodoc import ( from app.scodoc import (
sco_bulletins, sco_bulletins,
sco_evaluation_db,
sco_formsemestre, sco_formsemestre,
sco_saisie_notes, sco_saisie_notes,
) )
@ -131,7 +130,9 @@ def test_notes_rattrapage(test_client):
# Note moyenne: reviens à 10/20 # Note moyenne: reviens à 10/20
assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(10.0) assert b["ues"][0]["modules"][0]["mod_moy_txt"] == scu.fmt_note(10.0)
# Supprime l'évaluation de rattrapage: # Supprime l'évaluation de rattrapage:
sco_evaluation_db.do_evaluation_delete(e_rat["id"]) evaluation = db.session.get(Evaluation, e_rat["id"])
assert evaluation
evaluation.delete()
b = sco_bulletins.formsemestre_bulletinetud_dict( b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etud["etudid"] sem["formsemestre_id"], etud["etudid"]
) )