From 4aad637ff300251f7b47503ec593866c0582477d Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet <emmanuel.viennet@gmail.com> Date: Tue, 15 Apr 2025 18:59:51 +0200 Subject: [PATCH] =?UTF-8?q?Export=20de=20toutes=20les=20notesd'un=20=C3=A9?= =?UTF-8?q?tudiant=20aux=20=C3=A9vals=20d'un=20semestre.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scodoc/sco_bulletins.py | 8 +++ app/scodoc/sco_saisie_notes.py | 89 +++++++++++++++++++++++++++++----- app/scodoc/sco_utils.py | 3 +- app/views/notes.py | 19 ++++++++ 4 files changed, 105 insertions(+), 14 deletions(-) diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index 0d09b3ba..e2483606 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -1261,6 +1261,14 @@ def make_menu_autres_operations( # possible slt si on a un mail... "enabled": etud_perso and can_send_bulletin_by_mail(formsemestre.id), }, + { + "title": "Exporter toutes les notes d'évaluations", + "endpoint": "notes.formsemestre_etud_export_all_notes", + "args": { + "formsemestre_id": formsemestre.id, + "etudid": etud.id, + }, + }, { "title": "Version json", "endpoint": endpoint, diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py index a53e4607..7146dd0b 100644 --- a/app/scodoc/sco_saisie_notes.py +++ b/app/scodoc/sco_saisie_notes.py @@ -48,7 +48,7 @@ from app.models import ( NotesNotes, ) from app.models.etudiants import Identite - +from app.scodoc.gen_tables import GenTable from app.scodoc.sco_exceptions import ( AccessDenied, NoteProcessError, @@ -63,6 +63,7 @@ from app.scodoc import sco_evaluations from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_groups from app.scodoc import sco_groups_view +from app.scodoc import sco_preferences from app.scodoc import sco_undo_notes import app.scodoc.notesdb as ndb from app.scodoc.TrivialFormulator import TF @@ -902,6 +903,23 @@ def get_data(formsemestre: FormSemestre, etud: Identite) -> DataForm: return data +def _formsemestre_module_type_order(formsemestre: FormSemestre) -> list[ModuleType]: + """Liste des types de modules, pour avoir l'ordre d'affichage. + Dépend du type de formation.""" + if formsemestre.formation.is_apc(): + return [ + ModuleType.RESSOURCE, + ModuleType.SAE, + ModuleType.STANDARD, + ModuleType.MALUS, + ] + # Formations classiques: + return [ + ModuleType.STANDARD, + ModuleType.MALUS, + ] + + def saisie_notes_par_etu(formsemestre: FormSemestre, etud: Identite): "Formulaire de saisie de toutes les notes d'un semestre pour un étudiant" # Check access @@ -928,18 +946,8 @@ def saisie_notes_par_etu(formsemestre: FormSemestre, etud: Identite): if inscription.etat != scu.INSCRIT: raise ScoValueError("Étudiant démissionnaire ou défaillant") data = get_data(formsemestre, etud) - if formsemestre.formation.is_apc(): - module_type_order = [ - ModuleType.RESSOURCE, - ModuleType.SAE, - ModuleType.STANDARD, - ModuleType.MALUS, - ] - else: - module_type_order = [ - ModuleType.STANDARD, - ModuleType.MALUS, - ] + module_type_order = _formsemestre_module_type_order(formsemestre) + return render_template( "etud/saisie_notes_par_etu.j2", title="Saisie notes par étudiant", @@ -958,6 +966,61 @@ def get_evaluation_etud_note(evaluation: Evaluation, etudid: int) -> NotesNotes ).first() +def formsemestre_etud_export_all_notes( + formsemestre: FormSemestre, etud: Identite +) -> GenTable: + """Table avec toutes les notes de toutes les évaluations du formsemestre, + sans aucun calcul de moyennes. + """ + data = get_data(formsemestre, etud) + titles = { + "modimpl_id": "modimpl_id", + "code_module": "Module", + "evaluation_id": "evaluation_id", + "evaluation_description": "Description", + "date_debut": "Date début", + "date_fin": "Date fin", + "evaluation_type": "Type", + "coef": "Coef", + "note": "Note", + "bareme": "Barème", + } + columns_ids = titles.keys() + # poids_{ue_acronyme} (une colonne par UE) + rows = [] + for module_type in _formsemestre_module_type_order(formsemestre): + for data_modimpl in data.data_sections[module_type].data_modimpl: + for data_eval in data_modimpl.data_evals: + rows.append( + { + "modimpl_id": data_modimpl.modimpl.id, + "code_module": data_modimpl.module_code or "", + "evaluation_id": data_eval.evaluation.id, + "evaluation_description": data_eval.evaluation.description + or "", + "bareme": data_eval.evaluation.note_max, + "coef": data_eval.evaluation.coefficient, + "date_debut": data_eval.evaluation.date_debut or "", + "date_fin": data_eval.evaluation.date_fin or "", + "evaluation_type": data_eval.evaluation.type_abbrev(), + "note": ( + scu.fmt_note(data_eval.note.value, keep_numeric=True) + if data_eval.note + else "" + ), + } + ) + name = scu.make_filename(f"notes_{etud.nomprenom}_{formsemestre.titre_num()}") + return GenTable( + titles=titles, + columns_ids=columns_ids, + rows=rows, + preferences=sco_preferences.SemPreferences(formsemestre.id), + xls_sheet_name=name, + filename=name + scu.XLSX_SUFFIX, + ) + + def get_sorted_etuds_notes( evaluation: Evaluation, etudids: list, formsemestre_id: int ) -> list[dict]: diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index e1ee3286..b6aecabd 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -655,7 +655,8 @@ def fmt_note( val, note_max=None, keep_numeric=False, fixed_precision_str=True ) -> str | float: """conversion note en str pour affichage dans tables HTML ou PDF. - Si keep_numeric, laisse les valeur numeriques telles quelles (pour export Excel) + Si keep_numeric, laisse les valeur numeriques telles quelles (pour export Excel). + Si note_max > 0, normalise sur cette valeur. Si fixed_precision_str (défaut), formatte sur 4 chiffres ("01.23"), sinon utilise %g (chaine précision variable, pour les formulaires) """ diff --git a/app/views/notes.py b/app/views/notes.py index 8f5929a2..c3ca15a9 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -1942,6 +1942,25 @@ def moduleimpl_feuille_import_notes(moduleimpl_id: int): return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE) +# --- Export des notes +@bp.route("formsemestre_etud_export_all_notes/<int:formsemestre_id>/<int:etudid>") +@scodoc +@permission_required(Permission.ScoView) +def formsemestre_etud_export_all_notes(formsemestre_id: int, etudid: int): + """Exporte un classeur xlsx avec toutes les notes de l'étudiant + aux évaluations de ce semestre (sans les moyennes). + """ + formsemestre = FormSemestre.get_formsemestre(formsemestre_id) + etud = Identite.get_etud(etudid) + table = sco_saisie_notes.formsemestre_etud_export_all_notes(formsemestre, etud) + return scu.send_file( + table.excel(), + table.filename, + scu.XLSX_SUFFIX, + mime=scu.XLSX_MIMETYPE, + ) + + # --- Bulletins @bp.route("/formsemestre_bulletins_pdf") @scodoc -- GitLab