2020-09-26 16:19:37 +02:00
|
|
|
# -*- mode: python -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# Gestion scolarite IUT
|
|
|
|
#
|
2022-01-01 14:49:42 +01:00
|
|
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
2020-09-26 16:19:37 +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
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
2022-02-06 16:09:17 +01:00
|
|
|
"""Tableau récapitulatif des notes d'un semestre
|
2020-09-26 16:19:37 +02:00
|
|
|
"""
|
2021-02-04 20:02:44 +01:00
|
|
|
import datetime
|
2021-09-16 00:15:10 +02:00
|
|
|
import time
|
2021-07-10 17:40:40 +02:00
|
|
|
from xml.etree import ElementTree
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2022-03-23 22:30:22 +01:00
|
|
|
from flask import g, request
|
|
|
|
from flask import make_response, url_for
|
2021-09-18 10:10:02 +02:00
|
|
|
|
2021-08-29 19:57:32 +02:00
|
|
|
from app import log
|
2021-12-11 20:27:58 +01:00
|
|
|
from app.but import bulletin_but
|
2022-01-08 18:06:00 +01:00
|
|
|
from app.comp import res_sem
|
2022-03-27 22:25:00 +02:00
|
|
|
from app.comp.res_compat import NotesTableCompat
|
2021-12-17 21:59:28 +01:00
|
|
|
from app.models import FormSemestre
|
|
|
|
from app.models.etudiants import Identite
|
2022-02-06 16:09:17 +01:00
|
|
|
from app.models.evaluations import Evaluation
|
2021-12-11 20:27:58 +01:00
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
from app.scodoc.gen_tables import GenTable
|
2021-12-11 20:27:58 +01:00
|
|
|
import app.scodoc.sco_utils as scu
|
2021-06-19 23:21:37 +02:00
|
|
|
from app.scodoc import html_sco_header
|
|
|
|
from app.scodoc import sco_bulletins_json
|
|
|
|
from app.scodoc import sco_bulletins_xml
|
|
|
|
from app.scodoc import sco_bulletins, sco_excel
|
2022-04-05 22:23:55 +02:00
|
|
|
from app.scodoc import sco_cache
|
2021-06-19 23:21:37 +02:00
|
|
|
from app.scodoc import sco_codes_parcours
|
|
|
|
from app.scodoc import sco_evaluations
|
2021-11-12 22:17:46 +01:00
|
|
|
from app.scodoc import sco_evaluation_db
|
2022-04-06 18:51:01 +02:00
|
|
|
from app.scodoc.sco_exceptions import ScoValueError
|
2021-06-19 23:21:37 +02:00
|
|
|
from app.scodoc import sco_formations
|
|
|
|
from app.scodoc import sco_formsemestre
|
|
|
|
from app.scodoc import sco_formsemestre_status
|
|
|
|
from app.scodoc import sco_groups
|
|
|
|
from app.scodoc import sco_permissions_check
|
|
|
|
from app.scodoc import sco_preferences
|
|
|
|
from app.scodoc import sco_etud
|
2021-07-03 23:35:32 +02:00
|
|
|
from app.scodoc import sco_users
|
2021-07-10 17:40:40 +02:00
|
|
|
from app.scodoc import sco_xml
|
2021-06-19 23:21:37 +02:00
|
|
|
from app.scodoc.sco_codes_parcours import DEF, UE_SPORT
|
2020-09-26 16:19:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
def formsemestre_recapcomplet(
|
|
|
|
formsemestre_id=None,
|
|
|
|
modejury=False, # affiche lien saisie decision jury
|
|
|
|
tabformat="html",
|
|
|
|
sortcol=None,
|
|
|
|
xml_with_decisions=False, # XML avec decisions
|
|
|
|
rank_partition_id=None, # si None, calcul rang global
|
2020-12-12 17:22:54 +01:00
|
|
|
force_publishing=True, # publie les XML/JSON meme si bulletins non publiés
|
2020-09-26 16:19:37 +02:00
|
|
|
):
|
|
|
|
"""Page récapitulant les notes d'un semestre.
|
|
|
|
Grand tableau récapitulatif avec toutes les notes de modules
|
|
|
|
pour tous les étudiants, les moyennes par UE et générale,
|
|
|
|
trié par moyenne générale décroissante.
|
2022-04-06 18:51:01 +02:00
|
|
|
|
|
|
|
tabformat:
|
|
|
|
html : page web
|
|
|
|
evals : page web, avec toutes les évaluations dans le tableau
|
|
|
|
xls, xlsx: export excel simple
|
|
|
|
xlsall : export excel simple, avec toutes les évaluations dans le tableau
|
|
|
|
csv : export CSV, avec toutes les évaluations
|
|
|
|
xml, json : concaténation de tous les bulletins, au format demandé
|
|
|
|
pdf : NON SUPPORTE (car tableau trop grand pour générer un pdf utilisable)
|
|
|
|
|
|
|
|
modejury: cache modules, affiche lien saisie decision jury
|
|
|
|
|
2020-09-26 16:19:37 +02:00
|
|
|
"""
|
2021-12-11 20:27:58 +01:00
|
|
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
2022-04-06 18:51:01 +02:00
|
|
|
|
2020-09-26 16:19:37 +02:00
|
|
|
modejury = int(modejury)
|
2022-04-06 18:51:01 +02:00
|
|
|
|
2020-09-26 16:19:37 +02:00
|
|
|
xml_with_decisions = int(xml_with_decisions)
|
2020-12-12 17:22:54 +01:00
|
|
|
force_publishing = int(force_publishing)
|
2022-04-06 18:51:01 +02:00
|
|
|
is_file = tabformat in {"csv", "json", "xls", "xlsx", "xlsall", "xml"}
|
2020-09-26 16:19:37 +02:00
|
|
|
H = []
|
2022-04-06 18:51:01 +02:00
|
|
|
if not is_file:
|
2020-09-26 16:19:37 +02:00
|
|
|
H += [
|
2021-06-13 23:37:14 +02:00
|
|
|
html_sco_header.sco_header(
|
2020-09-26 16:19:37 +02:00
|
|
|
page_title="Récapitulatif",
|
|
|
|
no_side_bar=True,
|
|
|
|
init_qtip=True,
|
2022-03-26 23:33:57 +01:00
|
|
|
javascripts=["js/etud_info.js", "js/table_recap.js"],
|
2020-09-26 16:19:37 +02:00
|
|
|
),
|
|
|
|
sco_formsemestre_status.formsemestre_status_head(
|
2021-09-27 10:20:10 +02:00
|
|
|
formsemestre_id=formsemestre_id
|
2020-09-26 16:19:37 +02:00
|
|
|
),
|
|
|
|
]
|
2022-03-27 23:19:17 +02:00
|
|
|
if len(formsemestre.inscriptions) > 0:
|
2022-04-06 18:51:01 +02:00
|
|
|
H.append(
|
|
|
|
f"""<form name="f" method="get" action="{request.base_url}">
|
|
|
|
<input type="hidden" name="formsemestre_id" value="{formsemestre_id}"></input>
|
|
|
|
"""
|
|
|
|
)
|
2022-03-27 23:19:17 +02:00
|
|
|
if modejury:
|
|
|
|
H.append(
|
2022-04-06 18:51:01 +02:00
|
|
|
f'<input type="hidden" name="modejury" value="{modejury}"></input>'
|
2022-03-27 23:19:17 +02:00
|
|
|
)
|
2020-09-26 16:19:37 +02:00
|
|
|
H.append(
|
2022-03-27 23:19:17 +02:00
|
|
|
'<select name="tabformat" onchange="document.f.submit()" class="noprint">'
|
|
|
|
)
|
|
|
|
for (format, label) in (
|
2022-04-04 09:35:52 +02:00
|
|
|
("html", "Tableau"),
|
|
|
|
("evals", "Avec toutes les évaluations"),
|
|
|
|
("xml", "Bulletins XML (obsolète)"),
|
|
|
|
("json", "Bulletins JSON"),
|
2022-03-27 23:19:17 +02:00
|
|
|
):
|
|
|
|
if format == tabformat:
|
|
|
|
selected = " selected"
|
|
|
|
else:
|
|
|
|
selected = ""
|
2022-04-06 18:51:01 +02:00
|
|
|
H.append(f'<option value="{format}"{selected}>{label}</option>')
|
2022-03-27 23:19:17 +02:00
|
|
|
H.append("</select>")
|
|
|
|
|
|
|
|
H.append(
|
2022-04-06 18:51:01 +02:00
|
|
|
f""" (cliquer sur un nom pour afficher son bulletin ou <a class="stdlink"
|
|
|
|
href="{url_for('notes.formsemestre_bulletins_pdf',
|
|
|
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
|
|
|
|
}">ici avoir le classeur papier</a>)
|
2022-03-27 23:30:56 +02:00
|
|
|
"""
|
2020-09-26 16:19:37 +02:00
|
|
|
)
|
|
|
|
|
2021-09-27 10:20:10 +02:00
|
|
|
data = do_formsemestre_recapcomplet(
|
|
|
|
formsemestre_id,
|
|
|
|
format=tabformat,
|
|
|
|
modejury=modejury,
|
|
|
|
sortcol=sortcol,
|
|
|
|
xml_with_decisions=xml_with_decisions,
|
|
|
|
rank_partition_id=rank_partition_id,
|
|
|
|
force_publishing=force_publishing,
|
2020-09-26 16:19:37 +02:00
|
|
|
)
|
2021-09-27 10:20:10 +02:00
|
|
|
if tabformat == "xml":
|
|
|
|
response = make_response(data)
|
|
|
|
response.headers["Content-Type"] = scu.XML_MIMETYPE
|
|
|
|
return response
|
|
|
|
H.append(data)
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
if not is_file:
|
2022-03-27 23:19:17 +02:00
|
|
|
if len(formsemestre.inscriptions) > 0:
|
|
|
|
H.append("</form>")
|
2020-09-26 16:19:37 +02:00
|
|
|
H.append(
|
2022-04-06 18:51:01 +02:00
|
|
|
f"""<p><a class="stdlink" href="{url_for('notes.formsemestre_pvjury',
|
|
|
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
|
|
|
|
}">Voir les décisions du jury</a></p>"""
|
2020-09-26 16:19:37 +02:00
|
|
|
)
|
2022-03-27 23:19:17 +02:00
|
|
|
if sco_permissions_check.can_validate_sem(formsemestre_id):
|
|
|
|
H.append("<p>")
|
|
|
|
if modejury:
|
|
|
|
H.append(
|
2022-04-06 18:51:01 +02:00
|
|
|
f"""<a class="stdlink" href="{url_for('formsemestre_validation_auto',
|
|
|
|
formsemestre_id=formsemestre_id)
|
|
|
|
}">Calcul automatique des décisions du jury</a></p>"""
|
2022-03-27 23:19:17 +02:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
H.append(
|
2022-04-06 18:51:01 +02:00
|
|
|
f"""<a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet',
|
|
|
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, modejury=1)
|
|
|
|
}">Saisie des décisions du jury</a>"""
|
2022-03-27 23:19:17 +02:00
|
|
|
)
|
|
|
|
H.append("</p>")
|
|
|
|
if sco_preferences.get_preference("use_ue_coefs", formsemestre_id):
|
|
|
|
H.append(
|
|
|
|
"""
|
|
|
|
<p class="infop">utilise les coefficients d'UE pour calculer la moyenne générale.</p>
|
|
|
|
"""
|
|
|
|
)
|
2021-07-29 10:19:00 +02:00
|
|
|
H.append(html_sco_header.sco_footer())
|
2021-08-21 16:51:08 +02:00
|
|
|
# HTML or binary data ?
|
|
|
|
if len(H) > 1:
|
|
|
|
return "".join(H)
|
|
|
|
elif len(H) == 1:
|
|
|
|
return H[0]
|
|
|
|
else:
|
|
|
|
return H
|
2020-09-26 16:19:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
def do_formsemestre_recapcomplet(
|
|
|
|
formsemestre_id=None,
|
2020-12-02 01:00:23 +01:00
|
|
|
format="html", # html, xml, xls, xlsall, json
|
2020-09-26 16:19:37 +02:00
|
|
|
hidemodules=False, # ne pas montrer les modules (ignoré en XML)
|
|
|
|
hidebac=False, # pas de colonne Bac (ignoré en XML)
|
|
|
|
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
|
|
|
|
modejury=False, # saisie décisions jury
|
|
|
|
sortcol=None, # indice colonne a trier dans table T
|
|
|
|
xml_with_decisions=False,
|
|
|
|
disable_etudlink=False,
|
|
|
|
rank_partition_id=None, # si None, calcul rang global
|
2020-12-12 17:22:54 +01:00
|
|
|
force_publishing=True,
|
2020-09-26 16:19:37 +02:00
|
|
|
):
|
2020-12-02 01:00:23 +01:00
|
|
|
"""Calcule et renvoie le tableau récapitulatif."""
|
2022-03-26 23:33:57 +01:00
|
|
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
2022-04-06 18:51:01 +02:00
|
|
|
|
|
|
|
filename = scu.sanitize_filename(
|
|
|
|
f"""recap-{formsemestre.titre_num()}-{time.strftime("%Y-%m-%d")}"""
|
|
|
|
)
|
|
|
|
|
2022-04-04 09:35:52 +02:00
|
|
|
if (format == "html" or format == "evals") and not modejury:
|
2022-03-27 22:25:00 +02:00
|
|
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
2022-04-06 18:51:01 +02:00
|
|
|
data = gen_formsemestre_recapcomplet_html(
|
|
|
|
formsemestre,
|
|
|
|
res,
|
|
|
|
include_evaluations=(format == "evals"),
|
|
|
|
filename=filename,
|
2022-03-26 23:33:57 +01:00
|
|
|
)
|
2020-09-26 16:19:37 +02:00
|
|
|
return data
|
2022-04-06 18:51:01 +02:00
|
|
|
elif format.startswith("xls") or format == "csv":
|
|
|
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
|
|
|
include_evaluations = format in {"xlsall", "csv "}
|
|
|
|
if format != "csv":
|
|
|
|
format = "xlsx"
|
|
|
|
data, filename = gen_formsemestre_recapcomplet_excel(
|
|
|
|
formsemestre,
|
|
|
|
res,
|
|
|
|
include_evaluations=include_evaluations,
|
|
|
|
format=format,
|
|
|
|
filename=filename,
|
2021-09-16 00:15:10 +02:00
|
|
|
)
|
2022-04-06 18:51:01 +02:00
|
|
|
return scu.send_file(data, filename=filename, mime=scu.get_mime_suffix(format))
|
|
|
|
elif format == "xml":
|
|
|
|
data = gen_formsemestre_recapcomplet_xml(
|
2020-12-12 17:22:54 +01:00
|
|
|
formsemestre_id,
|
|
|
|
xml_nodate,
|
|
|
|
xml_with_decisions=xml_with_decisions,
|
|
|
|
force_publishing=force_publishing,
|
2020-09-26 16:19:37 +02:00
|
|
|
)
|
2022-04-06 18:51:01 +02:00
|
|
|
return scu.send_file(data, filename=filename, suffix=scu.XML_SUFFIX)
|
2020-12-02 01:00:23 +01:00
|
|
|
elif format == "json":
|
2022-04-06 18:51:01 +02:00
|
|
|
data = gen_formsemestre_recapcomplet_json(
|
2020-12-12 17:22:54 +01:00
|
|
|
formsemestre_id,
|
|
|
|
xml_nodate=xml_nodate,
|
|
|
|
xml_with_decisions=xml_with_decisions,
|
|
|
|
force_publishing=force_publishing,
|
2020-12-02 01:00:23 +01:00
|
|
|
)
|
2022-04-06 18:51:01 +02:00
|
|
|
return scu.sendJSON(data, filename=filename)
|
2022-03-23 22:30:22 +01:00
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
raise ScoValueError(f"Format demandé invalide: {format}")
|
2020-09-26 16:19:37 +02:00
|
|
|
|
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
def gen_formsemestre_recapcomplet_xml(
|
2020-12-12 17:22:54 +01:00
|
|
|
formsemestre_id,
|
|
|
|
xml_nodate,
|
|
|
|
xml_with_decisions=False,
|
|
|
|
force_publishing=True,
|
2022-04-06 18:51:01 +02:00
|
|
|
) -> str:
|
2020-12-02 01:00:23 +01:00
|
|
|
"XML export: liste tous les bulletins XML."
|
2022-02-12 22:57:46 +01:00
|
|
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
|
|
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
2020-09-26 16:19:37 +02:00
|
|
|
T = nt.get_table_moyennes_triees()
|
|
|
|
if not T:
|
|
|
|
return "", "", "xml"
|
|
|
|
|
|
|
|
if xml_nodate:
|
|
|
|
docdate = ""
|
|
|
|
else:
|
|
|
|
docdate = datetime.datetime.now().isoformat()
|
2021-07-10 17:40:40 +02:00
|
|
|
doc = ElementTree.Element(
|
2021-08-22 17:18:15 +02:00
|
|
|
"recapsemestre", formsemestre_id=str(formsemestre_id), date=docdate
|
2021-07-10 17:40:40 +02:00
|
|
|
)
|
2021-07-29 10:19:00 +02:00
|
|
|
evals = sco_evaluations.do_evaluation_etat_in_sem(formsemestre_id)
|
2021-07-10 17:40:40 +02:00
|
|
|
doc.append(
|
|
|
|
ElementTree.Element(
|
|
|
|
"evals_info",
|
|
|
|
nb_evals_completes=str(evals["nb_evals_completes"]),
|
|
|
|
nb_evals_en_cours=str(evals["nb_evals_en_cours"]),
|
|
|
|
nb_evals_vides=str(evals["nb_evals_vides"]),
|
|
|
|
date_derniere_note=str(evals["last_modif"]),
|
|
|
|
)
|
2020-09-26 16:19:37 +02:00
|
|
|
)
|
|
|
|
for t in T:
|
|
|
|
etudid = t[-1]
|
|
|
|
sco_bulletins_xml.make_xml_formsemestre_bulletinetud(
|
|
|
|
formsemestre_id,
|
|
|
|
etudid,
|
|
|
|
doc=doc,
|
2020-12-12 17:22:54 +01:00
|
|
|
force_publishing=force_publishing,
|
2020-09-26 16:19:37 +02:00
|
|
|
xml_nodate=xml_nodate,
|
|
|
|
xml_with_decisions=xml_with_decisions,
|
|
|
|
)
|
2022-04-06 18:51:01 +02:00
|
|
|
return ElementTree.tostring(doc).decode(scu.SCO_ENCODING)
|
2020-12-02 01:00:23 +01:00
|
|
|
|
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
def gen_formsemestre_recapcomplet_json(
|
2020-12-12 17:22:54 +01:00
|
|
|
formsemestre_id,
|
|
|
|
xml_nodate=False,
|
|
|
|
xml_with_decisions=False,
|
|
|
|
force_publishing=True,
|
2022-04-06 18:51:01 +02:00
|
|
|
) -> dict:
|
2020-12-12 17:22:54 +01:00
|
|
|
"""JSON export: liste tous les bulletins JSON
|
|
|
|
:param xml_nodate(bool): indique la date courante (attribut docdate)
|
|
|
|
:param force_publishing: donne les bulletins même si non "publiés sur portail"
|
2022-04-06 18:51:01 +02:00
|
|
|
:returns: dict
|
2020-12-12 17:22:54 +01:00
|
|
|
"""
|
2021-12-17 21:59:28 +01:00
|
|
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
|
|
|
is_apc = formsemestre.formation.is_apc()
|
|
|
|
|
2020-12-02 01:00:23 +01:00
|
|
|
if xml_nodate:
|
|
|
|
docdate = ""
|
|
|
|
else:
|
|
|
|
docdate = datetime.datetime.now().isoformat()
|
2021-07-29 10:19:00 +02:00
|
|
|
evals = sco_evaluations.do_evaluation_etat_in_sem(formsemestre_id)
|
2022-04-06 18:51:01 +02:00
|
|
|
js_data = {
|
2020-12-02 01:00:23 +01:00
|
|
|
"docdate": docdate,
|
|
|
|
"formsemestre_id": formsemestre_id,
|
|
|
|
"evals_info": {
|
|
|
|
"nb_evals_completes": evals["nb_evals_completes"],
|
|
|
|
"nb_evals_en_cours": evals["nb_evals_en_cours"],
|
|
|
|
"nb_evals_vides": evals["nb_evals_vides"],
|
|
|
|
"date_derniere_note": evals["last_modif"],
|
|
|
|
},
|
|
|
|
"bulletins": [],
|
|
|
|
}
|
2022-04-06 18:51:01 +02:00
|
|
|
bulletins = js_data["bulletins"]
|
2022-02-12 22:57:46 +01:00
|
|
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
|
|
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
2020-12-02 01:00:23 +01:00
|
|
|
T = nt.get_table_moyennes_triees()
|
|
|
|
for t in T:
|
|
|
|
etudid = t[-1]
|
2021-12-17 21:59:28 +01:00
|
|
|
if is_apc:
|
|
|
|
etud = Identite.query.get(etudid)
|
2021-12-24 00:08:25 +01:00
|
|
|
r = bulletin_but.BulletinBUT(formsemestre)
|
2021-12-17 21:59:28 +01:00
|
|
|
bul = r.bulletin_etud(etud, formsemestre)
|
|
|
|
else:
|
|
|
|
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
|
2020-12-02 01:00:23 +01:00
|
|
|
formsemestre_id,
|
|
|
|
etudid,
|
2020-12-12 17:22:54 +01:00
|
|
|
force_publishing=force_publishing,
|
2020-12-02 01:00:23 +01:00
|
|
|
xml_with_decisions=xml_with_decisions,
|
|
|
|
)
|
2021-12-17 21:59:28 +01:00
|
|
|
bulletins.append(bul)
|
2022-04-06 18:51:01 +02:00
|
|
|
return js_data
|
2020-12-12 17:22:54 +01:00
|
|
|
|
|
|
|
|
2021-09-27 10:20:10 +02:00
|
|
|
def formsemestres_bulletins(annee_scolaire):
|
2020-12-12 17:22:54 +01:00
|
|
|
"""Tous les bulletins des semestres publiés des semestres de l'année indiquée.
|
2022-02-09 23:22:00 +01:00
|
|
|
:param annee_scolaire(int): année de début de l'année scolaire
|
2020-12-12 17:22:54 +01:00
|
|
|
:returns: JSON
|
|
|
|
"""
|
2022-04-06 18:51:01 +02:00
|
|
|
js_list = []
|
2021-08-19 10:28:35 +02:00
|
|
|
sems = sco_formsemestre.list_formsemestre_by_etape(annee_scolaire=annee_scolaire)
|
2020-12-12 17:22:54 +01:00
|
|
|
log("formsemestres_bulletins(%s): %d sems" % (annee_scolaire, len(sems)))
|
|
|
|
for sem in sems:
|
2022-04-06 18:51:01 +02:00
|
|
|
js_data = gen_formsemestre_recapcomplet_json(
|
2021-08-21 00:24:51 +02:00
|
|
|
sem["formsemestre_id"], force_publishing=False
|
2020-12-12 17:22:54 +01:00
|
|
|
)
|
2022-04-06 18:51:01 +02:00
|
|
|
js_list.append(js_data)
|
2020-12-12 17:22:54 +01:00
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
return scu.sendJSON(js_list)
|
2022-03-26 23:33:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _gen_cell(key: str, row: dict, elt="td"):
|
|
|
|
"html table cell"
|
|
|
|
klass = row.get(f"_{key}_class")
|
|
|
|
attrs = f'class="{klass}"' if klass else ""
|
2022-03-27 10:05:12 +02:00
|
|
|
order = row.get(f"_{key}_order")
|
2022-03-26 23:33:57 +01:00
|
|
|
if order:
|
|
|
|
attrs += f' data-order="{order}"'
|
2022-03-27 10:49:45 +02:00
|
|
|
content = row.get(key, "")
|
|
|
|
target = row.get(f"_{key}_target")
|
2022-03-28 18:13:51 +02:00
|
|
|
target_attrs = row.get(f"_{key}_target_attrs", "")
|
|
|
|
if target or target_attrs: # avec lien
|
2022-03-27 18:49:15 +02:00
|
|
|
href = f'href="{target}"' if target else ""
|
2022-03-28 18:13:51 +02:00
|
|
|
content = f"<a {href} {target_attrs}>{content}</a>"
|
2022-03-27 10:49:45 +02:00
|
|
|
return f"<{elt} {attrs}>{content}</{elt}>"
|
2022-03-26 23:33:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _gen_row(keys: list[str], row, elt="td"):
|
|
|
|
klass = row.get("_tr_class")
|
|
|
|
tr_class = f'class="{klass}"' if klass else ""
|
|
|
|
return f'<tr {tr_class}>{"".join([_gen_cell(key, row, elt) for key in keys])}</tr>'
|
|
|
|
|
|
|
|
|
2022-03-27 22:25:00 +02:00
|
|
|
def gen_formsemestre_recapcomplet_html(
|
2022-04-06 18:51:01 +02:00
|
|
|
formsemestre: FormSemestre,
|
|
|
|
res: NotesTableCompat,
|
|
|
|
include_evaluations=False,
|
|
|
|
filename="",
|
2022-03-27 22:25:00 +02:00
|
|
|
):
|
2022-03-26 23:33:57 +01:00
|
|
|
"""Construit table recap pour le BUT
|
2022-04-05 22:23:55 +02:00
|
|
|
Cache le résultat pour le semestre.
|
2022-03-26 23:33:57 +01:00
|
|
|
Return: data, filename
|
2022-04-06 18:51:01 +02:00
|
|
|
data est une chaine, le <div>...</div> incluant le tableau.
|
2022-03-26 23:33:57 +01:00
|
|
|
"""
|
2022-04-05 22:23:55 +02:00
|
|
|
if include_evaluations:
|
|
|
|
table_html = sco_cache.TableRecapWithEvalsCache.get(formsemestre.id)
|
|
|
|
else:
|
|
|
|
table_html = sco_cache.TableRecapCache.get(formsemestre.id)
|
|
|
|
if table_html is None:
|
|
|
|
table_html = _gen_formsemestre_recapcomplet_html(
|
|
|
|
formsemestre, res, include_evaluations, filename
|
|
|
|
)
|
|
|
|
if include_evaluations:
|
|
|
|
sco_cache.TableRecapWithEvalsCache.set(formsemestre.id, table_html)
|
|
|
|
else:
|
|
|
|
sco_cache.TableRecapCache.set(formsemestre.id, table_html)
|
|
|
|
|
2022-04-06 18:51:01 +02:00
|
|
|
return table_html
|
2022-04-05 22:23:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
def _gen_formsemestre_recapcomplet_html(
|
|
|
|
formsemestre: FormSemestre,
|
|
|
|
res: NotesTableCompat,
|
|
|
|
include_evaluations=False,
|
|
|
|
filename: str = "",
|
|
|
|
) -> str:
|
|
|
|
"""Génère le html"""
|
2022-04-04 09:35:52 +02:00
|
|
|
rows, footer_rows, titles, column_ids = res.get_table_recap(
|
|
|
|
convert_values=True, include_evaluations=include_evaluations
|
|
|
|
)
|
2022-03-27 23:19:17 +02:00
|
|
|
if not rows:
|
|
|
|
return (
|
2022-04-06 18:51:01 +02:00
|
|
|
'<div class="table_recap"><div class="message">aucun étudiant !</div></div>'
|
2022-03-27 23:19:17 +02:00
|
|
|
)
|
2022-03-28 18:13:51 +02:00
|
|
|
H = [
|
2022-04-04 09:35:52 +02:00
|
|
|
f"""<div class="table_recap"><table class="table_recap {
|
|
|
|
'apc' if formsemestre.formation.is_apc() else 'classic'}"
|
|
|
|
data-filename="{filename}">"""
|
2022-03-28 18:13:51 +02:00
|
|
|
]
|
2022-03-26 23:33:57 +01:00
|
|
|
# header
|
|
|
|
H.append(
|
|
|
|
f"""
|
|
|
|
<thead>
|
|
|
|
{_gen_row(column_ids, titles, "th")}
|
|
|
|
</thead>
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
# body
|
|
|
|
H.append("<tbody>")
|
|
|
|
for row in rows:
|
|
|
|
H.append(f"{_gen_row(column_ids, row)}\n")
|
|
|
|
H.append("</tbody>\n")
|
|
|
|
# footer
|
|
|
|
H.append("<tfoot>")
|
2022-03-27 18:49:15 +02:00
|
|
|
idx_last = len(footer_rows) - 1
|
|
|
|
for i, row in enumerate(footer_rows):
|
|
|
|
H.append(f'{_gen_row(column_ids, row, "th" if i == idx_last else "td")}\n')
|
2022-03-26 23:33:57 +01:00
|
|
|
H.append(
|
2022-03-27 18:49:15 +02:00
|
|
|
"""
|
2022-03-26 23:33:57 +01:00
|
|
|
</tfoot>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
"""
|
|
|
|
)
|
2022-04-05 22:23:55 +02:00
|
|
|
return "".join(H)
|
2022-04-06 18:51:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
def gen_formsemestre_recapcomplet_excel(
|
|
|
|
formsemestre: FormSemestre,
|
|
|
|
res: NotesTableCompat,
|
|
|
|
include_evaluations=False,
|
|
|
|
filename: str = "",
|
|
|
|
format="xls",
|
|
|
|
) -> tuple:
|
|
|
|
"""Génère le tableau recap en excel (xlsx) ou CSV.
|
|
|
|
Utilisé pour archives et autres besoins particuliers (API).
|
|
|
|
Attention: le tableau exporté depuis la page html est celui généré en js par DataTables,
|
|
|
|
et non celui-ci.
|
|
|
|
"""
|
|
|
|
suffix = scu.CSV_SUFFIX if format == "csv" else scu.XLSX_SUFFIX
|
|
|
|
filename += suffix
|
|
|
|
rows, footer_rows, titles, column_ids = res.get_table_recap(
|
|
|
|
convert_values=False, include_evaluations=include_evaluations
|
|
|
|
)
|
|
|
|
|
|
|
|
tab = GenTable(
|
|
|
|
columns_ids=column_ids,
|
|
|
|
titles=titles,
|
|
|
|
rows=rows + footer_rows,
|
|
|
|
preferences=sco_preferences.SemPreferences(formsemestre_id=formsemestre.id),
|
|
|
|
)
|
|
|
|
|
|
|
|
return tab.gen(format=format), filename
|