# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2022 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 # ############################################################################## """Tableau de bord semestre """ import datetime from flask import current_app from flask import g from flask import request from flask import render_template, url_for from flask_login import current_user from app import log from app.comp import res_sem from app.comp.res_compat import NotesTableCompat from app.models import Module from app.models.formsemestre import FormSemestre import app.scodoc.sco_utils as scu from app.scodoc.sco_utils import ModuleType import app.scodoc.notesdb as ndb from app.scodoc.sco_permissions import Permission from app.scodoc.sco_exceptions import ScoValueError, ScoInvalidDateError from app.scodoc import html_sco_header from app.scodoc import htmlutils from app.scodoc import sco_abs from app.scodoc import sco_archives from app.scodoc import sco_bulletins from app.scodoc import sco_codes_parcours from app.scodoc import sco_compute_moy from app.scodoc import sco_edit_ue from app.scodoc import sco_evaluations from app.scodoc import sco_evaluation_db from app.scodoc import sco_formations from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_edit from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_groups from app.scodoc import sco_moduleimpl from app.scodoc import sco_permissions_check from app.scodoc import sco_preferences from app.scodoc import sco_users from app.scodoc.gen_tables import GenTable from app.scodoc.sco_formsemestre_custommenu import formsemestre_custommenu_html import sco_version def _build_menu_stats(formsemestre_id): "Définition du menu 'Statistiques'" return [ { "title": "Statistiques...", "endpoint": "notes.formsemestre_report_counts", "args": {"formsemestre_id": formsemestre_id}, }, { "title": "Suivi de cohortes", "endpoint": "notes.formsemestre_suivi_cohorte", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, }, { "title": "Graphe des parcours", "endpoint": "notes.formsemestre_graph_parcours", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, }, { "title": "Codes des parcours", "endpoint": "notes.formsemestre_suivi_parcours", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, }, { "title": "Lycées d'origine", "endpoint": "notes.formsemestre_etuds_lycees", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, }, { "title": 'Table "poursuite"', "endpoint": "notes.formsemestre_poursuite_report", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, }, { "title": "Documents Avis Poursuite Etudes (xp)", "endpoint": "notes.pe_view_sem_recap", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, # current_app.config["TESTING"] or current_app.config["DEBUG"], }, { "title": 'Table "débouchés"', "endpoint": "notes.report_debouche_date", "enabled": True, }, { "title": "Estimation du coût de la formation", "endpoint": "notes.formsemestre_estim_cost", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, }, ] def formsemestre_status_menubar(sem): """HTML to render menubar""" formsemestre_id = sem["formsemestre_id"] if int(sem["etat"]): change_lock_msg = "Verrouiller" else: change_lock_msg = "Déverrouiller" F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0] menuSemestre = [ { "title": "Tableau de bord", "endpoint": "notes.formsemestre_status", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "Tableau de bord du semestre", }, { "title": "Voir la formation %(acronyme)s (v%(version)s)" % F, "endpoint": "notes.ue_table", "args": {"formation_id": sem["formation_id"]}, "enabled": True, "helpmsg": "Tableau de bord du semestre", }, { "title": "Modifier le semestre", "endpoint": "notes.formsemestre_editwithmodules", "args": { "formation_id": sem["formation_id"], "formsemestre_id": formsemestre_id, }, "enabled": ( current_user.has_permission(Permission.ScoImplement) or (current_user.id in sem["responsables"] and sem["resp_can_edit"]) ) and (sem["etat"]), "helpmsg": "Modifie le contenu du semestre (modules)", }, { "title": "Préférences du semestre", "endpoint": "scolar.formsemestre_edit_preferences", "args": {"formsemestre_id": formsemestre_id}, "enabled": ( current_user.has_permission(Permission.ScoImplement) or (current_user.id in sem["responsables"] and sem["resp_can_edit"]) ) and (sem["etat"]), "helpmsg": "Préférences du semestre", }, { "title": "Réglages bulletins", "endpoint": "notes.formsemestre_edit_options", "args": {"formsemestre_id": formsemestre_id}, "enabled": (current_user.id in sem["responsables"]) or current_user.has_permission(Permission.ScoImplement), "helpmsg": "Change les options", }, { "title": change_lock_msg, "endpoint": "notes.formsemestre_change_lock", "args": {"formsemestre_id": formsemestre_id}, "enabled": (current_user.id in sem["responsables"]) or current_user.has_permission(Permission.ScoImplement), "helpmsg": "", }, { "title": "Description du semestre", "endpoint": "notes.formsemestre_description", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "", }, { "title": "Vérifier absences aux évaluations", "endpoint": "notes.formsemestre_check_absences_html", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "", }, { "title": "Lister tous les enseignants", "endpoint": "notes.formsemestre_enseignants_list", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "", }, { "title": "Cloner ce semestre", "endpoint": "notes.formsemestre_clone", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoImplement), "helpmsg": "", }, { "title": "Associer à une nouvelle version du programme", "endpoint": "notes.formsemestre_associate_new_version", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoChangeFormation) and (sem["etat"]), "helpmsg": "", }, { "title": "Supprimer ce semestre", "endpoint": "notes.formsemestre_delete", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoImplement), "helpmsg": "", }, ] # debug : if current_app.config["ENV"] == "development": menuSemestre.append( { "title": "Vérifier l'intégrité", "endpoint": "notes.check_sem_integrity", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, } ) menuInscriptions = [ { "title": "Voir les inscriptions aux modules", "endpoint": "notes.moduleimpl_inscriptions_stats", "args": {"formsemestre_id": formsemestre_id}, } ] menuInscriptions += [ { "title": "Passage des étudiants depuis d'autres semestres", "endpoint": "notes.formsemestre_inscr_passage", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoEtudInscrit) and (sem["etat"]), }, { "title": "Synchroniser avec étape Apogée", "endpoint": "notes.formsemestre_synchro_etuds", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoView) and sco_preferences.get_preference("portal_url") and (sem["etat"]), }, { "title": "Inscrire un étudiant", "endpoint": "notes.formsemestre_inscription_with_modules_etud", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoEtudInscrit) and (sem["etat"]), }, { "title": "Importer des étudiants dans ce semestre (table Excel)", "endpoint": "scolar.form_students_import_excel", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoEtudInscrit) and (sem["etat"]), }, { "title": "Import/export des données admission", "endpoint": "scolar.form_students_import_infos_admissions", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoView), }, { "title": "Resynchroniser données identité", "endpoint": "scolar.formsemestre_import_etud_admission", "args": {"formsemestre_id": formsemestre_id}, "enabled": current_user.has_permission(Permission.ScoEtudChangeAdr) and sco_preferences.get_preference("portal_url"), }, { "title": "Exporter table des étudiants", "endpoint": "scolar.groups_view", "args": { "format": "allxls", "group_ids": sco_groups.get_default_group( formsemestre_id, fix_if_missing=True ), }, }, { "title": "Vérifier inscriptions multiples", "endpoint": "notes.formsemestre_inscrits_ailleurs", "args": {"formsemestre_id": formsemestre_id}, }, ] menuGroupes = [ { "title": "Listes, photos, feuilles...", "endpoint": "scolar.groups_view", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "Accès aux listes des groupes d'étudiants", }, { "title": "Créer/modifier les partitions...", "endpoint": "scolar.editPartitionForm", "args": {"formsemestre_id": formsemestre_id}, "enabled": sco_groups.sco_permissions_check.can_change_groups( formsemestre_id ), }, ] # 1 item / partition: partitions = sco_groups.get_partitions_list(formsemestre_id, with_default=False) submenu = [] enabled = ( sco_groups.sco_permissions_check.can_change_groups(formsemestre_id) and partitions ) for partition in partitions: submenu.append( { "title": "%s" % partition["partition_name"], "endpoint": "scolar.affect_groups", "args": {"partition_id": partition["partition_id"]}, "enabled": enabled, } ) menuGroupes.append( {"title": "Modifier les groupes", "submenu": submenu, "enabled": enabled} ) menuNotes = [ { "title": "Tableau des moyennes (et liens bulletins)", "endpoint": "notes.formsemestre_recapcomplet", "args": {"formsemestre_id": formsemestre_id}, }, { "title": "État des évaluations", "endpoint": "notes.evaluations_recap", "args": {"formsemestre_id": formsemestre_id}, }, { "title": "Saisie des notes", "endpoint": "notes.formsemestre_status", "args": {"formsemestre_id": formsemestre_id}, "enabled": True, "helpmsg": "Tableau de bord du semestre", }, { "title": "Classeur PDF des bulletins", "endpoint": "notes.formsemestre_bulletins_pdf_choice", "args": {"formsemestre_id": formsemestre_id}, "helpmsg": "PDF regroupant tous les bulletins", }, { "title": "Envoyer à chaque étudiant son bulletin par e-mail", "endpoint": "notes.formsemestre_bulletins_mailetuds_choice", "args": {"formsemestre_id": formsemestre_id}, "enabled": sco_bulletins.can_send_bulletin_by_mail(formsemestre_id), }, { "title": "Calendrier des évaluations", "endpoint": "notes.formsemestre_evaluations_cal", "args": {"formsemestre_id": formsemestre_id}, }, { "title": "Lister toutes les saisies de notes", "endpoint": "notes.formsemestre_list_saisies_notes", "args": {"formsemestre_id": formsemestre_id}, }, ] menuJury = [ { "title": "Voir les décisions du jury", "endpoint": "notes.formsemestre_pvjury", "args": {"formsemestre_id": formsemestre_id}, }, { "title": "Générer feuille préparation Jury", "endpoint": "notes.feuille_preparation_jury", "args": {"formsemestre_id": formsemestre_id}, }, { "title": "Saisie des décisions du jury", "endpoint": "notes.formsemestre_recapcomplet", "args": { "formsemestre_id": formsemestre_id, "modejury": 1, }, "enabled": sco_permissions_check.can_validate_sem(formsemestre_id), }, { "title": "Éditer les PV et archiver les résultats", "endpoint": "notes.formsemestre_archive", "args": {"formsemestre_id": formsemestre_id}, "enabled": sco_permissions_check.can_edit_pv(formsemestre_id), }, { "title": "Documents archivés", "endpoint": "notes.formsemestre_list_archives", "args": {"formsemestre_id": formsemestre_id}, "enabled": sco_archives.PVArchive.list_obj_archives(formsemestre_id), }, ] menuStats = _build_menu_stats(formsemestre_id) H = [ #
', ' | ", #'
{group["label"]} | ({n_members} étudiants) | """ ) if with_absences: H.append(form_abs_tmpl % group) H.append("
Aucun groupe dans cette partition') if sco_groups.sco_permissions_check.can_change_groups(formsemestre_id): H.append( f""" (créer)""" ) H.append("
") if sco_groups.sco_permissions_check.can_change_groups(formsemestre_id): H.append( f"""Formation: | {formation.titre} """, ] if sem.semestre_id >= 0: H.append(", %s %s" % (parcours.SESSION_NAME, sem.semestre_id)) if sem.modalite: H.append(f" en {sem.modalite}") if sem.etapes: H.append( f""" (étape { sem.etapes_apo_str() or "-" })""" ) H.append(" |
Parcours: | {', '.join(parcours.code for parcours in sem.parcours)} |
Évaluations: | %(nb_evals_completes)s ok, %(nb_evals_en_cours)s en cours, %(nb_evals_vides)s vides' % evals ) if evals["last_modif"]: H.append( " (dernière note saisie le %s)" % evals["last_modif"].strftime("%d/%m/%Y à %Hh%M") ) H.append(" |
Il y a des notes en attente ! Le classement des étudiants n'a qu'une valeur indicative. |
' + sem_warning + "
") if sem.semestre_id >= 0 and not sem.est_sur_une_annee(): H.append( 'Attention: ce semestre couvre plusieurs années scolaires !
' ) return "".join(H) def formsemestre_status(formsemestre_id=None): """Tableau de bord semestre HTML""" # porté du DTML sem = sco_formsemestre.get_formsemestre(formsemestre_id, raise_soft_exc=True) modimpls = sco_moduleimpl.moduleimpl_withmodule_list( formsemestre_id=formsemestre_id ) formsemestre = FormSemestre.query.get_or_404(formsemestre_id) nt = res_sem.load_formsemestre_results(formsemestre) # Construit la liste de tous les enseignants de ce semestre: mails_enseignants = set( [sco_users.user_info(ens_id)["email"] for ens_id in sem["responsables"]] ) for modimpl in modimpls: mails_enseignants.add(sco_users.user_info(modimpl["responsable_id"])["email"]) mails_enseignants |= set( [sco_users.user_info(m["ens_id"])["email"] for m in modimpl["ens"]] ) can_edit = sco_formsemestre_edit.can_edit_sem(formsemestre_id, sem=sem) use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id) H = [ html_sco_header.sco_header( page_title=f"{formsemestre.sem_modalite()} {formsemestre.titre_annee()}" ), 'Tableau de bord: cliquez sur un module pour saisir des notes
""", ] if nt.expr_diagnostics: H.append(html_expr_diagnostic(nt.expr_diagnostics)) if nt.parcours.APC_SAE: # BUT: tableau ressources puis SAE ressources = [ m for m in modimpls if m["module"]["module_type"] == ModuleType.RESSOURCE ] saes = [m for m in modimpls if m["module"]["module_type"] == ModuleType.SAE] autres = [ m for m in modimpls if m["module"]["module_type"] not in (ModuleType.RESSOURCE, ModuleType.SAE) ] H += [ """", _TABLEAU_MODULES_HEAD, formsemestre_tableau_modules( modimpls, nt, formsemestre_id, can_edit=can_edit, use_ue_coefs=use_ue_coefs, ), _TABLEAU_MODULES_FOOT, "
", ] if use_ue_coefs and not formsemestre.formation.is_apc(): H.append( """utilise les coefficients d'UE pour calculer la moyenne générale.
""" ) # --- LISTE DES ETUDIANTS H += [ 'Courrier aux %d enseignants du semestre
' % (",".join(adrlist), len(adrlist)) ) return "".join(H) + html_sco_header.sco_footer() _TABLEAU_MODULES_HEAD = """Code | Module | Inscrits | Responsable | Coefs. | Évaluations |
---|