From 71615613f15a6626d5d846b72beef0d32d48fa9a Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 17 Dec 2021 21:36:34 +0100 Subject: [PATCH 01/10] =?UTF-8?q?Fix:=20bulletins=20oldjson=20des=20d?= =?UTF-8?q?=C3=A9m.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_bulletins_json.py | 7 +++++++ app/scodoc/sco_groups.py | 2 +- app/views/notes.py | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/scodoc/sco_bulletins_json.py b/app/scodoc/sco_bulletins_json.py index 2b5ec2c4..81df14d6 100644 --- a/app/scodoc/sco_bulletins_json.py +++ b/app/scodoc/sco_bulletins_json.py @@ -33,6 +33,7 @@ import json from app.but import bulletin_but from app.models.formsemestre import FormSemestre +from app.models.etudiants import Identite import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb @@ -86,6 +87,7 @@ def formsemestre_bulletinetud_published_dict( from app.scodoc import sco_bulletins formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + etud = Identite.query.get(etudid) sem = sco_formsemestre.get_formsemestre(formsemestre_id) if formsemestre.formation.is_apc(): @@ -139,6 +141,11 @@ def formsemestre_bulletinetud_published_dict( if not published: return d # stop ! + etat_inscription = etud.etat_inscription(formsemestre.id) + if etat_inscription != scu.INSCRIT: + d.update(dict_decision_jury(etudid, formsemestre_id, with_decisions=True)) + return d + # Groupes: partitions = sco_groups.get_partitions_list(formsemestre_id, with_default=False) partitions_etud_groups = {} # { partition_id : { etudid : group } } diff --git a/app/scodoc/sco_groups.py b/app/scodoc/sco_groups.py index cfd33196..da46270d 100644 --- a/app/scodoc/sco_groups.py +++ b/app/scodoc/sco_groups.py @@ -35,7 +35,6 @@ Optimisation possible: """ import collections import operator -import re import time from xml.etree import ElementTree @@ -45,6 +44,7 @@ import flask from flask import g, request from flask import url_for, make_response +from app import db from app.models.groups import Partition import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb diff --git a/app/views/notes.py b/app/views/notes.py index 8ec4702b..a7ed9fd5 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -285,6 +285,8 @@ def formsemestre_bulletinetud( prefer_mail_perso=False, code_nip=None, ): + if not formsemestre_id: + flask.abort(404, "argument manquant: formsemestre_id") formsemestre = FormSemestre.query.get_or_404(formsemestre_id) if formsemestre.formation.is_apc() and format != "oldjson": if etudid: From 593317a50aa4025e308fe59e1b2d356a01c1edf2 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 17 Dec 2021 21:59:28 +0100 Subject: [PATCH 02/10] Export recapcomplet json: format BUT --- app/scodoc/sco_recapcomplet.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index 34f1aee7..d3f7f6f4 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -37,7 +37,8 @@ from flask import make_response from app import log from app.but import bulletin_but -from app.models import FormSemestre, UniteEns, Module, ModuleImpl +from app.models import FormSemestre +from app.models.etudiants import Identite import app.scodoc.sco_utils as scu from app.scodoc import html_sco_header @@ -937,6 +938,9 @@ def _formsemestre_recapcomplet_json( :param force_publishing: donne les bulletins même si non "publiés sur portail" :returns: dict, "", "json" """ + formsemestre = FormSemestre.query.get_or_404(formsemestre_id) + is_apc = formsemestre.formation.is_apc() + if xml_nodate: docdate = "" else: @@ -958,14 +962,18 @@ def _formsemestre_recapcomplet_json( T = nt.get_table_moyennes_triees() for t in T: etudid = t[-1] - bulletins.append( - sco_bulletins_json.formsemestre_bulletinetud_published_dict( + if is_apc: + etud = Identite.query.get(etudid) + r = bulletin_but.ResultatsSemestreBUT(formsemestre) + bul = r.bulletin_etud(etud, formsemestre) + else: + bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict( formsemestre_id, etudid, force_publishing=force_publishing, xml_with_decisions=xml_with_decisions, ) - ) + bulletins.append(bul) return J, "", "json" From 4511951255a24de5d31ea06b5cfc1e454cc7219f Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 17 Dec 2021 22:53:34 +0100 Subject: [PATCH 03/10] =?UTF-8?q?Fix:=20suppression=20toutes=20notes=20?= =?UTF-8?q?=C3=A9valuations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_edit_ue.py | 4 ++-- app/scodoc/sco_saisie_notes.py | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index cd5dcb7e..929911f6 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -471,7 +471,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list raise ScoValueError("invalid formation_id") parcours = formation.get_parcours() is_apc = parcours.APC_SAE - locked = sco_formations.formation_has_locked_sems(formation_id) + locked = formation.has_locked_sems() if semestre_idx == "all": semestre_idx = None else: @@ -541,7 +541,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list if locked: H.append( f"""

Cette formation est verrouillée car -{len(locked)} semestres verrouillés s'y réferent. +des semestres verrouillés s'y réferent. Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module), vous devez:

diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py index c1ba813d..0b5cb3ce 100644 --- a/app/scodoc/sco_saisie_notes.py +++ b/app/scodoc/sco_saisie_notes.py @@ -408,7 +408,7 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False): if not dialog_confirmed: nb_changed, nb_suppress, existing_decisions = notes_add( - current_user, evaluation_id, notes, do_it=False + current_user, evaluation_id, notes, do_it=False, check_inscription=False ) msg = ( "

Confirmer la suppression des %d notes ? (peut affecter plusieurs groupes)

" @@ -426,7 +426,11 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False): # modif nb_changed, nb_suppress, existing_decisions = notes_add( - current_user, evaluation_id, notes, comment="effacer tout" + current_user, + evaluation_id, + notes, + comment="effacer tout", + check_inscription=False, ) assert nb_changed == nb_suppress H = ["

%s notes supprimées

" % nb_suppress] @@ -454,7 +458,14 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False): return html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer() -def notes_add(user, evaluation_id: int, notes: list, comment=None, do_it=True) -> tuple: +def notes_add( + user, + evaluation_id: int, + notes: list, + comment=None, + do_it=True, + check_inscription=True, +) -> tuple: """ Insert or update notes notes is a list of tuples (etudid,value) @@ -475,7 +486,7 @@ def notes_add(user, evaluation_id: int, notes: list, comment=None, do_it=True) - ) } for (etudid, value) in notes: - if etudid not in inscrits: + if check_inscription and (etudid not in inscrits): raise NoteProcessError("etudiant non inscrit dans ce module") if not ((value is None) or (type(value) == type(1.0))): raise NoteProcessError( From 5e65e75a3b641c1d7ee6585d75d791f0b9f0e650 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 17 Dec 2021 23:05:59 +0100 Subject: [PATCH 04/10] =?UTF-8?q?tolere=20module=5Ftype=20NULL=20(bug=20Or?= =?UTF-8?q?l=C3=A9ans/Chimie=20=3F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_formsemestre_status.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py index bff2283c..290b0340 100644 --- a/app/scodoc/sco_formsemestre_status.py +++ b/app/scodoc/sco_formsemestre_status.py @@ -1210,6 +1210,7 @@ def formsemestre_tableau_modules( ) if mod.module_type in ( + None, # ne devrait pas être nécessaire car la migration a remplacé les NULLs ModuleType.STANDARD, ModuleType.RESSOURCE, ModuleType.SAE, @@ -1249,7 +1250,7 @@ def formsemestre_tableau_modules( % (modimpl["moduleimpl_id"], nb_malus_notes) ) else: - raise ValueError("Invalid module_type") # a bug + raise ValueError(f"Invalid module_type {mod.module_type}") # a bug H.append("") return "\n".join(H) From 6596e70eecaae5942e0c494b6c7f734c3c3c0fa3 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 17 Dec 2021 23:50:34 +0100 Subject: [PATCH 05/10] =?UTF-8?q?Affichage=20des=20notes=20d'=C3=A9valuati?= =?UTF-8?q?on=20dans=20tableau=20de=20bord=20module=20(prise=20en=20compte?= =?UTF-8?q?=20des=20(de)inscriptions).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_evaluations.py | 58 +++++++++++---------- app/scodoc/sco_formsemestre_inscriptions.py | 4 +- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py index ab6cdf6f..7d6bb82b 100644 --- a/app/scodoc/sco_evaluations.py +++ b/app/scodoc/sco_evaluations.py @@ -109,30 +109,10 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition= nb_inscrits = len( sco_groups.do_evaluation_listeetuds_groups(evaluation_id, getallstudents=True) ) - NotesDB = sco_evaluation_db.do_evaluation_get_all_notes( + etuds_notes_dict = sco_evaluation_db.do_evaluation_get_all_notes( evaluation_id - ) # { etudid : value } - notes = [x["value"] for x in NotesDB.values()] - nb_abs = len([x for x in notes if x is None]) - nb_neutre = len([x for x in notes if x == scu.NOTES_NEUTRALISE]) - nb_att = len([x for x in notes if x == scu.NOTES_ATTENTE]) - moy_num, median_num, mini_num, maxi_num = notes_moyenne_median_mini_maxi(notes) - if moy_num is None: - median, moy = "", "" - median_num, moy_num = None, None - mini, maxi = "", "" - mini_num, maxi_num = None, None - else: - median = scu.fmt_note(median_num) - moy = scu.fmt_note(moy_num) - mini = scu.fmt_note(mini_num) - maxi = scu.fmt_note(maxi_num) - # cherche date derniere modif note - if len(NotesDB): - t = [x["date"] for x in NotesDB.values()] - last_modif = max(t) - else: - last_modif = None + ) # { etudid : note } + # ---- Liste des groupes complets et incomplets E = sco_evaluation_db.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] @@ -163,8 +143,32 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition= # Nombre de notes valides d'étudiants inscrits au module # (car il peut y avoir des notes d'étudiants désinscrits depuis l'évaluation) - nb_notes = len(insmodset.intersection(NotesDB)) - nb_notes_total = len(NotesDB) + etudids_avec_note = insmodset.intersection(etuds_notes_dict) + nb_notes = len(etudids_avec_note) + # toutes saisies, y compris chez des non-inscrits: + nb_notes_total = len(etuds_notes_dict) + + notes = [etuds_notes_dict[etudid]["value"] for etudid in etudids_avec_note] + nb_abs = len([x for x in notes if x is None]) + nb_neutre = len([x for x in notes if x == scu.NOTES_NEUTRALISE]) + nb_att = len([x for x in notes if x == scu.NOTES_ATTENTE]) + moy_num, median_num, mini_num, maxi_num = notes_moyenne_median_mini_maxi(notes) + if moy_num is None: + median, moy = "", "" + median_num, moy_num = None, None + mini, maxi = "", "" + mini_num, maxi_num = None, None + else: + median = scu.fmt_note(median_num) + moy = scu.fmt_note(moy_num) + mini = scu.fmt_note(mini_num) + maxi = scu.fmt_note(maxi_num) + # cherche date derniere modif note + if len(etuds_notes_dict): + t = [x["date"] for x in etuds_notes_dict.values()] + last_modif = max(t) + else: + last_modif = None # On considere une note "manquante" lorsqu'elle n'existe pas # ou qu'elle est en attente (ATT) @@ -181,8 +185,8 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition= groups[group["group_id"]] = group # isMissing = False - if i["etudid"] in NotesDB: - val = NotesDB[i["etudid"]]["value"] + if i["etudid"] in etuds_notes_dict: + val = etuds_notes_dict[i["etudid"]]["value"] if val == scu.NOTES_ATTENTE: isMissing = True TotalNbAtt += 1 diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py index 20ffa7a9..30cbec83 100644 --- a/app/scodoc/sco_formsemestre_inscriptions.py +++ b/app/scodoc/sco_formsemestre_inscriptions.py @@ -66,7 +66,9 @@ def do_formsemestre_inscription_list(*args, **kw): def do_formsemestre_inscription_listinscrits(formsemestre_id): - """Liste les inscrits (état I) à ce semestre et cache le résultat""" + """Liste les inscrits (état I) à ce semestre et cache le résultat. + Result: [ { "etudid":, "formsemestre_id": , "etat": , "etape": }] + """ r = sco_cache.SemInscriptionsCache.get(formsemestre_id) if r is None: # retreive list From 1aa822c90611b81b5b5379f7b5994fddcd38958f Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 18 Dec 2021 09:47:45 +0100 Subject: [PATCH 06/10] couleur SAE --- app/static/css/releve-but.css | 2 +- scodoc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/static/css/releve-but.css b/app/static/css/releve-but.css index 2091f17c..293dfbd8 100644 --- a/app/static/css/releve-but.css +++ b/app/static/css/releve-but.css @@ -16,7 +16,7 @@ main{ --couleurPrincipale: rgb(240,250,255); --couleurFondTitresUE: rgb(206,255,235); --couleurFondTitresRes: rgb(125, 170, 255); - --couleurFondTitresSAE: rgb(255, 190, 69); + --couleurFondTitresSAE: rgb(211, 255, 255); --couleurSecondaire: #fec; --couleurIntense: #c09; --couleurSurlignage: rgba(232, 255, 132, 0.47); diff --git a/scodoc.py b/scodoc.py index c93e9f2f..26598fc5 100755 --- a/scodoc.py +++ b/scodoc.py @@ -1,4 +1,4 @@ -# -*- coding: UTF-8 -* +# -*- coding: UTF-8 -*- """Application Flask: ScoDoc From 6d7645a599257297a0ae5e2965f490e4fb678e03 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 18 Dec 2021 12:15:40 +0100 Subject: [PATCH 07/10] =?UTF-8?q?Fix:=20ordre=20=C3=A9tudiants=20dans=20df?= =?UTF-8?q?=20evals=20(bis)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/comp/moy_mod.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/comp/moy_mod.py b/app/comp/moy_mod.py index f71a9e79..40616cba 100644 --- a/app/comp/moy_mod.py +++ b/app/comp/moy_mod.py @@ -111,13 +111,14 @@ def df_load_modimpl_notes(moduleimpl_id: int) -> tuple: N'utilise pas de cache ScoDoc. """ - # L'index du dataframe est la liste des étudiants inscrits au semestre, sans les démissionnaires - etudids = { + # L'index du dataframe est la liste des étudiants inscrits au semestre, + # sans les démissionnaires + etudids = [ e.etudid for e in ModuleImpl.query.get(moduleimpl_id).formsemestre.get_inscrits( include_dem=False ) - } + ] evaluations = Evaluation.query.filter_by(moduleimpl_id=moduleimpl_id).all() # --- Calcul nombre d'inscrits pour détermnier si évaluation "complete": if evaluations: @@ -128,7 +129,8 @@ def df_load_modimpl_notes(moduleimpl_id: int) -> tuple: nb_inscrits_module = len(inscrits_module) else: nb_inscrits_module = 0 - evals_notes = pd.DataFrame(index=etudids, dtype=float) # empty df with all students + # empty df with all students: + evals_notes = pd.DataFrame(index=etudids, dtype=float) evaluations_completes = [] for evaluation in evaluations: eval_df = pd.read_sql_query( From 3d8fe461b9949adf4407ef4de9e289dfe40e0f38 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 18 Dec 2021 12:16:49 +0100 Subject: [PATCH 08/10] ajout titres pages (liste evals, bul.) --- app/but/bulletin_but.py | 4 +-- app/scodoc/sco_liste_notes.py | 52 ++++++++++++++++++----------------- app/templates/sco_page.html | 8 +++--- app/views/notes.py | 28 +++++++++++-------- 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py index 79423197..cd1c59a5 100644 --- a/app/but/bulletin_but.py +++ b/app/but/bulletin_but.py @@ -149,9 +149,9 @@ class ResultatsSemestreBUT: """dict synthèse résultats des modules indiqués, avec évaluations de chacun.""" d = {} - etud_idx = self.etud_index[etud.id] + # etud_idx = self.etud_index[etud.id] for mi in modimpls: - mod_idx = self.modimpl_coefs_df.columns.get_loc(mi.id) + # mod_idx = self.modimpl_coefs_df.columns.get_loc(mi.id) # # moyennes indicatives (moyennes de moyennes d'UE) # try: # moyennes_etuds = np.nan_to_num( diff --git a/app/scodoc/sco_liste_notes.py b/app/scodoc/sco_liste_notes.py index fd4181ea..517d172d 100644 --- a/app/scodoc/sco_liste_notes.py +++ b/app/scodoc/sco_liste_notes.py @@ -53,35 +53,34 @@ from app.scodoc.gen_tables import GenTable from app.scodoc.htmlutils import histogram_notes -def do_evaluation_listenotes(): +def do_evaluation_listenotes( + evaluation_id=None, moduleimpl_id=None, format="html" +) -> str: """ - Affichage des notes d'une évaluation - - args: evaluation_id ou moduleimpl_id - (si moduleimpl_id, affiche toutes les évaluations du module) + Affichage des notes d'une évaluation (si evaluation_id) + ou de toutes les évaluations d'un module (si moduleimpl_id) """ mode = None - vals = scu.get_request_args() - if "evaluation_id" in vals: - evaluation_id = int(vals["evaluation_id"]) - mode = "eval" - evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id}) - if "moduleimpl_id" in vals and vals["moduleimpl_id"]: - moduleimpl_id = int(vals["moduleimpl_id"]) + if moduleimpl_id: mode = "module" evals = sco_evaluation_db.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) - if not mode: + elif evaluation_id: + mode = "eval" + evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id}) + else: 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 + modimpl = ModuleImpl.query.get(E["moduleimpl_id"]) # description de l'evaluation if mode == "eval": H = [sco_evaluations.evaluation_describe(evaluation_id=evaluation_id)] + page_title = f"Notes {E['description'] or modimpl.module.code}" else: H = [] + page_title = f"Notes {modimpl.module.code}" # groupes groups = sco_groups.do_evaluation_listegroupes( E["evaluation_id"], include_default=True @@ -187,7 +186,7 @@ def do_evaluation_listenotes(): is_submitted=True, # toujours "soumis" (démarre avec liste complète) ) if tf[0] == 0: - return "\n".join(H) + "\n" + tf[1] + return "\n".join(H) + "\n" + tf[1], page_title elif tf[0] == -1: return flask.redirect( "%s/Notes/moduleimpl_status?moduleimpl_id=%s" @@ -198,16 +197,19 @@ def do_evaluation_listenotes(): note_sur_20 = tf[2]["note_sur_20"] hide_groups = tf[2]["hide_groups"] with_emails = tf[2]["with_emails"] - return _make_table_notes( - tf[1], - evals, - format=format, - note_sur_20=note_sur_20, - anonymous_listing=anonymous_listing, - group_ids=tf[2]["group_ids"], - hide_groups=hide_groups, - with_emails=with_emails, - mode=mode, + return ( + _make_table_notes( + tf[1], + evals, + format=format, + note_sur_20=note_sur_20, + anonymous_listing=anonymous_listing, + group_ids=tf[2]["group_ids"], + hide_groups=hide_groups, + with_emails=with_emails, + mode=mode, + ), + page_title, ) diff --git a/app/templates/sco_page.html b/app/templates/sco_page.html index 0ebe6e19..249bfb39 100644 --- a/app/templates/sco_page.html +++ b/app/templates/sco_page.html @@ -12,7 +12,7 @@ {% endblock %} {% block title %} -{% if title %}{{ title }} - ScoDoc{% else %}Welcome to ScoDoc{% endif %} +{% if title %}{{ title }} - ScoDoc{% else %}ScoDoc{% endif %} {% endblock %} {% block content %} @@ -31,9 +31,9 @@ {% endwith %} {% if sco.sem %} - {% block formsemestre_header %} - {% include "formsemestre_header.html" %} - {% endblock %} + {% block formsemestre_header %} + {% include "formsemestre_header.html" %} + {% endblock %} {% endif %} {% block app_content %} diff --git a/app/views/notes.py b/app/views/notes.py index a7ed9fd5..30222830 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -301,7 +301,7 @@ def formsemestre_bulletinetud( elif format == "html": return render_template( "but/bulletin.html", - title="Bulletin BUT", + title=f"Bul. {etud.nom} - BUT", bul_url=url_for( "notes.formsemestre_bulletinetud", scodoc_dept=g.scodoc_dept, @@ -1728,27 +1728,33 @@ def evaluation_create(moduleimpl_id): @scodoc7func def evaluation_listenotes(): """Affichage des notes d'une évaluation""" - if request.args.get("format", "html") == "html": + evaluation_id = None + moduleimpl_id = None + vals = scu.get_request_args() + if "evaluation_id" in vals: + evaluation_id = int(vals["evaluation_id"]) + mode = "eval" + if "moduleimpl_id" in vals and vals["moduleimpl_id"]: + moduleimpl_id = int(vals["moduleimpl_id"]) + mode = "module" + + format = vals.get("format", "html") + B, page_title = sco_liste_notes.do_evaluation_listenotes( + evaluation_id=evaluation_id, moduleimpl_id=moduleimpl_id, format=format + ) + if format == "html": H = html_sco_header.sco_header( + page_title=page_title, cssstyles=["css/verticalhisto.css"], javascripts=["js/etud_info.js"], init_qtip=True, ) F = html_sco_header.sco_footer() - else: - H, F = "", "" - B = sco_liste_notes.do_evaluation_listenotes() - if H: return H + B + F else: return B -sco_publish( - "/do_evaluation_listenotes", - sco_liste_notes.do_evaluation_listenotes, - Permission.ScoView, -) sco_publish( "/evaluation_list_operations", sco_undo_notes.evaluation_list_operations, From c882a96556fd863072777692959b822daf6d98b4 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 18 Dec 2021 17:39:03 +0100 Subject: [PATCH 09/10] Import formations XML: anciennes ou BUT --- app/scodoc/sco_edit_ue.py | 10 ++++++++-- app/scodoc/sco_formations.py | 5 +++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index 929911f6..cdc83a04 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -104,7 +104,10 @@ def do_ue_create(args): # check duplicates ues = ue_list({"formation_id": args["formation_id"], "acronyme": args["acronyme"]}) if ues: - raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"]) + raise ScoValueError( + f"""Acronyme d'UE "{args['acronyme']}" déjà utilisé ! + (chaque UE doit avoir un acronyme unique dans la formation)""" + ) # create ue_id = _ueEditor.create(cnx, args) @@ -1146,7 +1149,10 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False): new_acro = args["acronyme"] ues = ue_list({"formation_id": ue["formation_id"], "acronyme": new_acro}) if ues and ues[0]["ue_id"] != ue_id: - raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"]) + raise ScoValueError( + f"""Acronyme d'UE "{args['acronyme']}" déjà utilisé ! + (chaque UE doit avoir un acronyme unique dans la formation)""" + ) # On ne peut pas supprimer le code UE: if "ue_code" in args and not args["ue_code"]: diff --git a/app/scodoc/sco_formations.py b/app/scodoc/sco_formations.py index b2eaef98..6bff40c5 100644 --- a/app/scodoc/sco_formations.py +++ b/app/scodoc/sco_formations.py @@ -230,9 +230,10 @@ def formation_import_xml(doc: str, import_tags=True): ue_id = sco_edit_ue.do_ue_create(ue_info[1]) if xml_ue_id: ues_old2new[xml_ue_id] = ue_id - ue_reference = int(ue_info[1].get("reference")) + # élément optionnel présent dans les exports BUT: + ue_reference = ue_info[1].get("reference") if ue_reference: - ue_reference_to_id[ue_reference] = ue_id + ue_reference_to_id[int(ue_reference)] = ue_id # -- create matieres for mat_info in ue_info[2]: assert mat_info[0] == "matiere" From ac5c433f5a42bcdc0412d098588486620f863b66 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 19 Dec 2021 11:08:03 +0100 Subject: [PATCH 10/10] Affichage poids sur tableau bord module + fix #222 --- app/models/evaluations.py | 15 +++++++++---- app/scodoc/sco_liste_notes.py | 15 +++++++++---- app/scodoc/sco_moduleimpl_status.py | 35 +++++++++++++++++++++-------- app/static/css/scodoc.css | 3 +++ sco_version.py | 2 +- 5 files changed, 52 insertions(+), 18 deletions(-) diff --git a/app/models/evaluations.py b/app/models/evaluations.py index 9a237c5c..e0733fb7 100644 --- a/app/models/evaluations.py +++ b/app/models/evaluations.py @@ -76,11 +76,11 @@ class Evaluation(db.Model): db.session.add(copy) return copy - def set_ue_poids(self, ue, poids: float): + def set_ue_poids(self, ue, poids: float) -> None: """Set poids évaluation vers cette UE""" self.update_ue_poids_dict({ue.id: poids}) - def set_ue_poids_dict(self, ue_poids_dict: dict): + def set_ue_poids_dict(self, ue_poids_dict: dict) -> None: """set poids vers les UE (remplace existants) ue_poids_dict = { ue_id : poids } """ @@ -91,16 +91,23 @@ class Evaluation(db.Model): self.ue_poids = L self.moduleimpl.invalidate_evaluations_poids() # inval cache - def update_ue_poids_dict(self, ue_poids_dict: dict): + def update_ue_poids_dict(self, ue_poids_dict: dict) -> None: """update poids vers UE (ajoute aux existants)""" current = self.get_ue_poids_dict() current.update(ue_poids_dict) self.set_ue_poids_dict(current) - def get_ue_poids_dict(self): + def get_ue_poids_dict(self) -> dict: """returns { ue_id : poids }""" return {p.ue.id: p.poids for p in self.ue_poids} + def get_ue_poids_str(self) -> str: + """string describing poids, for excel cells and pdfs + Note: si les poids ne sont pas initialisés (poids par défaut), + ils ne sont pas affichés. + """ + return ", ".join([f"{p.ue.acronyme}: {p.poids}" for p in self.ue_poids]) + class EvaluationUEPoids(db.Model): """Poids des évaluations (BUT) diff --git a/app/scodoc/sco_liste_notes.py b/app/scodoc/sco_liste_notes.py index 517d172d..09e5480f 100644 --- a/app/scodoc/sco_liste_notes.py +++ b/app/scodoc/sco_liste_notes.py @@ -32,6 +32,7 @@ import flask from flask import url_for, g, request from app import models +from app.models.evaluations import Evaluation from app.models.moduleimpls import ModuleImpl import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb @@ -395,6 +396,7 @@ def _make_table_notes( key_mgr, note_sur_20, keep_numeric, + format=format, ) columns_ids.append(e["evaluation_id"]) # @@ -408,7 +410,7 @@ def _make_table_notes( # Si module, ajoute la (les) "moyenne(s) du module: if mode == "module": if len(evals) > 1: - # Moyenne de l'étudant dans le module + # Moyenne de l'étudiant dans le module # Affichée même en APC à titre indicatif _add_moymod_column( sem["formsemestre_id"], @@ -637,6 +639,7 @@ def _add_eval_columns( K, note_sur_20, keep_numeric, + format="html", ): """Add eval e""" nb_notes = 0 @@ -645,6 +648,7 @@ def _add_eval_columns( sum_notes = 0 notes = [] # liste des notes numeriques, pour calcul histogramme uniquement evaluation_id = e["evaluation_id"] + e_o = Evaluation.query.get(evaluation_id) # XXX en attendant ré-écriture NotesDB = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id) for row in rows: etudid = row["etudid"] @@ -706,9 +710,12 @@ def _add_eval_columns( row_coefs[evaluation_id] = "coef. %s" % e["coefficient"] if is_apc: - row_poids[evaluation_id] = _mini_table_eval_ue_poids( - evaluation_id, evals_poids, ues - ) + if format == "html": + row_poids[evaluation_id] = _mini_table_eval_ue_poids( + evaluation_id, evals_poids, ues + ) + else: + row_poids[evaluation_id] = e_o.get_ue_poids_str() if note_sur_20: nmax = 20.0 else: diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index 921fbd11..c9f5aaa2 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -31,9 +31,10 @@ import time from flask import g, url_for from flask_login import current_user -from app.auth.models import User +from app.auth.models import User from app.models import ModuleImpl +from app.models.evaluations import Evaluation import app.scodoc.sco_utils as scu from app.scodoc.sco_permissions import Permission @@ -391,8 +392,9 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): ) H.append("""""") eval_index = len(mod_evals) - 1 - first = True + first_eval = True for eval in mod_evals: + evaluation = Evaluation.query.get(eval["evaluation_id"]) # TODO unifier etat = sco_evaluations.do_evaluation_etat( eval["evaluation_id"], partition_id=partition_id, @@ -406,9 +408,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): else: tr_class = "mievr" tr_class_1 = "mievr" - if first: - first = False - else: + if not first_eval: H.append("""""") tr_class_1 += " mievr_spaced" H.append("""""") # if etat["nb_notes"] == 0: - H.append("""""") + H.append("""""" % tr_class) + if modimpl.module.is_apc(): + H.append( + f"""""" + ) + else: + H.append('') + H.append("""""") else: # il y a deja des notes saisies gr_moyennes = etat["gr_moyennes"] + first_group = True for gr_moyenne in gr_moyennes: H.append("""""" % tr_class) - H.append("""""") + H.append("""""") + if first_group and modimpl.module.is_apc(): + H.append( + f"""""" + ) + else: + H.append("""""") + first_group = False if gr_moyenne["group_name"] is None: name = "Tous" # tous else: name = "Groupe %s" % gr_moyenne["group_name"] H.append( - """""") + first_eval = False # if caneditevals or not sem["etat"]: diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css index 4de39209..58f819c5 100644 --- a/app/static/css/scodoc.css +++ b/app/static/css/scodoc.css @@ -1476,6 +1476,9 @@ span.evalindex { margin-left: 3px; } +table.moduleimpl_evaluations td.eval_poids { + color:rgb(0, 0, 255); +} /* Formulaire edition des partitions */ form#editpart table { diff --git a/sco_version.py b/sco_version.py index cdee3253..b33f520a 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.1.10" +SCOVERSION = "9.1.11" SCONAME = "ScoDoc"
 
""" % tr_class_1) @@ -586,19 +586,35 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): H.append("""
 """ % tr_class) - H.append("""
{ + evaluation.get_ue_poids_str()}
  { + evaluation.get_ue_poids_str()}%s  """ % name + """%s  """ % name ) if gr_moyenne["gr_nb_notes"] > 0: H.append("%(gr_moy)s" % gr_moyenne) @@ -637,6 +653,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): H.append("""""") H.append("") H.append("""