forked from ScoDoc/ScoDoc
various fixes. Bulletins et saisie décision ok.
This commit is contained in:
parent
3dc94775a1
commit
f0c96e3e68
@ -31,17 +31,13 @@ Module main: essais divers
|
|||||||
Emmanuel Viennet, 2021
|
Emmanuel Viennet, 2021
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
import pprint
|
import pprint
|
||||||
from pprint import pprint as pp
|
from pprint import pprint as pp
|
||||||
import functools
|
import functools
|
||||||
import six.moves._thread # essai
|
import six.moves._thread # essai
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
try:
|
|
||||||
from io import StringIO ## for Python 3
|
|
||||||
except ImportError:
|
|
||||||
from cStringIO import StringIO ## for Python 2
|
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import request, render_template, redirect
|
from flask import request, render_template, redirect
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
@ -180,7 +176,7 @@ def getzip():
|
|||||||
# REQUEST.RESPONSE.setHeader(
|
# REQUEST.RESPONSE.setHeader(
|
||||||
# "content-disposition", 'attachement; filename="monzip.zip"'
|
# "content-disposition", 'attachement; filename="monzip.zip"'
|
||||||
# )
|
# )
|
||||||
zipdata = StringIO()
|
zipdata = io.StringIO()
|
||||||
zipfile = ZipFile(zipdata, "w")
|
zipfile = ZipFile(zipdata, "w")
|
||||||
zipfile.writestr("fichier1", "un contenu")
|
zipfile.writestr("fichier1", "un contenu")
|
||||||
zipfile.writestr("fichier2", "deux contenus")
|
zipfile.writestr("fichier2", "deux contenus")
|
||||||
|
@ -187,7 +187,7 @@ def bonus_iutr(notes_sport, coefs, infos=None):
|
|||||||
# le bonus est le minimum entre 0.35 et la somme de toutes les bonifs
|
# le bonus est le minimum entre 0.35 et la somme de toutes les bonifs
|
||||||
bonus = min(0.35, sum([x for x in notes_sport]))
|
bonus = min(0.35, sum([x for x in notes_sport]))
|
||||||
for ue_id in infos["moy_ues"]:
|
for ue_id in infos["moy_ues"]:
|
||||||
# open('/tmp/log','a').write( ue_id + infos['moy_ues'] + '\n\n' )
|
# open('/tmp/log','a').write( str(ue_id) + infos['moy_ues'] + '\n\n' )
|
||||||
ue_status = infos["moy_ues"][ue_id]
|
ue_status = infos["moy_ues"][ue_id]
|
||||||
if ue_status["sum_coefs"] > 0:
|
if ue_status["sum_coefs"] > 0:
|
||||||
# modifie moyenne UE dans semestre courant
|
# modifie moyenne UE dans semestre courant
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
"""Simple image resize using PIL"""
|
"""Simple image resize using PIL"""
|
||||||
|
|
||||||
|
import io
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
|
|
||||||
try:
|
|
||||||
from io import StringIO # for Python 3
|
|
||||||
except ImportError:
|
|
||||||
from cStringIO import StringIO # for Python 2
|
|
||||||
|
|
||||||
|
|
||||||
def ImageScale(img_file, maxx, maxy):
|
def ImageScale(img_file, maxx, maxy):
|
||||||
im = PILImage.open(img_file)
|
im = PILImage.open(img_file)
|
||||||
im.thumbnail((maxx, maxy), PILImage.ANTIALIAS)
|
im.thumbnail((maxx, maxy), PILImage.ANTIALIAS)
|
||||||
out_file_str = StringIO()
|
out_file_str = io.BytesIO()
|
||||||
im.save(out_file_str, im.format)
|
im.save(out_file_str, im.format)
|
||||||
out_file_str.seek(0)
|
out_file_str.seek(0)
|
||||||
tmp = out_file_str.read()
|
tmp = out_file_str.read()
|
||||||
@ -25,7 +21,7 @@ def ImageScaleH(img_file, W=None, H=90):
|
|||||||
# keep aspect
|
# keep aspect
|
||||||
W = int((im.size[0] * H) / float(im.size[1]))
|
W = int((im.size[0] * H) / float(im.size[1]))
|
||||||
im.thumbnail((W, H), PILImage.ANTIALIAS)
|
im.thumbnail((W, H), PILImage.ANTIALIAS)
|
||||||
out_file_str = StringIO()
|
out_file_str = io.BytesIO()
|
||||||
im.save(out_file_str, im.format)
|
im.save(out_file_str, im.format)
|
||||||
out_file_str.seek(0)
|
out_file_str.seek(0)
|
||||||
tmp = out_file_str.read()
|
tmp = out_file_str.read()
|
||||||
|
@ -1289,7 +1289,18 @@ class NotesTable(object):
|
|||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select n.* from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_moduleimpl_inscription i where n.etudid = %(etudid)s and n.value = %(code_attente)s and n.evaluation_id=e.evaluation_id and e.moduleimpl_id=m.moduleimpl_id and m.formsemestre_id=%(formsemestre_id)s and e.coefficient != 0 and m.moduleimpl_id=i.moduleimpl_id and i.etudid=%(etudid)s",
|
"""SELECT n.*
|
||||||
|
FROM notes_notes n, notes_evaluation e, notes_moduleimpl m,
|
||||||
|
notes_moduleimpl_inscription i
|
||||||
|
WHERE n.etudid = %(etudid)s
|
||||||
|
and n.value = %(code_attente)s
|
||||||
|
and n.evaluation_id = e.id
|
||||||
|
and e.moduleimpl_id = m.id
|
||||||
|
and m.formsemestre_id = %(formsemestre_id)s
|
||||||
|
and e.coefficient != 0
|
||||||
|
and m.id = i.moduleimpl_id
|
||||||
|
and i.etudid=%(etudid)s
|
||||||
|
""",
|
||||||
{
|
{
|
||||||
"formsemestre_id": self.formsemestre_id,
|
"formsemestre_id": self.formsemestre_id,
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
|
@ -81,15 +81,12 @@ XXX A vérifier:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
import datetime
|
||||||
|
import io
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import datetime
|
|
||||||
import os
|
|
||||||
|
|
||||||
try:
|
|
||||||
from io import StringIO # for Python 3
|
|
||||||
except ImportError:
|
|
||||||
from cStringIO import StringIO # for Python 2
|
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import pprint
|
import pprint
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
@ -203,7 +200,7 @@ def fix_data_encoding(
|
|||||||
|
|
||||||
class StringIOFileLineWrapper(object):
|
class StringIOFileLineWrapper(object):
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
self.f = StringIO(data)
|
self.f = io.StringIO(data)
|
||||||
self.lineno = 0
|
self.lineno = 0
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
@ -1223,7 +1220,7 @@ def export_csv_to_apogee(
|
|||||||
e.associate_sco(context, apo_data)
|
e.associate_sco(context, apo_data)
|
||||||
|
|
||||||
# Ré-écrit le fichier Apogée
|
# Ré-écrit le fichier Apogée
|
||||||
f = StringIO()
|
f = io.StringIO()
|
||||||
apo_data.write_header(f)
|
apo_data.write_header(f)
|
||||||
apo_data.write_etuds(f)
|
apo_data.write_etuds(f)
|
||||||
|
|
||||||
@ -1245,7 +1242,7 @@ def export_csv_to_apogee(
|
|||||||
|
|
||||||
# Create ZIP
|
# Create ZIP
|
||||||
if not dest_zip:
|
if not dest_zip:
|
||||||
data = StringIO()
|
data = io.StringIO()
|
||||||
dest_zip = ZipFile(data, "w")
|
dest_zip = ZipFile(data, "w")
|
||||||
my_zip = True
|
my_zip = True
|
||||||
else:
|
else:
|
||||||
@ -1269,7 +1266,7 @@ def export_csv_to_apogee(
|
|||||||
nar_filename = basename + "-nar" + scu.XLSX_SUFFIX
|
nar_filename = basename + "-nar" + scu.XLSX_SUFFIX
|
||||||
cr_filename = basename + "-decisions" + scu.XLSX_SUFFIX
|
cr_filename = basename + "-decisions" + scu.XLSX_SUFFIX
|
||||||
|
|
||||||
logf = StringIO()
|
logf = io.StringIO()
|
||||||
logf.write("export_to_apogee du %s\n\n" % time.ctime())
|
logf.write("export_to_apogee du %s\n\n" % time.ctime())
|
||||||
logf.write("Semestres ScoDoc sources:\n")
|
logf.write("Semestres ScoDoc sources:\n")
|
||||||
for sem in apo_data.sems_etape:
|
for sem in apo_data.sems_etape:
|
||||||
|
@ -50,15 +50,12 @@ Pour définir un nouveau type de bulletin:
|
|||||||
Chaque semestre peut si nécessaire utiliser un type de bulletin différent.
|
Chaque semestre peut si nécessaire utiliser un type de bulletin différent.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import re
|
|
||||||
import os
|
|
||||||
|
|
||||||
try:
|
|
||||||
from io import StringIO # for Python 3
|
|
||||||
except ImportError:
|
|
||||||
from cStringIO import StringIO # for Python 2
|
|
||||||
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||||
|
|
||||||
from app.scodoc import VERSION
|
from app.scodoc import VERSION
|
||||||
@ -92,7 +89,7 @@ def pdfassemblebulletins(
|
|||||||
sco_preferences.get_preference("bottom_margin", formsemestre_id),
|
sco_preferences.get_preference("bottom_margin", formsemestre_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
report = StringIO.StringIO() # in-memory document, no disk file
|
report = io.BytesIO() # in-memory document, no disk file
|
||||||
document = BaseDocTemplate(report)
|
document = BaseDocTemplate(report)
|
||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
sco_pdf.ScolarsPageTemplate(
|
sco_pdf.ScolarsPageTemplate(
|
||||||
@ -149,16 +146,21 @@ def process_field(
|
|||||||
image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id() + "/"
|
image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id() + "/"
|
||||||
if not os.path.exists(image_dir):
|
if not os.path.exists(image_dir):
|
||||||
image_dir = scu.SCODOC_LOGOS_DIR + "/" # use global logos
|
image_dir = scu.SCODOC_LOGOS_DIR + "/" # use global logos
|
||||||
|
if not os.path.exists(image_dir):
|
||||||
|
log(f"Warning: missing global logo directory ({image_dir})")
|
||||||
|
image_dir = None
|
||||||
|
|
||||||
text = re.sub(
|
text = re.sub(
|
||||||
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
|
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
|
||||||
) # remove forbidden src attribute
|
) # remove forbidden src attribute
|
||||||
text = re.sub(
|
if image_dir is not None:
|
||||||
r'<\s*logo(.*?)name\s*=\s*"(\w*?)"(.*?)/?>',
|
text = re.sub(
|
||||||
r'<img\1src="%s/logo_\2.jpg"\3/>' % image_dir,
|
r'<\s*logo(.*?)name\s*=\s*"(\w*?)"(.*?)/?>',
|
||||||
text,
|
r'<img\1src="%s/logo_\2.jpg"\3/>' % image_dir,
|
||||||
)
|
text,
|
||||||
# nota: le match sur \w*? donne le nom du logo et interdit les .. et autres
|
)
|
||||||
# tentatives d'acceder à d'autres fichiers !
|
# nota: le match sur \w*? donne le nom du logo et interdit les .. et autres
|
||||||
|
# tentatives d'acceder à d'autres fichiers !
|
||||||
|
|
||||||
# log('field: %s' % (text))
|
# log('field: %s' % (text))
|
||||||
return sco_pdf.makeParas(text, style, suppress_empty=suppress_empty_pars)
|
return sco_pdf.makeParas(text, style, suppress_empty=suppress_empty_pars)
|
||||||
@ -170,7 +172,7 @@ def get_formsemestre_bulletins_pdf(
|
|||||||
"document pdf et filename"
|
"document pdf et filename"
|
||||||
from app.scodoc import sco_bulletins
|
from app.scodoc import sco_bulletins
|
||||||
|
|
||||||
cached = sco_cache.SemBulletinsPDFCache.get(formsemestre_id + "_" + version)
|
cached = sco_cache.SemBulletinsPDFCache.get(str(formsemestre_id) + "_" + version)
|
||||||
if cached:
|
if cached:
|
||||||
return cached[1], cached[0]
|
return cached[1], cached[0]
|
||||||
fragments = []
|
fragments = []
|
||||||
@ -219,7 +221,7 @@ def get_formsemestre_bulletins_pdf(
|
|||||||
filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "")
|
filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "")
|
||||||
# fill cache
|
# fill cache
|
||||||
sco_cache.SemBulletinsPDFCache.set(
|
sco_cache.SemBulletinsPDFCache.set(
|
||||||
formsemestre_id + "_" + version, (filename, pdfdoc)
|
str(formsemestre_id) + "_" + version, (filename, pdfdoc)
|
||||||
)
|
)
|
||||||
return pdfdoc, filename
|
return pdfdoc, filename
|
||||||
|
|
||||||
|
@ -86,15 +86,18 @@ class DecisionSem(object):
|
|||||||
self.devenir = devenir
|
self.devenir = devenir
|
||||||
self.assiduite = assiduite
|
self.assiduite = assiduite
|
||||||
self.rule_id = rule_id
|
self.rule_id = rule_id
|
||||||
# code unique utilise pour la gestion du formulaire
|
# code unique (string) utilise pour la gestion du formulaire
|
||||||
self.codechoice = str(
|
self.codechoice = (
|
||||||
hash(
|
"C" # prefix pour éviter que Flask le considère comme int
|
||||||
(
|
+ str(
|
||||||
code_etat,
|
hash(
|
||||||
new_code_prev,
|
(
|
||||||
formsemestre_id_utilise_pour_compenser,
|
code_etat,
|
||||||
devenir,
|
new_code_prev,
|
||||||
assiduite,
|
formsemestre_id_utilise_pour_compenser,
|
||||||
|
devenir,
|
||||||
|
assiduite,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -126,6 +126,7 @@ def makeParas(txt, style, suppress_empty=False):
|
|||||||
paras = r
|
paras = r
|
||||||
return [Paragraph(SU(s), style) for s in paras]
|
return [Paragraph(SU(s), style) for s in paras]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
raise
|
||||||
detail = " " + str(e)
|
detail = " " + str(e)
|
||||||
log(traceback.format_exc())
|
log(traceback.format_exc())
|
||||||
log("Invalid pdf para format: %s" % txt)
|
log("Invalid pdf para format: %s" % txt)
|
||||||
|
@ -201,8 +201,8 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
self.logo_header = None
|
self.logo_header = None
|
||||||
# Search logos in dept specific dir, then in global scu.CONFIG dir
|
# Search logos in dept specific dir, then in global scu.CONFIG dir
|
||||||
for image_dir in (
|
for image_dir in (
|
||||||
scu.SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id() + "/",
|
scu.SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id(),
|
||||||
scu.SCODOC_LOGOS_DIR + "/", # global logos
|
scu.SCODOC_LOGOS_DIR, # global logos
|
||||||
):
|
):
|
||||||
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
||||||
if template_name == "PVJuryTemplate":
|
if template_name == "PVJuryTemplate":
|
||||||
@ -222,6 +222,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
|
|
||||||
fn = image_dir + "/logo_header" + "." + suffix
|
fn = image_dir + "/logo_header" + "." + suffix
|
||||||
if not self.logo_header and os.path.exists(fn):
|
if not self.logo_header and os.path.exists(fn):
|
||||||
|
log("XXX XXX : logo_header " + fn)
|
||||||
self.logo_header = Image(
|
self.logo_header = Image(
|
||||||
fn,
|
fn,
|
||||||
height=LOGO_HEADER_HEIGHT,
|
height=LOGO_HEADER_HEIGHT,
|
||||||
|
@ -64,10 +64,10 @@ ATTRIBUTES_MAPPING = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def setup_log(dept_id: str):
|
def setup_log(dept_acronym: str):
|
||||||
"""log to console (stderr) and /opt/scodoc-data/log/migration78.log"""
|
"""log to console (stderr) and /opt/scodoc-data/log/migration78.log"""
|
||||||
log_formatter = logging.Formatter(
|
log_formatter = logging.Formatter(
|
||||||
"%(asctime)s %(levelname)s (" + dept_id + ") %(message)s"
|
"%(asctime)s %(levelname)s (" + dept_acronym + ") %(message)s"
|
||||||
)
|
)
|
||||||
# Log to file:
|
# Log to file:
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
@ -117,8 +117,7 @@ def import_scodoc7_dept(dept_id: str, dept_db_uri=None):
|
|||||||
logging.info(f"All table imported: clearing app caches...")
|
logging.info(f"All table imported: clearing app caches...")
|
||||||
clear_scodoc_cache()
|
clear_scodoc_cache()
|
||||||
logging.info(f"Done.")
|
logging.info(f"Done.")
|
||||||
logging.warning(f"Un redémarrage du serveur postgresql est conseillé")
|
logging.warning(f"Un redémarrage du serveur postgresql est conseillé.")
|
||||||
logging.warning(f"systemctl restart postgresql"
|
|
||||||
|
|
||||||
|
|
||||||
def get_class_for_table(table):
|
def get_class_for_table(table):
|
||||||
|
Loading…
Reference in New Issue
Block a user