# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2021 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@viennet.net # ############################################################################## """Liste des notes d'une évaluation """ from operator import itemgetter import urllib import flask from flask import url_for, g, request import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app import log from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc import htmlutils from app.scodoc import html_sco_header from app.scodoc import sco_abs from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_evaluations from app.scodoc import sco_excel from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_groups from app.scodoc import sco_moduleimpl from app.scodoc import sco_preferences from app.scodoc import sco_etud from app.scodoc import sco_users import sco_version from app.scodoc.gen_tables import GenTable from app.scodoc.htmlutils import histogram_notes def do_evaluation_listenotes(): """ Affichage des notes d'une évaluation args: evaluation_id ou moduleimpl_id (si moduleimpl_id, affiche toutes les évaluations du module) """ mode = None vals = scu.get_request_args() if "evaluation_id" in vals: evaluation_id = int(vals["evaluation_id"]) mode = "eval" evals = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id}) if "moduleimpl_id" in vals and vals["moduleimpl_id"]: moduleimpl_id = int(vals["moduleimpl_id"]) mode = "module" evals = sco_evaluations.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) if not mode: raise ValueError("missing argument: evaluation or module") if not evals: return "
Aucune évaluation !
" format = vals.get("format", "html") E = evals[0] # il y a au moins une evaluation # description de l'evaluation if mode == "eval": H = [sco_evaluations.evaluation_describe(evaluation_id=evaluation_id)] else: H = [] # groupes groups = sco_groups.do_evaluation_listegroupes( E["evaluation_id"], include_default=True ) grlabs = [g["group_name"] or "tous" for g in groups] # legendes des boutons grnams = [str(g["group_id"]) for g in groups] # noms des checkbox if len(evals) > 1: descr = [ ("moduleimpl_id", {"default": E["moduleimpl_id"], "input_type": "hidden"}) ] else: descr = [ ("evaluation_id", {"default": E["evaluation_id"], "input_type": "hidden"}) ] if len(grnams) > 1: descr += [ ( "s", { "input_type": "separator", "title": "Choix du ou des groupes d'étudiants:", }, ), ( "group_ids", { "input_type": "checkbox", "title": "", "allowed_values": grnams, "labels": grlabs, "attributes": ('onclick="document.tf.submit();"',), }, ), ] else: if grnams: def_nam = grnams[0] else: def_nam = "" descr += [ ( "group_ids", {"input_type": "hidden", "type": "list", "default": [def_nam]}, ) ] descr += [ ( "anonymous_listing", { "input_type": "checkbox", "title": "", "allowed_values": ("yes",), "labels": ('listing "anonyme"',), "attributes": ('onclick="document.tf.submit();"',), "template": 'Aucune évaluation !
" E = evals[0] moduleimpl_id = E["moduleimpl_id"] M = sco_moduleimpl.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] Mod = sco_edit_module.do_module_list(args={"module_id": M["module_id"]})[0] sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"]) # (debug) check that all evals are in same module: for e in evals: if e["moduleimpl_id"] != moduleimpl_id: raise ValueError("invalid evaluations list") if format == "xls": keep_numeric = True # pas de conversion des notes en strings else: keep_numeric = False # Si pas de groupe, affiche tout if not group_ids: group_ids = [sco_groups.get_default_group(M["formsemestre_id"])] groups = sco_groups.listgroups(group_ids) gr_title = sco_groups.listgroups_abbrev(groups) gr_title_filename = sco_groups.listgroups_filename(groups) etudids = sco_groups.do_evaluation_listeetuds_groups( E["evaluation_id"], groups, include_dems=True ) if anonymous_listing: columns_ids = ["code"] # cols in table else: if format == "xls" or format == "xml": columns_ids = ["nom", "prenom"] else: columns_ids = ["nomprenom"] if not hide_groups: columns_ids.append("group") titles = { "code": "Code", "group": "Groupe", "nom": "Nom", "prenom": "Prénom", "nomprenom": "Nom", "expl_key": "Rem.", "email": "e-mail", "emailperso": "e-mail perso", } rows = [] class keymgr(dict): # comment : key (pour regrouper les comments a la fin) def __init__(self): self.lastkey = 1 def nextkey(self): r = self.lastkey self.lastkey += 1 # self.lastkey = chr(ord(self.lastkey)+1) return str(r) K = keymgr() for etudid in etudids: css_row_class = None # infos identite etudiant etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] # infos inscription inscr = sco_formsemestre_inscriptions.do_formsemestre_inscription_list( {"etudid": etudid, "formsemestre_id": M["formsemestre_id"]} )[0] if inscr["etat"] == "I": # si inscrit, indique groupe groups = sco_groups.get_etud_groups(etudid, sem) grc = sco_groups.listgroups_abbrev(groups) else: if inscr["etat"] == "D": grc = "DEM" # attention: ce code est re-ecrit plus bas, ne pas le changer (?) css_row_class = "etuddem" else: grc = inscr["etat"] code = "" # code pour listings anonyme, à la place du nom if sco_preferences.get_preference("anonymous_lst_code") == "INE": code = etud["code_ine"] elif sco_preferences.get_preference("anonymous_lst_code") == "NIP": code = etud["code_nip"] if not code: # laisser le code vide n'aurait aucun sens, prenons l'etudid code = etudid rows.append( { "code": str(code), # INE, NIP ou etudid "_code_td_attrs": 'style="padding-left: 1em; padding-right: 2em;"', "etudid": etudid, "nom": etud["nom"].upper(), "_nomprenom_target": "formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" % (M["formsemestre_id"], etudid), "_nomprenom_td_attrs": 'id="%s" class="etudinfo"' % (etud["etudid"]), "prenom": etud["prenom"].lower().capitalize(), "nomprenom": etud["nomprenom"], "group": grc, "email": etud["email"], "emailperso": etud["emailperso"], "_css_row_class": css_row_class or "", } ) # Lignes en tête: coefs = { "nom": "", "prenom": "", "nomprenom": "", "group": "", "code": "", "_css_row_class": "sorttop fontitalic", "_table_part": "head", } note_max = { "nom": "", "prenom": "", "nomprenom": "", "group": "", "code": "", "_css_row_class": "sorttop fontitalic", "_table_part": "head", } moys = { "_css_row_class": "moyenne sortbottom", "_table_part": "foot", #'_nomprenom_td_attrs' : 'colspan="2" ', "nomprenom": "Moyenne (sans les absents) :", "comment": "", } # Ajoute les notes de chaque évaluation: for e in evals: e["eval_state"] = sco_evaluations.do_evaluation_etat(e["evaluation_id"]) notes, nb_abs, nb_att = _add_eval_columns( e, rows, titles, coefs, note_max, moys, K, note_sur_20, keep_numeric, ) columns_ids.append(e["evaluation_id"]) # if anonymous_listing: rows.sort(key=lambda x: x["code"]) else: rows.sort( key=lambda x: (x["nom"] or "", x["prenom"] or "") ) # sort by nom, prenom # Si module, ajoute moyenne du module: if len(evals) > 1: _add_moymod_column( sem["formsemestre_id"], e, rows, titles, coefs, note_max, moys, note_sur_20, keep_numeric, ) columns_ids.append("moymod") # Ajoute colonnes emails tout à droite: if with_emails: columns_ids += ["email", "emailperso"] # Ajoute lignes en tête et moyennes if len(evals) > 0: rows = [coefs, note_max] + rows rows.append(moys) # ajout liens HTMl vers affichage une evaluation: if format == "html" and len(evals) > 1: rlinks = {"_table_part": "head"} for e in evals: rlinks[e["evaluation_id"]] = "afficher" rlinks[ "_" + str(e["evaluation_id"]) + "_help" ] = "afficher seulement les notes de cette évaluation" rlinks["_" + str(e["evaluation_id"]) + "_target"] = url_for( "notes.evaluation_listenotes", scodoc_dept=g.scodoc_dept, evaluation_id=e["evaluation_id"], ) rlinks["_" + str(e["evaluation_id"]) + "_td_attrs"] = ' class="tdlink" ' rows.append(rlinks) if len(evals) == 1: # colonne "Rem." seulement si une eval if format == "html": # pas d'indication d'origine en pdf (pour affichage) columns_ids.append("expl_key") elif format == "xls" or format == "xml": columns_ids.append("comment") # titres divers: gl = "".join(["&group_ids%3Alist=" + str(g) for g in group_ids]) if note_sur_20: gl = "¬e_sur_20%3Alist=yes" + gl if anonymous_listing: gl = "&anonymous_listing%3Alist=yes" + gl if hide_groups: gl = "&hide_groups%3Alist=yes" + gl if with_emails: gl = "&with_emails%3Alist=yes" + gl if len(evals) == 1: evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"])) hh = "%s, %s (%d étudiants)" % (E["description"], gr_title, len(etudids)) filename = scu.make_filename("notes_%s_%s" % (evalname, gr_title_filename)) caption = hh pdf_title = "%(description)s (%(jour)s)" % e html_title = "" base_url = "evaluation_listenotes?evaluation_id=%s" % E["evaluation_id"] + gl html_next_section = ( 'Répartition des notes:" + histo + " | \n",
'',
]
commentkeys = list(K.items()) # [ (comment, key), ... ]
commentkeys.sort(key=lambda x: int(x[1]))
for (comment, key) in commentkeys:
C.append(
'(%s) %s Vérification de la cohérence entre les notes saisies et les absences signalées. """, ] else: # pas de header, mais un titre H = [ """%s du %s """ % (E["description"], E["jour"]) ] if ( not ValButAbs and not AbsNonSignalee and not ExcNonSignalee and not ExcNonJust ): H.append(': ok') H.append("") def etudlist(etudids, linkabs=False): H.append("
Etudiants ayant une note alors qu'ils sont signalés absents:" ) etudlist(ValButAbs) if AbsNonSignalee or show_ok: H.append( """Etudiants avec note "ABS" alors qu'ils ne sont pas signalés absents:""" ) etudlist(AbsNonSignalee, linkabs=True) if ExcNonSignalee or show_ok: H.append( """Etudiants avec note "EXC" alors qu'ils ne sont pas signalés absents:""" ) etudlist(ExcNonSignalee) if ExcNonJust or show_ok: H.append( """Etudiants avec note "EXC" alors qu'ils sont absents non justifiés:""" ) etudlist(ExcNonJust) if AbsButExc or show_ok: H.append( """Etudiants avec note "ABS" alors qu'ils ont une justification:""" ) etudlist(AbsButExc) if with_header: H.append(html_sco_header.sco_footer()) return "\n".join(H) def formsemestre_check_absences_html(formsemestre_id): """Affiche etat verification absences pour toutes les evaluations du semestre !""" sem = sco_formsemestre.get_formsemestre(formsemestre_id) H = [ html_sco_header.html_sem_header( "Vérification absences aux évaluations de ce semestre", sem, ), """Vérification de la cohérence entre les notes saisies et les absences signalées.
Sont listés tous les modules avec des évaluations. %s: %s' % (M["moduleimpl_id"], M["module"]["code"], M["module"]["abbrev"]) ) for E in evals: H.append( evaluation_check_absences_html( E["evaluation_id"], with_header=False, show_ok=False, ) ) if evals: H.append(" |