# -*- 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 import log from app import models from app.models.evaluations import Evaluation from app.models.formsemestre import FormSemestre from app.models.moduleimpls import 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 = models.Evaluation.query.get(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.query_ues(with_sport=False).all() 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 = models.Evaluation.query.get(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)