diff --git a/app/models/evaluations.py b/app/models/evaluations.py index e2c01695f..d796381d6 100644 --- a/app/models/evaluations.py +++ b/app/models/evaluations.py @@ -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 diff --git a/app/scodoc/sco_evaluation_db.py b/app/scodoc/sco_evaluation_db.py index e0668eb85..35d90a96a 100644 --- a/app/scodoc/sco_evaluation_db.py +++ b/app/scodoc/sco_evaluation_db.py @@ -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"], - ) + return flask.redirect( + url_for( + "notes.moduleimpl_status", + scodoc_dept=g.scodoc_dept, + moduleimpl_id=evaluation.moduleimpl.id, ) + ) diff --git a/app/scodoc/sco_evaluation_edit.py b/app/scodoc/sco_evaluation_edit.py index 9b5c716fd..b3277f73a 100644 --- a/app/scodoc/sco_evaluation_edit.py +++ b/app/scodoc/sco_evaluation_edit.py @@ -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"""

{action} en - {scu.MODULE_TYPE_NAMES[mod["module_type"]]} {mod["code"] or "module sans code"} {mod["titre"]} {link}

- """ - ] - 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"""

{action} en + {scu.MODULE_TYPE_NAMES[module.module_type]} {module.code or "module sans code"} { + module.titre or module.abbrev or "(sans titre)" + } {link}

+ """ + ] if tf[0] == 0: head = html_sco_header.sco_header(page_title=page_title) return ( diff --git a/sco_version.py b/sco_version.py index 547f69bb2..131fa66cf 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.6.93" +SCOVERSION = "9.6.931" SCONAME = "ScoDoc"