preparation envoi fichier

This commit is contained in:
Jean-Marie Place 2021-09-13 07:16:37 +02:00
parent c8872bd220
commit c44aa808df
4 changed files with 77 additions and 43 deletions

View File

@ -60,6 +60,7 @@ from app.scodoc import sco_pdf
from app.scodoc import sco_xml from app.scodoc import sco_xml
from app.scodoc.sco_pdf import SU from app.scodoc.sco_pdf import SU
from app import log from app import log
from app.scodoc.sco_utils import flaskPDFResponse
def mark_paras(L, tags): def mark_paras(L, tags):
@ -648,30 +649,35 @@ class GenTable(object):
objects, title=title, preferences=self.preferences objects, title=title, preferences=self.preferences
) )
if publish: if publish:
return scu.sendPDFFile(REQUEST, doc, filename + ".pdf") return scu.PDF_FORMAT.send_file(doc, filename, add_suffix=True, attached=True)
# return scu.flaskPDFResponse(doc, filename + ".pdf")
# return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
else: else:
return doc return doc
elif format == "xls" or format == "xlsx": elif format == "xls" or format == "xlsx":
xls = self.excel() xls = self.excel()
if publish: if publish:
return sco_excel.send_excel_file( return scu.XLSX_FORMAT.send_file(xls, filename, add_suffix=True, attached=True)
REQUEST, xls, filename + scu.XLSX_SUFFIX # return sco_excel.send_from_flask(xls, filename + scu.XLSX_SUFFIX)
) # return sco_excel.send_excel_file(REQUEST, xls, filename + scu.XLSX_SUFFIX)
else: else:
return xls return xls
elif format == "text": elif format == "text":
return self.text() return self.text()
elif format == "csv": elif format == "csv":
return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv") return scu.CSV_FORMAT.send_file(self.text(), filename, add_suffix=True, attached=True)
# return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv")
elif format == "xml": elif format == "xml":
xml = self.xml() xml = self.xml()
if REQUEST and publish: if publish:
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) # REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
return xml # return xml
return scu.XML_FORMAT.send_file(self.xml)
elif format == "json": elif format == "json":
js = self.json() js = self.json()
if REQUEST and publish: if publish:
REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE) return scu.JSON_FORMAT.send_file(self.xml)
# REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
return js return js
else: else:
log("make_page: format=%s" % format) log("make_page: format=%s" % format)

View File

@ -66,7 +66,7 @@ class COLORS(Enum):
def send_from_flask(data, filename, mime=scu.XLSX_MIMETYPE): def send_from_flask(data, filename, mime=scu.XLSX_MIMETYPE):
scu.make_filename(filename) filename = scu.make_filename(filename)
response = make_response(data) response = make_response(data)
response.headers['Content-Type'] = mime response.headers['Content-Type'] = mime
response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename

View File

