# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2023 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 time import flask from flask import url_for, render_template from flask import g from flask_login import current_user from flask import request from app import db from app.models import Evaluation, FormSemestre, ModuleImpl 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 html_sco_header from app.scodoc import sco_evaluations from app.scodoc import sco_evaluation_db from app.scodoc import sco_moduleimpl from app.scodoc import sco_permissions_check 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)" if evaluation_id is not None: evaluation: 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"] formsemestre = modimpl.formsemestre 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) 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 sco_permissions_check.can_edit_evaluation(moduleimpl_id=moduleimpl_id): return f""" {html_sco_header.sco_header()}

Opération non autorisée

Modification évaluation impossible pour {current_user.get_nomplogin()}

Revenir

{html_sco_header.sco_footer()} """ if not edit: # création nouvel if moduleimpl_id is None: raise ValueError("missing moduleimpl_id parameter") initvalues = { "note_max": 20, "jour": time.strftime("%d/%m/%Y", time.localtime()), "publish_incomplete": is_malus, } 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 les données" 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" # 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["visibulletin"] = initvalues.get("visibulletin", True) if initvalues["visibulletin"]: initvalues["visibulletinlist"] = ["X"] else: initvalues["visibulletinlist"] = [] initvalues["coefficient"] = initvalues.get("coefficient", 1.0) vals = scu.get_request_args() if vals.get("tf_submitted", False) and "visibulletinlist" not in vals: vals["visibulletinlist"] = [] # 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 # 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"}), ( "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": "menu", "allowed_values": heures, "labels": heures, }, ), ( "heure_fin", { "title": "Heure de fin", "explanation": "heure de fin de l'épreuve", "input_type": "menu", "allowed_values": heures, "labels": heures, }, ), ] 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 et 2ème session)", "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".""", }, ), ( "visibulletinlist", { "input_type": "checkbox", "allowed_values": ["X"], "labels": [""], "title": "Visible sur bulletins", "explanation": "(pour les bulletins en version intermédiaire)", }, ), ( "publish_incomplete", { "input_type": "boolcheckbox", "title": "Prise en compte immédiate", "explanation": "notes utilisées même si incomplètes", }, ), ( "evaluation_type", { "input_type": "menu", "title": "Modalité", "allowed_values": ( scu.EVALUATION_NORMALE, scu.EVALUATION_RATTRAPAGE, scu.EVALUATION_SESSION2, ), "type": "int", "labels": ( "Normale", "Rattrapage (remplace si meilleure note)", "Deuxième session (remplace toujours)", ), }, ), ] if is_apc: # ressources et SAÉs form += [ ( "coefficient", { "size": 6, "type": "float", "explanation": "importance de l'évaluation (multiplie les poids ci-dessous)", "allow_null": False, }, ), ] # 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": """
les poids ne sont pas modifiables (voir réglage paramétrage)
""", }, ) ) for ue in sem_ues: coef_ue = ue_coef_dict.get(ue.id, 0.0) form.append( ( f"poids_{ue.id}", { "title": f"Poids {ue.acronyme}", "size": 2, "type": "float", "explanation": f""" ({ "coef. mod.:" +str(coef_ue) if coef_ue else "ce module n'a pas de coef. dans cette UE" }) {ue.titre} """, "allow_null": False, # ok si poids nul ou coef vers l'UE nul: "validator": lambda val, field: (not val) or ue_coef_dict.get(int(field[len("poids_") :]), 0.0) != 0, "enabled": (coef_ue != 0 or initvalues[f"poids_{ue.id}"] != 0.0) and can_edit_poids, }, ), ) tf = TrivialFormulator( request.base_url, vals, form, cancelbutton="Annuler", submitlabel=submitlabel, initvalues=initvalues, readonly=False, ) dest_url = url_for( "notes.moduleimpl_status", scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id ) if tf[0] == 0: head = html_sco_header.sco_header(page_title=page_title) return ( head + "\n".join(H) + "\n" + tf[1] + render_template("scodoc/help/evaluations.j2", is_apc=is_apc) + html_sco_header.sco_footer() ) elif tf[0] == -1: return flask.redirect(dest_url) else: # form submission if tf[2]["visibulletinlist"]: tf[2]["visibulletin"] = True else: tf[2]["visibulletin"] = False if edit: sco_evaluation_db.do_evaluation_edit(tf[2]) else: # création d'une evaluation (via fonction ScoDoc7) evaluation_id = sco_evaluation_db.do_evaluation_create(**tf[2]) if is_apc: # Set poids evaluation = db.session.get(Evaluation, evaluation_id) for ue in sem_ues: evaluation.set_ue_poids(ue, tf[2][f"poids_{ue.id}"]) db.session.add(evaluation) db.session.commit() return flask.redirect(dest_url)