Ordre boites export Apogee + fix export excel

This commit is contained in:
Emmanuel Viennet 2021-09-25 10:43:06 +02:00
parent 4e59b9597b
commit a2c16207cb
5 changed files with 66 additions and 40 deletions

View File

@ -185,6 +185,9 @@ class GenTable(object):
else: else:
self.preferences = DEFAULT_TABLE_PREFERENCES() self.preferences = DEFAULT_TABLE_PREFERENCES()
def __repr__(self):
return f"<gen_table( nrows={self.get_nb_rows()}, ncols={self.get_nb_cols()} )>"
def get_nb_cols(self): def get_nb_cols(self):
return len(self.columns_ids) return len(self.columns_ids)

View File

@ -81,6 +81,7 @@ def list_authorized_etuds_by_sem(sem, delai=274):
"title": src["titreannee"], "title": src["titreannee"],
"title_target": "formsemestre_status?formsemestre_id=%s" "title_target": "formsemestre_status?formsemestre_id=%s"
% src["formsemestre_id"], % src["formsemestre_id"],
"filename": "etud_autorises",
}, },
} }
# ajoute attribut inscrit qui indique si l'étudiant est déjà inscrit dans le semestre dest. # ajoute attribut inscrit qui indique si l'étudiant est déjà inscrit dans le semestre dest.
@ -99,6 +100,7 @@ def list_authorized_etuds_by_sem(sem, delai=274):
% sem["formsemestre_id"], % sem["formsemestre_id"],
"comment": " actuellement inscrits dans ce semestre", "comment": " actuellement inscrits dans ce semestre",
"help": "Ces étudiants sont actuellement inscrits dans ce semestre. Si vous les décochez, il seront désinscrits.", "help": "Ces étudiants sont actuellement inscrits dans ce semestre. Si vous les décochez, il seront désinscrits.",
"filename": "etud_inscrits",
}, },
} }
@ -506,7 +508,12 @@ def etuds_select_boxes(
</script> </script>
<div class="etuds_select_boxes">""" <div class="etuds_select_boxes">"""
] # " ] # "
# Élimine les boites vides:
auth_etuds_by_cat = {
k: auth_etuds_by_cat[k]
for k in auth_etuds_by_cat
if auth_etuds_by_cat[k]["etuds"]
}
for src_cat in auth_etuds_by_cat.keys(): for src_cat in auth_etuds_by_cat.keys():
infos = auth_etuds_by_cat[src_cat]["infos"] infos = auth_etuds_by_cat[src_cat]["infos"]
infos["comment"] = infos.get("comment", "") # commentaire dans sous-titre boite infos["comment"] = infos.get("comment", "") # commentaire dans sous-titre boite
@ -549,10 +556,8 @@ def etuds_select_boxes(
if with_checkbox or sel_inscrits: if with_checkbox or sel_inscrits:
H.append(")") H.append(")")
if base_url and etuds: if base_url and etuds:
H.append( url = scu.build_url_query(base_url, export_cat_xls=src_cat)
'<a href="%s&export_cat_xls=%s">%s</a>&nbsp;' H.append(f'<a href="{url}">{scu.ICON_XLS}</a>&nbsp;')
% (base_url, src_cat, scu.ICON_XLS)
)
H.append("</div>") H.append("</div>")
for etud in etuds: for etud in etuds:
if etud.get("inscrit", False): if etud.get("inscrit", False):
@ -632,4 +637,4 @@ def etuds_select_box_xls(src_cat):
caption="%(title)s. %(help)s" % src_cat["infos"], caption="%(title)s. %(help)s" % src_cat["infos"],
preferences=sco_preferences.SemPreferences(), preferences=sco_preferences.SemPreferences(),
) )
return tab.excel() return tab.excel() # tab.make_page(filename=src_cat["infos"]["filename"])

View File

