2022-04-20 22:55:40 +02:00
|
|
|
# -*- mode: python -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# Gestion scolarite IUT
|
|
|
|
#
|
2023-01-02 13:16:27 +01:00
|
|
|
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
2022-04-20 22:55:40 +02:00
|
|
|
#
|
|
|
|
# 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
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
|
|
|
"""Table recap formation (avec champs éditables)
|
|
|
|
"""
|
2022-04-20 23:47:46 +02:00
|
|
|
import io
|
|
|
|
from zipfile import ZipFile, BadZipfile
|
|
|
|
|
2022-04-21 14:33:11 +02:00
|
|
|
from flask import Response
|
2022-04-20 23:47:46 +02:00
|
|
|
from flask import send_file, url_for
|
2022-04-20 22:55:40 +02:00
|
|
|
from flask import g, request
|
|
|
|
from flask_login import current_user
|
|
|
|
|
2023-07-11 06:57:38 +02:00
|
|
|
from app.models import Formation, FormSemestre, Matiere, Module, UniteEns
|
2022-04-20 22:55:40 +02:00
|
|
|
|
|
|
|
from app.scodoc.gen_tables import GenTable
|
|
|
|
from app.scodoc.sco_permissions import Permission
|
|
|
|
from app.scodoc import sco_preferences
|
|
|
|
import app.scodoc.sco_utils as scu
|
|
|
|
|
|
|
|
|
|
|
|
# ---- Table recap formation
|
2022-04-21 14:33:11 +02:00
|
|
|
def formation_table_recap(formation_id, format="html") -> Response:
|
2022-04-20 22:55:40 +02:00
|
|
|
"""Table recapitulant formation."""
|
|
|
|
T = []
|
|
|
|
formation = Formation.query.get_or_404(formation_id)
|
|
|
|
ues = formation.ues.order_by(UniteEns.semestre_idx, UniteEns.numero)
|
|
|
|
can_edit = current_user.has_permission(Permission.ScoChangeFormation)
|
|
|
|
li = 0
|
|
|
|
for ue in ues:
|
|
|
|
# L'UE
|
|
|
|
T.append(
|
|
|
|
{
|
|
|
|
"sem": f"S{ue.semestre_idx}" if ue.semestre_idx is not None else "-",
|
|
|
|
"_sem_order": f"{li:04d}",
|
|
|
|
"code": ue.acronyme,
|
|
|
|
"titre": ue.titre or "",
|
2022-04-20 23:47:46 +02:00
|
|
|
"_titre_target": url_for(
|
|
|
|
"notes.ue_edit",
|
|
|
|
scodoc_dept=g.scodoc_dept,
|
|
|
|
ue_id=ue.id,
|
|
|
|
)
|
|
|
|
if can_edit
|
|
|
|
else None,
|
2022-04-20 22:55:40 +02:00
|
|
|
"apo": ue.code_apogee or "",
|
|
|
|
"_apo_td_attrs": f""" data-oid="{ue.id}" data-value="{ue.code_apogee or ''}" """,
|
|
|
|
"coef": ue.coefficient or "",
|
|
|
|
"ects": ue.ects,
|
2022-04-21 13:59:53 +02:00
|
|
|
"_css_row_class": "ue",
|
2022-04-20 22:55:40 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
li += 1
|
|
|
|
matieres = ue.matieres.order_by(Matiere.numero)
|
|
|
|
for mat in matieres:
|
|
|
|
modules = mat.modules.order_by(Module.numero)
|
|
|
|
for mod in modules:
|
|
|
|
nb_moduleimpls = mod.modimpls.count()
|
|
|
|
# le module (ou ressource ou sae)
|
|
|
|
T.append(
|
|
|
|
{
|
|
|
|
"sem": f"S{mod.semestre_id}"
|
|
|
|
if mod.semestre_id is not None
|
|
|
|
else "-",
|
|
|
|
"_sem_order": f"{li:04d}",
|
|
|
|
"code": mod.code,
|
|
|
|
"titre": mod.abbrev or mod.titre,
|
|
|
|
"_titre_target": url_for(
|
|
|
|
"notes.module_edit",
|
|
|
|
scodoc_dept=g.scodoc_dept,
|
|
|
|
module_id=mod.id,
|
|
|
|
)
|
|
|
|
if can_edit
|
|
|
|
else None,
|
|
|
|
"apo": mod.code_apogee,
|
|
|
|
"_apo_td_attrs": f""" data-oid="{mod.id}" data-value="{mod.code_apogee or ''}" """,
|
|
|
|
"coef": mod.coefficient,
|
|
|
|
"nb_moduleimpls": nb_moduleimpls,
|
|
|
|
"heures_cours": mod.heures_cours,
|
|
|
|
"heures_td": mod.heures_td,
|
|
|
|
"heures_tp": mod.heures_tp,
|
|
|
|
"_css_row_class": f"mod {mod.type_abbrv()}",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
columns_ids = [
|
|
|
|
"sem",
|
|
|
|
"code",
|
|
|
|
"apo",
|
|
|
|
# "mat", inutile d'afficher la matière
|
|
|
|
"titre",
|
|
|
|
"ects",
|
|
|
|
"nb_moduleimpls",
|
|
|
|
"heures_cours",
|
|
|
|
"heures_td",
|
|
|
|
"heures_tp",
|
|
|
|
]
|
2022-09-06 15:21:32 +02:00
|
|
|
if not formation.is_apc():
|
|
|
|
columns_ids.insert(columns_ids.index("ects"), "coef")
|
2022-04-20 22:55:40 +02:00
|
|
|
titles = {
|
|
|
|
"ue": "UE",
|
|
|
|
"mat": "Matière",
|
|
|
|
"titre": "Titre",
|
|
|
|
"code": "Code",
|
|
|
|
"apo": "Apo",
|
|
|
|
"coef": "Coef.",
|
|
|
|
"sem": "Sem.",
|
|
|
|
"nb_moduleimpls": "Nb utilisé",
|
|
|
|
"heures_cours": "Cours (h)",
|
|
|
|
"heures_td": "TD (h)",
|
|
|
|
"heures_tp": "TP (h)",
|
|
|
|
"ects": "ECTS",
|
|
|
|
}
|
|
|
|
|
|
|
|
title = f"""Formation {formation.titre} ({formation.acronyme})
|
|
|
|
[version {formation.version}] code {formation.formation_code}"""
|
|
|
|
html_class = "stripe cell-border compact hover order-column formation_table_recap"
|
|
|
|
if current_user.has_permission(Permission.ScoEditApo):
|
|
|
|
html_class += " apo_editable"
|
|
|
|
|
|
|
|
tab = GenTable(
|
|
|
|
columns_ids=columns_ids,
|
|
|
|
rows=T,
|
|
|
|
titles=titles,
|
|
|
|
origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}",
|
|
|
|
caption=title,
|
|
|
|
html_caption=title,
|
|
|
|
html_class=html_class,
|
|
|
|
html_class_ignore_default=True,
|
|
|
|
html_table_attrs=f"""
|
|
|
|
data-apo_ue_save_url="{url_for('notes.ue_set_apo', scodoc_dept=g.scodoc_dept)}"
|
|
|
|
data-apo_mod_save_url="{url_for('notes.module_set_apo', scodoc_dept=g.scodoc_dept)}"
|
|
|
|
""",
|
|
|
|
html_with_td_classes=True,
|
|
|
|
base_url=f"{request.base_url}?formation_id={formation_id}",
|
|
|
|
page_title=title,
|
|
|
|
html_title=f"<h2>{title}</h2>",
|
|
|
|
pdf_title=title,
|
|
|
|
preferences=sco_preferences.SemPreferences(),
|
|
|
|
table_id="formation_table_recap",
|
|
|
|
)
|
|
|
|
return tab.make_page(format=format, javascripts=["js/formation_recap.js"])
|
2022-04-20 23:47:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
def export_recap_formations_annee_scolaire(annee_scolaire):
|
|
|
|
"""Exporte un zip des recap (excel) des formatons de tous les semestres
|
|
|
|
de l'année scolaire indiquée.
|
|
|
|
"""
|
|
|
|
annee_scolaire = int(annee_scolaire)
|
|
|
|
data = io.BytesIO()
|
|
|
|
zip_file = ZipFile(data, "w")
|
|
|
|
formsemestres = FormSemestre.query.filter_by(dept_id=g.scodoc_dept_id).filter(
|
|
|
|
FormSemestre.date_debut >= scu.date_debut_anne_scolaire(annee_scolaire),
|
|
|
|
FormSemestre.date_debut <= scu.date_fin_anne_scolaire(annee_scolaire),
|
|
|
|
)
|
|
|
|
formation_ids = {formsemestre.formation.id for formsemestre in formsemestres}
|
|
|
|
for formation_id in formation_ids:
|
2023-07-11 06:57:38 +02:00
|
|
|
formation = db.session.get(Formation, formation_id)
|
2022-04-20 23:47:46 +02:00
|
|
|
xls = formation_table_recap(formation_id, format="xlsx").data
|
|
|
|
filename = (
|
|
|
|
scu.sanitize_filename(formation.get_titre_version()) + scu.XLSX_SUFFIX
|
|
|
|
)
|
|
|
|
zip_file.writestr(filename, xls)
|
|
|
|
zip_file.close()
|
|
|
|
data.seek(0)
|
|
|
|
return send_file(
|
|
|
|
data,
|
|
|
|
mimetype="application/zip",
|
|
|
|
download_name=f"formations-{g.scodoc_dept}-{annee_scolaire}-{annee_scolaire+1}.zip",
|
|
|
|
as_attachment=True,
|
|
|
|
)
|