# -*- 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@viennet.net # ############################################################################## """ScoDoc : gestion des fichiers archivés associés aux étudiants Il s'agit de fichiers quelconques, généralement utilisés pour conserver les dossiers d'admission et autres pièces utiles. """ import flask from flask import flash, render_template, url_for from flask import g, request from flask_login import current_user from app.models import Identite import app.scodoc.sco_utils as scu from app.scodoc import sco_import_etuds from app.scodoc import sco_groups from app.scodoc import sco_trombino from app.scodoc import sco_archives from app.scodoc.sco_permissions import Permission from app.scodoc.sco_exceptions import AccessDenied, ScoValueError from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc import html_sco_header from app.scodoc import sco_etud class EtudsArchiver(sco_archives.BaseArchiver): def __init__(self): sco_archives.BaseArchiver.__init__(self, archive_type="docetuds") # Global au processus, attention ! ETUDS_ARCHIVER = EtudsArchiver() def can_edit_etud_archive(authuser): """True si l'utilisateur peut modifier les archives etudiantes""" return authuser.has_permission(Permission.EtudAddAnnotations) def etud_list_archives_html(etud: Identite): """HTML snippet listing archives""" can_edit = can_edit_etud_archive(current_user) etud_archive_id = etud.id L = [] for archive_id in ETUDS_ARCHIVER.list_obj_archives( etud_archive_id, dept_id=etud.dept_id ): a = { "archive_id": archive_id, "description": ETUDS_ARCHIVER.get_archive_description( archive_id, dept_id=etud.dept_id ), "date": ETUDS_ARCHIVER.get_archive_date(archive_id), "content": ETUDS_ARCHIVER.list_archive(archive_id, dept_id=etud.dept_id), } L.append(a) delete_icon = scu.icontag( "delete_small_img", title="Supprimer fichier", alt="supprimer" ) delete_disabled_icon = scu.icontag( "delete_small_dis_img", title="Suppression non autorisée" ) H = ['
Le fichier ne doit pas dépasser %sMo.
""" % (scu.CONFIG.ETUD_MAX_FILE_SIZE // (1024 * 1024)), ] tf = TrivialFormulator( request.base_url, scu.get_request_args(), ( ("etudid", {"default": etudid, "input_type": "hidden"}), ("datafile", {"input_type": "file", "title": "Fichier", "size": 30}), ( "description", { "input_type": "textarea", "rows": 4, "cols": 77, "title": "Description", }, ), ), submitlabel="Valider", cancelbutton="Annuler", ) if tf[0] == 0: return "\n".join(H) + tf[1] + html_sco_header.sco_footer() elif tf[0] == -1: return flask.redirect( url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid) ) else: data = tf[2]["datafile"].read() descr = tf[2]["description"] filename = tf[2]["datafile"].filename etud_archive_id = etud["etudid"] _store_etud_file_to_new_archive( etud_archive_id, data, filename, description=descr ) return flask.redirect( url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid) ) def _store_etud_file_to_new_archive( etud_archive_id, data, filename, description="" ) -> tuple[bool, str]: """Store data to new archive.""" filesize = len(data) if filesize < 10 or filesize > scu.CONFIG.ETUD_MAX_FILE_SIZE: return False, f"Fichier archive '{filename}' de taille invalide ! ({filesize})" archive_id = ETUDS_ARCHIVER.create_obj_archive(etud_archive_id, description) ETUDS_ARCHIVER.store(archive_id, filename, data) return True, "ok" def etud_delete_archive(etudid, archive_name, dialog_confirmed=False): """Delete an archive""" # check permission if not can_edit_etud_archive(current_user): raise AccessDenied(f"opération non autorisée pour {current_user}") etuds = sco_etud.get_etud_info(filled=True) if not etuds: raise ScoValueError("étudiant inexistant") etud = etuds[0] etud_archive_id = etud["etudid"] archive_id = ETUDS_ARCHIVER.get_id_from_name( etud_archive_id, archive_name, dept_id=etud["dept_id"] ) if not dialog_confirmed: return scu.confirm_dialog( """Fichier associé le %s à l'étudiant %s
La suppression sera définitive.
""" % ( ETUDS_ARCHIVER.get_archive_date(archive_id).strftime("%d/%m/%Y %H:%M"), etud["nomprenom"], ), dest_url="", cancel_url=url_for( "scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid, head_message="annulation", ), parameters={"etudid": etudid, "archive_name": archive_name}, ) ETUDS_ARCHIVER.delete_archive(archive_id, dept_id=etud["dept_id"]) flash("Archive supprimée") return flask.redirect( url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid) ) def etud_get_archived_file(etudid, archive_name, filename): """Send file to client.""" etuds = sco_etud.get_etud_info(etudid=etudid, filled=True) if not etuds: raise ScoValueError("étudiant inexistant") etud = etuds[0] etud_archive_id = etud["etudid"] return ETUDS_ARCHIVER.get_archived_file( etud_archive_id, archive_name, filename, dept_id=etud["dept_id"] ) # --- Upload d'un ensemble de fichiers (pour un groupe d'étudiants) def etudarchive_generate_excel_sample(group_id=None): """Feuille excel pour import fichiers etudiants (utilisé pour admissions)""" fmt = sco_import_etuds.sco_import_format() data = sco_import_etuds.sco_import_generate_excel_sample( fmt, group_ids=[group_id], only_tables=["identite"], exclude_cols=[ "date_naissance", "lieu_naissance", "nationalite", "statut", "photo_filename", ], extra_cols=["fichier_a_charger"], ) return scu.send_file( data, "ImportFichiersEtudiants", suffix=scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE, ) def etudarchive_import_files_form(group_id): """Formulaire pour importation fichiers d'un groupe""" H = [ html_sco_header.sco_header( page_title="Import de fichiers associés aux étudiants" ), """Les fichiers associés (dossiers d'admission, certificats, ...), de types quelconques (pdf, doc, images) sont accessibles aux utilisateurs via la fiche individuelle de l'étudiant.
Ne pas confondre avec les photos des étudiants, qui se chargent via l'onglet "Photos".
Vous pouvez aussi charger à tout moment de nouveaux fichiers, ou en supprimer, via la fiche de chaque étudiant.
Cette page permet de charger en une seule fois les fichiers
de plusieurs étudiants.
Il faut d'abord remplir une feuille excel donnant les noms
des fichiers (un fichier par étudiant).
Ensuite, réunir vos fichiers dans un fichier zip, puis télécharger simultanément le fichier excel et le fichier zip.