Adaptation fonctions export Apogée pour ScoDoc 9
This commit is contained in:
parent
2fbce89edd
commit
a52de101b6
@ -82,14 +82,15 @@ XXX A vérifier:
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
|
from functools import reduce
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
import pprint
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import pprint
|
|
||||||
from functools import reduce
|
from flask import send_file
|
||||||
|
|
||||||
# Pour la détection auto de l'encodage des fichiers Apogée:
|
# Pour la détection auto de l'encodage des fichiers Apogée:
|
||||||
from chardet import detect as chardet_detect
|
from chardet import detect as chardet_detect
|
||||||
@ -500,7 +501,7 @@ class ApoEtud(dict):
|
|||||||
# print 'comp_elt_annuel cur_sem=%s autre_sem=%s' % (cur_sem['formsemestre_id'], autre_sem['formsemestre_id'])
|
# print 'comp_elt_annuel cur_sem=%s autre_sem=%s' % (cur_sem['formsemestre_id'], autre_sem['formsemestre_id'])
|
||||||
if not cur_sem:
|
if not cur_sem:
|
||||||
# l'étudiant n'a pas de semestre courant ?!
|
# l'étudiant n'a pas de semestre courant ?!
|
||||||
log("comp_elt_annuel: %s no cur_sem" % etudid)
|
log("comp_elt_annuel: etudid %s has no cur_sem" % etudid)
|
||||||
return VOID_APO_RES
|
return VOID_APO_RES
|
||||||
cur_nt = sco_cache.NotesTableCache.get(cur_sem["formsemestre_id"])
|
cur_nt = sco_cache.NotesTableCache.get(cur_sem["formsemestre_id"])
|
||||||
cur_decision = cur_nt.get_etud_decision_sem(etudid)
|
cur_decision = cur_nt.get_etud_decision_sem(etudid)
|
||||||
@ -756,22 +757,19 @@ class ApoData(object):
|
|||||||
else:
|
else:
|
||||||
self.sems_periode = None
|
self.sems_periode = None
|
||||||
|
|
||||||
def read_csv(self, data):
|
def read_csv(self, data: str):
|
||||||
if not data:
|
if not data:
|
||||||
raise FormatError("Fichier Apogée vide !")
|
raise FormatError("Fichier Apogée vide !")
|
||||||
|
|
||||||
data_utf8 = data.decode(APO_INPUT_ENCODING).encode(
|
f = StringIOFileLineWrapper(data) # pour traiter comme un fichier
|
||||||
scu.SCO_ENCODING
|
|
||||||
) # XXX #sco8
|
|
||||||
f = StringIOFileLineWrapper(data_utf8) # pour traiter comme un fichier
|
|
||||||
# check that we are at the begining of Apogee CSV
|
# check that we are at the begining of Apogee CSV
|
||||||
line = f.readline().strip()
|
line = f.readline().strip()
|
||||||
if line != "XX-APO_TITRES-XX":
|
if line != "XX-APO_TITRES-XX":
|
||||||
raise FormatError("format incorrect: pas de XX-APO_TITRES-XX")
|
raise FormatError("format incorrect: pas de XX-APO_TITRES-XX")
|
||||||
|
|
||||||
# 1-- En-tête: du début jusqu'à la balise XX-APO_VALEURS-XX
|
# 1-- En-tête: du début jusqu'à la balise XX-APO_VALEURS-XX
|
||||||
idx = data_utf8.index("XX-APO_VALEURS-XX")
|
idx = data.index("XX-APO_VALEURS-XX")
|
||||||
self.header = data_utf8[:idx] # en codage ScoDoc (utf8)
|
self.header = data[:idx]
|
||||||
|
|
||||||
# 2-- Titres:
|
# 2-- Titres:
|
||||||
# on va y chercher apoC_Fichier_Exp qui donnera le nom du fichier
|
# on va y chercher apoC_Fichier_Exp qui donnera le nom du fichier
|
||||||
@ -1236,7 +1234,7 @@ def export_csv_to_apogee(
|
|||||||
|
|
||||||
# Create ZIP
|
# Create ZIP
|
||||||
if not dest_zip:
|
if not dest_zip:
|
||||||
data = io.StringIO()
|
data = io.BytesIO()
|
||||||
dest_zip = ZipFile(data, "w")
|
dest_zip = ZipFile(data, "w")
|
||||||
my_zip = True
|
my_zip = True
|
||||||
else:
|
else:
|
||||||
@ -1293,7 +1291,7 @@ def export_csv_to_apogee(
|
|||||||
)
|
)
|
||||||
log(logf.getvalue()) # sortie aussi sur le log ScoDoc
|
log(logf.getvalue()) # sortie aussi sur le log ScoDoc
|
||||||
|
|
||||||
csv_data = f.getvalue().decode(scu.SCO_ENCODING).encode(APO_OUTPUT_ENCODING) # XXX
|
csv_data = f.getvalue().encode(APO_OUTPUT_ENCODING)
|
||||||
|
|
||||||
# Write data to ZIP
|
# Write data to ZIP
|
||||||
dest_zip.writestr(csv_filename, csv_data)
|
dest_zip.writestr(csv_filename, csv_data)
|
||||||
@ -1304,13 +1302,12 @@ def export_csv_to_apogee(
|
|||||||
|
|
||||||
if my_zip:
|
if my_zip:
|
||||||
dest_zip.close()
|
dest_zip.close()
|
||||||
size = data.tell()
|
data.seek(0)
|
||||||
content_type = "application/zip"
|
return send_file(
|
||||||
REQUEST.RESPONSE.setHeader(
|
data,
|
||||||
"content-disposition", 'attachement; filename="%s-scodoc.zip"' % basename
|
mimetype="application/zip",
|
||||||
|
download_name=basename + "-scodoc.zip",
|
||||||
|
as_attachment=True,
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.setHeader("content-type", content_type)
|
|
||||||
REQUEST.RESPONSE.setHeader("content-length", size)
|
|
||||||
return data.getvalue()
|
|
||||||
else:
|
else:
|
||||||
return None # zip modified in place
|
return None # zip modified in place
|
||||||
|
@ -99,12 +99,14 @@ ApoCSVArchive = ApoCSVArchiver()
|
|||||||
# return archive_id
|
# return archive_id
|
||||||
|
|
||||||
|
|
||||||
def apo_csv_store(csv_data, annee_scolaire, sem_id):
|
def apo_csv_store(csv_data: str, annee_scolaire, sem_id):
|
||||||
"""
|
"""
|
||||||
csv_data: maquette content, as a string, encoding given by APO_INPUT_ENCODING (latin-1, not utf8)
|
csv_data: maquette content (string)
|
||||||
annee_scolaire: int (2016)
|
annee_scolaire: int (2016)
|
||||||
sem_id: 0 (année ?), 1 (premier semestre de l'année) ou 2 (deuxième semestre)
|
sem_id: 0 (année ?), 1 (premier semestre de l'année) ou 2 (deuxième semestre)
|
||||||
:return: etape_apo du fichier CSV stocké
|
:return: etape_apo du fichier CSV stocké
|
||||||
|
|
||||||
|
Note: le fichier CSV est stocké encodé en APO_OUTPUT_ENCODING
|
||||||
"""
|
"""
|
||||||
# sanity check
|
# sanity check
|
||||||
filesize = len(csv_data)
|
filesize = len(csv_data)
|
||||||
@ -128,7 +130,8 @@ def apo_csv_store(csv_data, annee_scolaire, sem_id):
|
|||||||
oid = "%d-%d" % (annee_scolaire, sem_id)
|
oid = "%d-%d" % (annee_scolaire, sem_id)
|
||||||
description = "%s;%s;%s" % (str(apo_data.etape), annee_scolaire, sem_id)
|
description = "%s;%s;%s" % (str(apo_data.etape), annee_scolaire, sem_id)
|
||||||
archive_id = ApoCSVArchive.create_obj_archive(oid, description)
|
archive_id = ApoCSVArchive.create_obj_archive(oid, description)
|
||||||
ApoCSVArchive.store(archive_id, filename, csv_data)
|
csv_data_bytes = csv_data.encode(sco_apogee_csv.APO_OUTPUT_ENCODING)
|
||||||
|
ApoCSVArchive.store(archive_id, filename, csv_data_bytes)
|
||||||
|
|
||||||
return apo_data.etape
|
return apo_data.etape
|
||||||
|
|
||||||
@ -199,7 +202,7 @@ def apo_csv_get_archive(etape_apo, annee_scolaire="", sem_id=""):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def apo_csv_get(etape_apo="", annee_scolaire="", sem_id=""):
|
def apo_csv_get(etape_apo="", annee_scolaire="", sem_id="") -> str:
|
||||||
"""Get CSV data for given etape_apo
|
"""Get CSV data for given etape_apo
|
||||||
:return: CSV, as a data string
|
:return: CSV, as a data string
|
||||||
"""
|
"""
|
||||||
@ -210,7 +213,9 @@ def apo_csv_get(etape_apo="", annee_scolaire="", sem_id=""):
|
|||||||
)
|
)
|
||||||
archive_id = info["archive_id"]
|
archive_id = info["archive_id"]
|
||||||
data = ApoCSVArchive.get(archive_id, etape_apo + ".csv")
|
data = ApoCSVArchive.get(archive_id, etape_apo + ".csv")
|
||||||
return data
|
# ce fichier a été archivé donc généré par ScoDoc
|
||||||
|
# son encodage est donc APO_OUTPUT_ENCODING
|
||||||
|
return data.decode(sco_apogee_csv.APO_OUTPUT_ENCODING)
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------
|
# ------------------------------------------------------------------------
|
||||||
|
@ -28,22 +28,21 @@
|
|||||||
"""ScoDoc : formulaires gestion maquettes Apogee / export resultats
|
"""ScoDoc : formulaires gestion maquettes Apogee / export resultats
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from io import StringIO
|
import io
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import url_for, g
|
from flask import url_for, g, send_file
|
||||||
|
|
||||||
|
# from werkzeug.utils import send_file
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import notes_table
|
|
||||||
from app.scodoc import sco_apogee_csv
|
from app.scodoc import sco_apogee_csv
|
||||||
from app.scodoc import sco_archives
|
|
||||||
from app.scodoc import sco_etape_apogee
|
from app.scodoc import sco_etape_apogee
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_formsemestre_status
|
|
||||||
from app.scodoc import sco_portal_apogee
|
from app.scodoc import sco_portal_apogee
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_semset
|
from app.scodoc import sco_semset
|
||||||
@ -180,15 +179,6 @@ def apo_semset_maq_status(
|
|||||||
H.append('<div class="apo_csv_problems"><ul>')
|
H.append('<div class="apo_csv_problems"><ul>')
|
||||||
if len(semset.annees_scolaires()) > 1:
|
if len(semset.annees_scolaires()) > 1:
|
||||||
H.append("""<li>Il y a plusieurs années scolaires !</li>""")
|
H.append("""<li>Il y a plusieurs années scolaires !</li>""")
|
||||||
if nips_no_sco: # seulement un warning
|
|
||||||
url_list = (
|
|
||||||
"view_apo_etuds?semset_id=%s&title=Etudiants%%20presents%%20dans%%20maquettes%%20Apogee%%20mais%%20pas%%20dans%%20les%%20semestres%%20ScoDoc:&nips=%s"
|
|
||||||
% (semset_id, "&nips=".join(nips_no_sco))
|
|
||||||
)
|
|
||||||
H.append(
|
|
||||||
'<li class="apo_csv_warning">Attention: il y a <a href="%s">%d étudiant(s)</a> dans les maquettes Apogée chargées non inscrit(s) dans ce semestre ScoDoc;</li>'
|
|
||||||
% (url_list, len(nips_no_sco))
|
|
||||||
)
|
|
||||||
|
|
||||||
if etapes_missing_csv:
|
if etapes_missing_csv:
|
||||||
H.append(
|
H.append(
|
||||||
@ -200,9 +190,12 @@ def apo_semset_maq_status(
|
|||||||
H.append("<li>%d étudiants ScoDoc sans code NIP</li>" % len(etuds_without_nip))
|
H.append("<li>%d étudiants ScoDoc sans code NIP</li>" % len(etuds_without_nip))
|
||||||
|
|
||||||
if nips_no_apo:
|
if nips_no_apo:
|
||||||
url_list = (
|
url_list = url_for(
|
||||||
"view_scodoc_etuds?semset_id=%s&title=Etudiants%%20ScoDoc%%20non%%20listés%%20dans%%20les%%20maquettes%%20Apogée%%20chargées&nips=%s"
|
"notes.view_scodoc_etuds",
|
||||||
% (semset_id, "&nips=".join(nips_no_apo))
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
semset_id=semset_id,
|
||||||
|
title="Etudiants ScoDoc non listés dans les maquettes Apogée chargées",
|
||||||
|
nip_list=",".join(nips_no_apo),
|
||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
'<li><a href="%s">%d étudiants</a> dans ce semestre non présents dans les maquettes Apogée chargées</li>'
|
'<li><a href="%s">%d étudiants</a> dans ce semestre non présents dans les maquettes Apogée chargées</li>'
|
||||||
@ -210,9 +203,12 @@ def apo_semset_maq_status(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if nips_no_sco: # seulement un warning
|
if nips_no_sco: # seulement un warning
|
||||||
url_list = (
|
url_list = url_for(
|
||||||
"view_apo_etuds?semset_id=%s&title=Etudiants%%20presents%%20dans%%20maquettes%%20Apogee%%20mais%%20pas%%20dans%%20les%%20semestres%%20ScoDoc:&nips=%s"
|
"notes.view_apo_etuds",
|
||||||
% (semset_id, "&nips=".join(nips_no_sco))
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
semset_id=semset_id,
|
||||||
|
title="Etudiants présents dans maquettes Apogée mais pas dans les semestres ScoDoc",
|
||||||
|
nip_list=",".join(nips_no_sco),
|
||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
'<li class="apo_csv_warning">Attention: il reste <a href="%s">%d étudiants</a> dans les maquettes Apogée chargées mais pas inscrits dans ce semestre ScoDoc</li>'
|
'<li class="apo_csv_warning">Attention: il reste <a href="%s">%d étudiants</a> dans les maquettes Apogée chargées mais pas inscrits dans ce semestre ScoDoc</li>'
|
||||||
@ -220,9 +216,12 @@ def apo_semset_maq_status(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if apo_dups:
|
if apo_dups:
|
||||||
url_list = "view_apo_etuds?semset_id=%s&title=Doublons%%20Apogee&nips=%s" % (
|
url_list = url_for(
|
||||||
semset_id,
|
"notes.view_apo_etuds",
|
||||||
"&nips=".join(apo_dups),
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
semset_id=semset_id,
|
||||||
|
title="Doublons%%20Apogée",
|
||||||
|
nip_list=",".join(apo_dups),
|
||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
'<li><a href="%s">%d étudiants</a> présents dans les <em>plusieurs</em> maquettes Apogée chargées</li>'
|
'<li><a href="%s">%d étudiants</a> présents dans les <em>plusieurs</em> maquettes Apogée chargées</li>'
|
||||||
@ -485,16 +484,18 @@ def table_apo_csv_list(semset, REQUEST=None):
|
|||||||
return tab
|
return tab
|
||||||
|
|
||||||
|
|
||||||
def view_apo_etuds(semset_id, title="", nips=[], format="html", REQUEST=None):
|
def view_apo_etuds(semset_id, title="", nip_list="", format="html", REQUEST=None):
|
||||||
"""Table des étudiants Apogée par nips"""
|
"""Table des étudiants Apogée par nips
|
||||||
|
nip_list est une chaine, codes nip séparés par des ,
|
||||||
|
"""
|
||||||
if not semset_id:
|
if not semset_id:
|
||||||
raise ValueError("invalid null semset_id")
|
raise ValueError("invalid null semset_id")
|
||||||
semset = sco_semset.SemSet(semset_id=semset_id)
|
semset = sco_semset.SemSet(semset_id=semset_id)
|
||||||
# annee_scolaire = semset["annee_scolaire"]
|
# annee_scolaire = semset["annee_scolaire"]
|
||||||
# sem_id = semset["sem_id"]
|
# sem_id = semset["sem_id"]
|
||||||
|
if not isinstance(nip_list, str):
|
||||||
if nips and type(nips) != type([]):
|
nip_list = str(nip_list)
|
||||||
nips = [nips]
|
nips = nip_list.split(",")
|
||||||
etuds = sco_etape_apogee.apo_csv_retreive_etuds_by_nip(semset, nips)
|
etuds = sco_etape_apogee.apo_csv_retreive_etuds_by_nip(semset, nips)
|
||||||
# Ils sont parfois dans ScoDoc même si pas dans le semestre: essaie de les retrouver
|
# Ils sont parfois dans ScoDoc même si pas dans le semestre: essaie de les retrouver
|
||||||
for etud in etuds.values():
|
for etud in etuds.values():
|
||||||
@ -520,22 +521,12 @@ def view_apo_etuds(semset_id, title="", nips=[], format="html", REQUEST=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def view_scodoc_etuds(
|
def view_scodoc_etuds(semset_id, title="", nip_list="", format="html", REQUEST=None):
|
||||||
semset_id, title="", etudids=None, nips=None, format="html", REQUEST=None
|
|
||||||
):
|
|
||||||
"""Table des étudiants ScoDoc par nips ou etudids"""
|
"""Table des étudiants ScoDoc par nips ou etudids"""
|
||||||
if etudids is not None:
|
if not isinstance(nip_list, str):
|
||||||
if type(etudids) != type([]):
|
nip_list = str(nip_list)
|
||||||
etudids = [etudids]
|
nips = nip_list.split(",")
|
||||||
etuds = [
|
|
||||||
sco_etud.get_etud_info(etudid=etudid, filled=True)[0] for etudid in etudids
|
|
||||||
]
|
|
||||||
elif nips is not None:
|
|
||||||
if type(nips) != type([]):
|
|
||||||
nips = [nips]
|
|
||||||
etuds = [sco_etud.get_etud_info(code_nip=nip, filled=True)[0] for nip in nips]
|
etuds = [sco_etud.get_etud_info(code_nip=nip, filled=True)[0] for nip in nips]
|
||||||
else:
|
|
||||||
raise ValueError("etudid or NIP must be specified")
|
|
||||||
|
|
||||||
for e in etuds:
|
for e in etuds:
|
||||||
tgt = url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=e["etudid"])
|
tgt = url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=e["etudid"])
|
||||||
@ -809,7 +800,7 @@ def apo_csv_export_results(
|
|||||||
annee_scolaire = semset["annee_scolaire"]
|
annee_scolaire = semset["annee_scolaire"]
|
||||||
periode = semset["sem_id"]
|
periode = semset["sem_id"]
|
||||||
|
|
||||||
data = StringIO()
|
data = io.BytesIO()
|
||||||
dest_zip = ZipFile(data, "w")
|
dest_zip = ZipFile(data, "w")
|
||||||
|
|
||||||
etapes_apo = sco_etape_apogee.apo_csv_list_stored_etapes(
|
etapes_apo = sco_etape_apogee.apo_csv_list_stored_etapes(
|
||||||
@ -830,6 +821,8 @@ def apo_csv_export_results(
|
|||||||
REQUEST=REQUEST,
|
REQUEST=REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dest_zip.close()
|
||||||
|
data.seek(0)
|
||||||
basename = (
|
basename = (
|
||||||
sco_preferences.get_preference("DeptName")
|
sco_preferences.get_preference("DeptName")
|
||||||
+ str(annee_scolaire)
|
+ str(annee_scolaire)
|
||||||
@ -838,12 +831,9 @@ def apo_csv_export_results(
|
|||||||
)
|
)
|
||||||
basename = scu.sanitize_filename(scu.unescape_html(basename))
|
basename = scu.sanitize_filename(scu.unescape_html(basename))
|
||||||
|
|
||||||
dest_zip.close()
|
return send_file(
|
||||||
size = data.tell()
|
data,
|
||||||
content_type = "application/zip"
|
mimetype="application/zip",
|
||||||
REQUEST.RESPONSE.setHeader(
|
download_name=basename + ".zip",
|
||||||
"content-disposition", 'attachement; filename="%s.zip"' % basename
|
as_attachment=True,
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.setHeader("content-type", content_type)
|
|
||||||
REQUEST.RESPONSE.setHeader("content-length", size)
|
|
||||||
return data.getvalue()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user