# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Emmanuel Viennet emmanuel.viennet@gmail.com # ############################################################################## """Formulaire ajout/édition d'une évaluation """ import datetime import time import flask from flask import g, render_template, request, url_for from flask_login import current_user from app import db from app.models import Evaluation, Module, ModuleImpl 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 from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc import sco_cache from app.scodoc import sco_evaluations from app.scodoc import sco_preferences def evaluation_create_form( moduleimpl_id=None, evaluation_id=None, edit=False, page_title="Évaluation", ): "Formulaire création/édition d'une évaluation (pas de ses notes)" evaluation: Evaluation if evaluation_id is not None: 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.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 = 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 # if not modimpl.can_edit_evaluation(current_user): return render_template( "sco_page.j2", title="Opération non autorisée", content=f"""
Modification évaluation impossible pour {current_user.get_nomplogin()}
""", ) if not edit: # création nouvel if moduleimpl_id is None: raise ValueError("missing moduleimpl_id parameter") numeros = [(e.numero or 0) for e in modimpl.evaluations] initvalues = { "jour": time.strftime(scu.DATE_FMT, time.localtime()), "note_max": 20, "numero": (max(numeros) + 1) if numeros else 0, "publish_incomplete": is_malus, "visibulletin": 1, } submitlabel = "Créer cette évaluation" action = "Création d'une évaluation" link = "" else: # édition données existantes # setup form init values if evaluation_id is None: raise ValueError("missing evaluation_id parameter") initvalues = evaluation.to_dict() moduleimpl_id = initvalues["moduleimpl_id"] submitlabel = "Modifier l'évaluation" action = "Modification d'une évaluation" link = "" # Note maximale actuelle dans cette éval ? etat = sco_evaluations.do_evaluation_etat(evaluation_id) if etat["maxi_num"] is not None: min_note_max = max(scu.NOTES_PRECISION, etat["maxi_num"]) else: min_note_max = scu.NOTES_PRECISION # if min_note_max > scu.NOTES_PRECISION: min_note_max_str = scu.fmt_note(min_note_max) else: min_note_max_str = "0" initvalues["coefficient"] = initvalues.get("coefficient", 1.0) vals = scu.get_request_args() # ue_coef_dict = modimpl.module.get_ue_coef_dict() if is_apc: # BUT: poids vers les UE if edit: if evaluation.set_default_poids(): db.session.commit() ue_poids_dict = evaluation.get_ue_poids_dict() for ue in sem_ues: initvalues[f"poids_{ue.id}"] = ue_poids_dict[ue.id] else: for ue in sem_ues: coef_ue = ue_coef_dict.get(ue.id, 0.0) or 0.0 if coef_ue > 0: poids = 1.0 # par défaut au départ else: poids = 0.0 initvalues[f"poids_{ue.id}"] = poids # Blocage if edit: initvalues["blocked"] = evaluation.is_blocked() initvalues["blocked_until"] = ( evaluation.blocked_until.strftime(scu.DATE_FMT) if evaluation.blocked_until and evaluation.blocked_until < Evaluation.BLOCKED_FOREVER else "" ) # 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", { "input_type": "datedmy", "title": "Date", "size": 12, "explanation": "date de l'examen, devoir ou contrôle", }, ), ( "heure_debut", { "title": "Heure de début", "explanation": "heure du début de l'épreuve", "input_type": "time", }, ), ( "heure_fin", { "title": "Heure de fin", "explanation": "heure de fin de l'épreuve", "input_type": "time", }, ), ] if is_malus: # pas de coefficient form.append(("coefficient", {"input_type": "hidden", "default": "1."})) elif not is_apc: # modules standard hors BUT form.append( ( "coefficient", { "size": 6, "type": "float", # peut être négatif (!) "explanation": """coef. dans le module (choisi librement par l'enseignant, non utilisé pour rattrapage, 2ème session et bonus)""", "allow_null": False, }, ) ) form += [ ( "note_max", { "size": 4, "type": "float", "title": "Notes de 0 à", "explanation": f"""barème (note max actuelle: {min_note_max_str}).""", "allow_null": False, "max_value": scu.NOTES_MAX, "min_value": min_note_max, }, ), ( "description", { "size": 36, "type": "text", "explanation": """type d'évaluation, apparait sur le bulletins longs. Exemples: "contrôle court", "examen de TP", "examen final".""", }, ), ( "visibulletin", { "input_type": "boolcheckbox", "title": "Visible sur bulletins", "explanation": "(pour les bulletins en version intermédiaire/passerelle)", }, ), ( "publish_incomplete", { "input_type": "boolcheckbox", "title": "Prise en compte immédiate", "explanation": """notes utilisées même si incomplètes (dangereux, à n'utiliser que dans des cas particuliers voir la documentation ) """, }, ), ( "evaluation_type", { "input_type": "menu", "title": "Modalité", "allowed_values": Evaluation.VALID_EVALUATION_TYPES, "type": "int", "labels": ( "Normale", "Rattrapage (remplace si meilleure note)", "Deuxième session (remplace toujours)", ( "Bonus " + ( "(pondéré par poids et ajouté aux moyennes de ce module)" if is_apc else "(ajouté à la moyenne de ce module, différent du bonus sport !)" ) ), ), }, ), ] if is_apc: # ressources et SAÉs form += [ ( "coefficient", { "size": 6, "type": "float", "explanation": """importance de l'évaluation (multiplie les poids ci-dessous). Non utilisé pour les bonus.""", "allow_null": False, "dom_id": "evaluation-edit-coef", }, ), ] # Liste des UE utilisées dans des modules de ce semestre: if sem_ues and not can_edit_poids: form.append( ( "sep_poids", { "input_type": "separator", "title": """