@ -231,7 +231,7 @@ def do_formsemestre_recapcomplet(
return data return data
elif format == "csv": elif format == "csv":
return scu.send_file(data, filename=filename, mime=scu.CSV_MIMETYPE) return scu.send_file(data, filename=filename, mime=scu.CSV_MIMETYPE)
elif format[:3] == "xls" or format[:4] == "xlsx": elif format.startswith("xls") or format.startswith("xlsx"):
return scu.send_file(data, filename=filename, mime=scu.XLSX_MIMETYPE) return scu.send_file(data, filename=filename, mime=scu.XLSX_MIMETYPE)
elif format == "json": elif format == "json":
js = json.dumps(data, indent=1, cls=scu.ScoDocJSONEncoder) js = json.dumps(data, indent=1, cls=scu.ScoDocJSONEncoder)

View File

@ -32,7 +32,7 @@ import time
import pprint import pprint
from operator import itemgetter from operator import itemgetter
from flask import g, url_for, send_file from flask import g, url_for
from flask_login import current_user from flask_login import current_user
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
@ -112,6 +112,7 @@ def formsemestre_synchro_etuds(
base_url = url_for( base_url = url_for(
"notes.formsemestre_synchro_etuds", "notes.formsemestre_synchro_etuds",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
anneeapogee=anneeapogee or None, # si None, le param n'est pas dans l'URL anneeapogee=anneeapogee or None, # si None, le param n'est pas dans l'URL
) )
@ -146,11 +147,11 @@ def formsemestre_synchro_etuds(
base_url=base_url, base_url=base_url,
read_only=read_only, read_only=read_only,
) )
return send_file( return scu.send_file(
xls, xls,
mimetype=scu.XLS_MIMETYPE, mime=scu.XLS_MIMETYPE,
download_name=scu.sanitize_filename(filename + scu.XLSX_SUFFIX), filename=filename,
as_attachment=True, suffix=scu.XLSX_SUFFIX,
) )
H = [header] H = [header]
@ -317,7 +318,8 @@ def build_page(
""" """
% sem, % sem,
""" """
Année Apogée: <select id="anneeapogee" name="anneeapogee" onchange="document.location='formsemestre_synchro_etuds?formsemestre_id=%s&anneeapogee='+document.getElementById('anneeapogee').value">""" Année Apogée: <select id="anneeapogee" name="anneeapogee"
onchange="document.location='formsemestre_synchro_etuds?formsemestre_id=%s&anneeapogee='+document.getElementById('anneeapogee').value">"""
% (sem["formsemestre_id"]), % (sem["formsemestre_id"]),
"\n".join(options), "\n".join(options),
""" """
@ -430,17 +432,20 @@ def list_synch(sem, anneeapogee=None):
return etuds return etuds
# #
r = { boites = {
"etuds_ok": { "etuds_a_importer": {
"etuds": set_to_sorted_list(etuds_ok, is_inscrit=True), "etuds": set_to_sorted_list(a_importer, is_inscrit=True, etud_apo=True),
"infos": { "infos": {
"id": "etuds_ok", "id": "etuds_a_importer",
"title": "Etudiants dans Apogée et déjà inscrits", "title": "Etudiants dans Apogée à importer",
"help": "Ces etudiants sont inscrits dans le semestre ScoDoc et sont présents dans Apogée: tout est donc correct. Décocher les étudiants que vous souhaitez désinscrire.", "help": """Ces étudiants sont inscrits dans cette étape Apogée mais ne sont pas connus par ScoDoc:
cocher les noms à importer et inscrire puis appuyer sur le bouton "Appliquer".""",
"title_target": "", "title_target": "",
"with_checkbox": True, "with_checkbox": True,
"etud_key": EKEY_SCO, "etud_key": EKEY_APO, # clé à stocker dans le formulaire html
"filename": "etuds_a_importer",
}, },
"nomprenoms": etudsapo_ident,
}, },
"etuds_noninscrits": { "etuds_noninscrits": {
"etuds": set_to_sorted_list(etuds_noninscrits, is_inscrit=True), "etuds": set_to_sorted_list(etuds_noninscrits, is_inscrit=True),
@ -453,20 +458,9 @@ def list_synch(sem, anneeapogee=None):
"title_target": "", "title_target": "",
"with_checkbox": True, "with_checkbox": True,
"etud_key": EKEY_SCO, "etud_key": EKEY_SCO,
"filename": "etuds_non_inscrits",
}, },
}, },
"etuds_a_importer": {
"etuds": set_to_sorted_list(a_importer, is_inscrit=True, etud_apo=True),
"infos": {
"id": "etuds_a_importer",
"title": "Etudiants dans Apogée à importer",
"help": """Ces étudiants sont inscrits dans cette étape Apogée mais ne sont pas connus par ScoDoc: cocher les noms à importer et inscrire puis appuyer sur le bouton "Appliquer".""",
"title_target": "",
"with_checkbox": True,
"etud_key": EKEY_APO, # clé à stocker dans le formulaire html
},
"nomprenoms": etudsapo_ident,
},
"etuds_nonapogee": { "etuds_nonapogee": {
"etuds": set_to_sorted_list(etuds_nonapogee, is_inscrit=True), "etuds": set_to_sorted_list(etuds_nonapogee, is_inscrit=True),
"infos": { "infos": {
@ -478,6 +472,7 @@ def list_synch(sem, anneeapogee=None):
"title_target": "", "title_target": "",
"with_checkbox": True, "with_checkbox": True,
"etud_key": EKEY_SCO, "etud_key": EKEY_SCO,
"filename": "etuds_non_apogee",
}, },
}, },
"inscrits_without_key": { "inscrits_without_key": {
@ -489,11 +484,25 @@ def list_synch(sem, anneeapogee=None):
"title_target": "", "title_target": "",
"with_checkbox": True, "with_checkbox": True,
"checkbox_name": "inscrits_without_key", "checkbox_name": "inscrits_without_key",
"filename": "inscrits_without_key",
},
},
"etuds_ok": {
"etuds": set_to_sorted_list(etuds_ok, is_inscrit=True),
"infos": {
"id": "etuds_ok",
"title": "Etudiants dans Apogée et déjà inscrits",
"help": """Ces etudiants sont inscrits dans le semestre ScoDoc et sont présents dans Apogée:
tout est donc correct. Décocher les étudiants que vous souhaitez désinscrire.""",
"title_target": "",
"with_checkbox": True,
"etud_key": EKEY_SCO,
"filename": "etuds_inscrits_ok_apo",
}, },
}, },
} }
return ( return (
r, boites,
a_importer, a_importer,
etuds_noninscrits, etuds_noninscrits,
inscrits_set, inscrits_set,

View File

@ -39,15 +39,11 @@ import os
import pydot import pydot
import re import re
import requests import requests
import six import _thread
import six.moves._thread
import sys
import time import time
import traceback
import types
import unicodedata import unicodedata
import urllib import urllib
from xml.etree import ElementTree from urllib.parse import urlparse, parse_qsl, urlunparse, urlencode
from flask import g, current_app from flask import g, current_app
@ -218,7 +214,7 @@ def group_by_key(d, key):
# ----- Global lock for critical sections (except notes_tables caches) # ----- Global lock for critical sections (except notes_tables caches)
GSL = six.moves._thread.allocate_lock() # Global ScoDoc Lock GSL = _thread.allocate_lock() # Global ScoDoc Lock
SCODOC_DIR = Config.SCODOC_DIR SCODOC_DIR = Config.SCODOC_DIR
@ -308,6 +304,7 @@ JSON_SUFFIX = ".json"
PDF_MIMETYPE = "application/pdf" PDF_MIMETYPE = "application/pdf"
PDF_SUFFIX = ".pdf" PDF_SUFFIX = ".pdf"
XLS_MIMETYPE = "application/vnd.ms-excel" XLS_MIMETYPE = "application/vnd.ms-excel"
XLS_SUFFIX = ".xls"
XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
XLSX_SUFFIX = ".xlsx" XLSX_SUFFIX = ".xlsx"
XML_MIMETYPE = "text/xml" XML_MIMETYPE = "text/xml"
@ -411,6 +408,18 @@ def unescape_html(s):
return s return s
def build_url_query(url: str, **params) -> str:
"""Add parameters to existing url, as a query string"""
url_parse = urlparse(url)
query = url_parse.query
url_dict = dict(parse_qsl(query))
url_dict.update(params)
url_new_query = urlencode(url_dict)
url_parse = url_parse._replace(query=url_new_query)
new_url = urlunparse(url_parse)
return new_url
# test if obj is iterable (but not a string) # test if obj is iterable (but not a string)
isiterable = lambda obj: getattr(obj, "__iter__", False) isiterable = lambda obj: getattr(obj, "__iter__", False)