Ordre évaluations

This commit is contained in:
Emmanuel Viennet 2024-02-04 12:00:26 +01:00
parent 7805a6cab9
commit 7162d83f39
4 changed files with 68 additions and 56 deletions

View File

@ -5,7 +5,7 @@
import datetime
from operator import attrgetter
from flask import g, url_for
from flask import abort, g, url_for
from flask_login import current_user
import sqlalchemy as sa
@ -241,6 +241,25 @@ class Evaluation(db.Model):
if k != "_sa_instance_state" and k != "id" and k in data:
setattr(self, k, data[k])
@classmethod
def get_evaluation(
cls, evaluation_id: int | str, dept_id: int = None
) -> "Evaluation":
"""Evaluation ou 404, cherche uniquement dans le département spécifié ou le courant."""
from app.models import FormSemestre, ModuleImpl
if not isinstance(evaluation_id, int):
try:
evaluation_id = int(evaluation_id)
except (TypeError, ValueError):
abort(404, "evaluation_id invalide")
if g.scodoc_dept:
dept_id = dept_id if dept_id is not None else g.scodoc_dept_id
query = cls.query.filter_by(id=evaluation_id)
if dept_id is not None:
query = query.join(ModuleImpl).join(FormSemestre).filter_by(dept_id=dept_id)
return query.first_or_404()
@classmethod
def get_max_numero(cls, moduleimpl_id: int) -> int:
"""Return max numero among evaluations in this
@ -265,7 +284,9 @@ class Evaluation(db.Model):
evaluations = moduleimpl.evaluations.order_by(
Evaluation.date_debut, Evaluation.numero
).all()
all_numbered = all(e.numero is not None for e in evaluations)
numeros_distincts = {e.numero for e in evaluations if e.numero is not None}
# pas de None, pas de dupliqués
all_numbered = len(numeros_distincts) == len(evaluations)
if all_numbered and only_if_unumbered:
return # all ok

View File

@ -162,50 +162,48 @@ def do_evaluation_get_all_notes(
return d
def moduleimpl_evaluation_move(evaluation_id: int, after=0, redirect=1):
def moduleimpl_evaluation_move(evaluation_id: int, after=0):
"""Move before/after previous one (decrement/increment numero)
(published)
"""
evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
redirect = int(redirect)
evaluation = Evaluation.get_evaluation(evaluation_id)
# access: can change eval ?
if not evaluation.moduleimpl.can_edit_evaluation(current_user):
raise AccessDenied(
f"Modification évaluation impossible pour {current_user.get_nomplogin()}"
)
Evaluation.moduleimpl_evaluation_renumber(
evaluation.moduleimpl, only_if_unumbered=True
)
e = get_evaluations_dict(args={"evaluation_id": evaluation_id})[0]
after = int(after) # 0: deplace avant, 1 deplace apres
if after not in (0, 1):
raise ValueError('invalid value for "after"')
mod_evals = get_evaluations_dict({"moduleimpl_id": e["moduleimpl_id"]})
if len(mod_evals) > 1:
idx = [p["evaluation_id"] for p in mod_evals].index(evaluation_id)
Evaluation.moduleimpl_evaluation_renumber(
evaluation.moduleimpl, only_if_unumbered=True
)
mod_evaluations = evaluation.moduleimpl.evaluations.all()
if len(mod_evaluations) > 1:
idx = [e.id for e in mod_evaluations].index(evaluation.id)
neigh = None # object to swap with
if after == 0 and idx > 0:
neigh = mod_evals[idx - 1]
elif after == 1 and idx < len(mod_evals) - 1:
neigh = mod_evals[idx + 1]
neigh = mod_evaluations[idx - 1]
elif after == 1 and idx < len(mod_evaluations) - 1:
neigh = mod_evaluations[idx + 1]
if neigh: #
if neigh["numero"] == e["numero"]:
if neigh.numero == evaluation.numero:
log("Warning: moduleimpl_evaluation_move: forcing renumber")
Evaluation.moduleimpl_evaluation_renumber(
evaluation.moduleimpl, only_if_unumbered=False
)
else:
# swap numero with neighbor
e["numero"], neigh["numero"] = neigh["numero"], e["numero"]
do_evaluation_edit(e)
do_evaluation_edit(neigh)
evaluation.numero, neigh.numero = neigh.numero, evaluation.numero
db.session.add(evaluation)
db.session.add(neigh)
db.session.commit()
# redirect to moduleimpl page:
if redirect:
return flask.redirect(
url_for(
"notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept,
moduleimpl_id=e["moduleimpl_id"],
moduleimpl_id=evaluation.moduleimpl.id,
)
)

View File

@ -37,7 +37,7 @@ from flask_login import current_user
from flask import request
from app import db
from app.models import Evaluation, FormSemestre, ModuleImpl
from app.models import Evaluation, Module, ModuleImpl
from app.models.evaluations import heure_to_time
import app.scodoc.sco_utils as scu
@ -47,7 +47,6 @@ from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc import html_sco_header
from app.scodoc import sco_cache
from app.scodoc import sco_evaluations
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_preferences
@ -58,27 +57,20 @@ def evaluation_create_form(
page_title="Évaluation",
):
"Formulaire création/édition d'une évaluation (pas de ses notes)"
evaluation: Evaluation
if evaluation_id is not None:
evaluation: Evaluation = db.session.get(Evaluation, evaluation_id)
evaluation = db.session.get(Evaluation, evaluation_id)
if evaluation is None:
raise ScoValueError("Cette évaluation n'existe pas ou plus !")
moduleimpl_id = evaluation.moduleimpl_id
#
modimpl: ModuleImpl = (
ModuleImpl.query.filter_by(id=moduleimpl_id)
.join(FormSemestre)
.filter_by(dept_id=g.scodoc_dept_id)
.first_or_404()
)
modimpl_o = sco_moduleimpl.moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[
0
]
mod = modimpl_o["module"]
formsemestre_id = modimpl_o["formsemestre_id"]
modimpl = ModuleImpl.get_modimpl(moduleimpl_id)
formsemestre_id = modimpl.formsemestre_id
formsemestre = modimpl.formsemestre
module: Module = modimpl.module
sem_ues = formsemestre.get_ues(with_sport=False)
is_malus = mod["module_type"] == ModuleType.MALUS
is_apc = mod["module_type"] in (ModuleType.RESSOURCE, ModuleType.SAE)
is_malus = module.module_type == ModuleType.MALUS
is_apc = module.module_type in (ModuleType.RESSOURCE, ModuleType.SAE)
preferences = sco_preferences.SemPreferences(formsemestre.id)
can_edit_poids = not preferences["but_disable_edit_poids_evaluations"]
min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible
@ -99,8 +91,9 @@ def evaluation_create_form(
if moduleimpl_id is None:
raise ValueError("missing moduleimpl_id parameter")
initvalues = {
"note_max": 20,
"jour": time.strftime("%d/%m/%Y", time.localtime()),
"note_max": 20,
"numero": max(e.numero or 0 for e in modimpl.evaluations) + 1,
"publish_incomplete": is_malus,
"visibulletin": 1,
}
@ -128,18 +121,7 @@ def evaluation_create_form(
min_note_max_str = scu.fmt_note(min_note_max)
else:
min_note_max_str = "0"
#
H = [
f"""<h3>{action} en
{scu.MODULE_TYPE_NAMES[mod["module_type"]]} <a class="stdlink" href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id)
}">{mod["code"] or "module sans code"} {mod["titre"]}</a> {link}</h3>
"""
]
heures = [f"{h:02d}h{m:02d}" for h in range(8, 19) for m in (0, 30)]
#
initvalues["coefficient"] = initvalues.get("coefficient", 1.0)
vals = scu.get_request_args()
#
@ -164,6 +146,7 @@ def evaluation_create_form(
("evaluation_id", {"default": evaluation_id, "input_type": "hidden"}),
("formsemestre_id", {"default": formsemestre_id, "input_type": "hidden"}),
("moduleimpl_id", {"default": moduleimpl_id, "input_type": "hidden"}),
("numero", {"default": initvalues["numero"], "input_type": "hidden"}),
(
"jour",
{
@ -323,6 +306,16 @@ def evaluation_create_form(
dest_url = url_for(
"notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id
)
H = [
f"""<h3>{action} en
{scu.MODULE_TYPE_NAMES[module.module_type]} <a class="stdlink" href="{
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id)
}">{module.code or "module sans code"} {
module.titre or module.abbrev or "(sans titre)"
}</a> {link}</h3>
"""
]
if tf[0] == 0:
head = html_sco_header.sco_header(page_title=page_title)
return (

View File

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