@ -310,10 +310,7 @@ class PlacementRunner:
return plan return plan
def _production_xls(self): def _production_xls(self):
filename = scu.make_filename( filename = "placement_%s_%s%s" % (self.evalname, self.gr_title_filename, scu.XLSX_SUFFIX)
"placement_%s_%s%s"
% (self.evalname, self.gr_title_filename, scu.XLSX_SUFFIX)
)
xls = self._excel_feuille_placement() xls = self._excel_feuille_placement()
return sco_excel.send_from_flask(xls, filename) return sco_excel.send_from_flask(xls, filename)
@ -323,8 +320,8 @@ class PlacementRunner:
"Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s" "Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s"
% self.eval_data % self.eval_data
) )
breakpoint()
filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % self filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % self.__dict__
titles = { titles = {
"nom": "Nom", "nom": "Nom",
"prenom": "Prenom", "prenom": "Prenom",
@ -339,7 +336,7 @@ class PlacementRunner:
columns_ids = ["nom", "prenom", "place"] columns_ids = ["nom", "prenom", "place"]
rows = [] rows = []
for etud in sorted(plan, key=lambda etud: etud[0][0]): # sort by name for etud in sorted(self.plan, key=lambda item: item[0][0]): # sort by name
if self.etiquetage == COORD: if self.etiquetage == COORD:
rows.append( rows.append(
{ {
@ -362,7 +359,7 @@ class PlacementRunner:
+ "", + "",
pdf_title=pdf_title, pdf_title=pdf_title,
# pdf_shorttitle = '', # pdf_shorttitle = '',
preferences=sco_preferences.SemPreferences(M["formsemestre_id"]), preferences=sco_preferences.SemPreferences(self.moduleimpl_data["formsemestre_id"]),
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete # html_generate_cells=False # la derniere ligne (moyennes) est incomplete
) )
t = tab.make_page(format="pdf", with_html_headers=False, REQUEST=REQUEST) t = tab.make_page(format="pdf", with_html_headers=False, REQUEST=REQUEST)

View File

@ -49,7 +49,7 @@ import unicodedata
import urllib import urllib
from xml.etree import ElementTree from xml.etree import ElementTree
from flask import g, current_app from flask import g, current_app, make_response
from PIL import Image as PILImage from PIL import Image as PILImage
@ -64,7 +64,6 @@ from app.scodoc import sco_exceptions
from app.scodoc import sco_xml from app.scodoc import sco_xml
import sco_version import sco_version
# ----- CALCUL ET PRESENTATION DES NOTES # ----- CALCUL ET PRESENTATION DES NOTES
NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis
NOTES_MIN = 0.0 # valeur minimale admise pour une note (sauf malus, dans [-20, 20]) NOTES_MIN = 0.0 # valeur minimale admise pour une note (sauf malus, dans [-20, 20])
@ -73,7 +72,6 @@ NOTES_NEUTRALISE = -1000.0 # notes non prises en comptes dans moyennes
NOTES_SUPPRESS = -1001.0 # note a supprimer NOTES_SUPPRESS = -1001.0 # note a supprimer
NOTES_ATTENTE = -1002.0 # note "en attente" (se calcule comme une note neutralisee) NOTES_ATTENTE = -1002.0 # note "en attente" (se calcule comme une note neutralisee)
# Types de modules # Types de modules
MODULE_STANDARD = 0 MODULE_STANDARD = 0
MODULE_MALUS = 1 MODULE_MALUS = 1
@ -88,7 +86,7 @@ IT_SITUATION_MISSING_STR = (
"____" # shown on ficheEtud (devenir) in place of empty situation "____" # shown on ficheEtud (devenir) in place of empty situation
) )
RANG_ATTENTE_STR = "(attente)" # rang affiché sur bulletins quand notes en attente RANG_ATTENTE_STR = "(attente)" # rang affiché sur bulletins quand notes en attente
# borne supérieure de chaque mention # borne supérieure de chaque mention
NOTES_MENTIONS_TH = ( NOTES_MENTIONS_TH = (
@ -234,11 +232,9 @@ if not os.path.exists(SCO_TMP_DIR):
SCODOC_LOGOS_DIR = os.path.join(SCODOC_CFG_DIR, "logos") SCODOC_LOGOS_DIR = os.path.join(SCODOC_CFG_DIR, "logos")
LOGOS_IMAGES_ALLOWED_TYPES = ("jpg", "jpeg", "png") # remind that PIL does not read pdf LOGOS_IMAGES_ALLOWED_TYPES = ("jpg", "jpeg", "png") # remind that PIL does not read pdf
# ----- Les outils distribués # ----- Les outils distribués
SCO_TOOLS_DIR = os.path.join(Config.SCODOC_DIR, "tools") SCO_TOOLS_DIR = os.path.join(Config.SCODOC_DIR, "tools")
# ----- Lecture du fichier de configuration # ----- Lecture du fichier de configuration
from app.scodoc import sco_config from app.scodoc import sco_config
from app.scodoc import sco_config_load from app.scodoc import sco_config_load
@ -272,7 +268,6 @@ else:
SCO_ENCODING = "utf-8" # used by Excel, XML, PDF, ... SCO_ENCODING = "utf-8" # used by Excel, XML, PDF, ...
SCO_DEFAULT_SQL_USER = "scodoc" # should match Zope process UID SCO_DEFAULT_SQL_USER = "scodoc" # should match Zope process UID
SCO_DEFAULT_SQL_PORT = "5432" SCO_DEFAULT_SQL_PORT = "5432"
SCO_DEFAULT_SQL_USERS_CNX = "dbname=SCOUSERS port=%s" % SCO_DEFAULT_SQL_PORT SCO_DEFAULT_SQL_USERS_CNX = "dbname=SCOUSERS port=%s" % SCO_DEFAULT_SQL_PORT
@ -304,8 +299,11 @@ XLS_MIMETYPE = "application/vnd.ms-excel"
XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
XLSX_SUFFIX = ".xlsx" XLSX_SUFFIX = ".xlsx"
PDF_MIMETYPE = "application/pdf" PDF_MIMETYPE = "application/pdf"
PDF_SUFFIX = ".pdf"
XML_MIMETYPE = "text/xml" XML_MIMETYPE = "text/xml"
XML_SUFFIX = ".xml"
JSON_MIMETYPE = "application/json" JSON_MIMETYPE = "application/json"
JSON_SUFFIX = ".json"
# Admissions des étudiants # Admissions des étudiants
# Différents types de voies d'admission: # Différents types de voies d'admission:
@ -315,6 +313,31 @@ TYPES_ADMISSION = (TYPE_ADMISSION_DEFAULT, "APB", "APB-PC", "CEF", "Direct")
BULLETINS_VERSIONS = ("short", "selectedevals", "long") BULLETINS_VERSIONS = ("short", "selectedevals", "long")
# File format management
class FileFormat:
def __init__(self, suffix, mime):
self._mime = mime
self._suffix = suffix
def send_file(self, data, filename, add_suffix=False, attached=False):
filename = make_filename(filename)
if add_suffix:
filename += self._suffix
response = make_response(data)
response.headers['Content-Type'] = self._mime
if attached:
response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename
return response
CSV_FORMAT = FileFormat(CSV_SUFFIX, CSV_MIMETYPE)
XLSX_FORMAT = FileFormat(XLSX_SUFFIX, XLSX_MIMETYPE)
XLS_FORMAT = FileFormat(XLS_SUFFIX, XLS_MIMETYPE)
PDF_FORMAT = FileFormat(PDF_SUFFIX, PDF_MIMETYPE)
XML_FORMAT = FileFormat(XML_SUFFIX, XML_MIMETYPE)
JSON_FORMAT = FileFormat(JSON_SUFFIX, JSON_MIMETYPE)
# Support for ScoDoc7 compatibility # Support for ScoDoc7 compatibility
@ -324,8 +347,8 @@ def ScoURL():
= page accueil département = page accueil département
""" """
return url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)[ return url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)[
: -len("/index_html") : -len("/index_html")
] ]
def NotesURL(): def NotesURL():
@ -352,8 +375,8 @@ def EntreprisesURL():
def AbsencesURL(): def AbsencesURL():
"""URL of Absences""" """URL of Absences"""
return url_for("absences.index_html", scodoc_dept=g.scodoc_dept)[ return url_for("absences.index_html", scodoc_dept=g.scodoc_dept)[
: -len("/index_html") : -len("/index_html")
] ]
def UsersURL(): def UsersURL():
@ -439,8 +462,8 @@ def suppress_accents(s):
if isinstance(s, str): if isinstance(s, str):
return ( return (
unicodedata.normalize("NFD", s) unicodedata.normalize("NFD", s)
.encode("ascii", "ignore") .encode("ascii", "ignore")
.decode(SCO_ENCODING) .decode(SCO_ENCODING)
) )
return s # may be int return s # may be int
@ -504,6 +527,14 @@ def sendCSVFile(REQUEST, data, filename):
return data return data
def flaskPDFResponse(data, filename, mime=PDF_MIMETYPE):
filename = make_filename(filename)
response = make_response(data)
response.headers['Content-Type'] = mime
response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename
return response
def sendPDFFile(REQUEST, data, filename): def sendPDFFile(REQUEST, data, filename):
filename = ( filename = (
unescape_html(suppress_accents(filename)).replace("&", "").replace(" ", "_") unescape_html(suppress_accents(filename)).replace("&", "").replace(" ", "_")
@ -641,7 +672,7 @@ def sem_decale_str(sem):
if sem["semestre_id"] <= 0: if sem["semestre_id"] <= 0:
return "" return ""
if (sem["semestre_id"] % 2 and sem["mois_debut_ord"] <= 6) or ( if (sem["semestre_id"] % 2 and sem["mois_debut_ord"] <= 6) or (
not sem["semestre_id"] % 2 and sem["mois_debut_ord"] > 6 not sem["semestre_id"] % 2 and sem["mois_debut_ord"] > 6
): ):
return "D" return "D"
else: else:
@ -800,15 +831,15 @@ def return_text_if_published(val, REQUEST):
def confirm_dialog( def confirm_dialog(
message="<p>Confirmer ?</p>", message="<p>Confirmer ?</p>",
OK="OK", OK="OK",
Cancel="Annuler", Cancel="Annuler",
dest_url="", dest_url="",
cancel_url="", cancel_url="",
target_variable="dialog_confirmed", target_variable="dialog_confirmed",
parameters={}, parameters={},
add_headers=True, # complete page add_headers=True, # complete page
helpmsg=None, helpmsg=None,
): ):
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
@ -850,7 +881,7 @@ def confirm_dialog(
H.append('<p class="help">' + helpmsg + "</p>") H.append('<p class="help">' + helpmsg + "</p>")
if add_headers: if add_headers:
return ( return (
html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer() html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer()
) )
else: else:
return "\n".join(H) return "\n".join(H)