diff --git a/app/scodoc/sco_cache.py b/app/scodoc/sco_cache.py index 94f954095..b3a80f626 100644 --- a/app/scodoc/sco_cache.py +++ b/app/scodoc/sco_cache.py @@ -251,6 +251,9 @@ def invalidate_formsemestre( # was inval_cache(formsemestre_id=None, pdfonly=Fa """ from app.scodoc import sco_parcours_dut + if g.defer_cache_invalidation: + g.sem_to_invalidate.add(formsemestre_id) + return log("inval_cache, formsemestre_id=%s pdfonly=%s" % (formsemestre_id, pdfonly)) if formsemestre_id is None: # clear all caches @@ -286,3 +289,25 @@ def invalidate_formsemestre( # was inval_cache(formsemestre_id=None, pdfonly=Fa SemInscriptionsCache.delete_many(formsemestre_ids) SemBulletinsPDFCache.invalidate_sems(formsemestre_ids) + + +class DefferedSemCacheManager: + """Experimental: pour effectuer des opérations indépendantes dans la + même requete qui invalident le cache. Par exemple, quand on inscrit + des étudiants un par un à un semestre, chaque inscription va invalider + le cache, et la suivante va le reconstruire... pour l'invalider juste après. + Ce context manager permet de grouper les invalidations. + """ + + def __enter__(self): + assert not hasattr(g, "defer_cache_invalidation") + g.defer_cache_invalidation = True + g.sem_to_invalidate = set() + return True + + def __exit__(self, exc_type, exc_value, exc_traceback): + assert g.defer_cache_invalidation + g.defer_cache_invalidation = False + while g.sem_to_invalidate: + formsemestre_id = g.sem_to_invalidate.pop() + invalidate_formsemestre(formsemestre_id) diff --git a/app/scodoc/sco_formsemestre_exterieurs.py b/app/scodoc/sco_formsemestre_exterieurs.py index 59e890dff..2ab82d875 100644 --- a/app/scodoc/sco_formsemestre_exterieurs.py +++ b/app/scodoc/sco_formsemestre_exterieurs.py @@ -74,7 +74,6 @@ def formsemestre_ext_create(etudid, sem_params, REQUEST=None): sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( formsemestre_id, etudid, - REQUEST=REQUEST, method="formsemestre_ext_create", ) return formsemestre_id diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py index 99e4f26ed..f8b29dd4b 100644 --- a/app/scodoc/sco_formsemestre_inscriptions.py +++ b/app/scodoc/sco_formsemestre_inscriptions.py @@ -135,7 +135,7 @@ def do_formsemestre_inscription_edit(args=None, formsemestre_id=None): ) # > modif inscription semestre (demission ?) -def do_formsemestre_desinscription(etudid, formsemestre_id, REQUEST=None): +def do_formsemestre_desinscription(etudid, formsemestre_id): """Désinscription d'un étudiant. Si semestre extérieur et dernier inscrit, suppression de ce semestre. """ @@ -194,14 +194,13 @@ def do_formsemestre_desinscription(etudid, formsemestre_id, REQUEST=None): ) sco_formsemestre_edit.do_formsemestre_delete(formsemestre_id) - if REQUEST: - logdb( - cnx, - method="formsemestre_desinscription", - etudid=etudid, - msg="desinscription semestre %s" % formsemestre_id, - commit=False, - ) + logdb( + cnx, + method="formsemestre_desinscription", + etudid=etudid, + msg="desinscription semestre %s" % formsemestre_id, + commit=False, + ) def do_formsemestre_inscription_with_modules( @@ -210,7 +209,6 @@ def do_formsemestre_inscription_with_modules( group_ids=[], etat="I", etape=None, - REQUEST=None, method="inscription_with_modules", ): """Inscrit cet etudiant à ce semestre et TOUS ses modules STANDARDS @@ -245,7 +243,6 @@ def do_formsemestre_inscription_with_modules( if mod["ue"]["type"] != UE_SPORT: sco_moduleimpl.do_moduleimpl_inscription_create( {"moduleimpl_id": mod["moduleimpl_id"], "etudid": etudid}, - REQUEST=REQUEST, formsemestre_id=formsemestre_id, ) @@ -406,7 +403,6 @@ def formsemestre_inscription_with_modules( etudid, group_ids=group_ids, etat="I", - REQUEST=REQUEST, method="formsemestre_inscription_with_modules", ) return flask.redirect( @@ -691,7 +687,6 @@ def do_moduleimpl_incription_options( mod = mods[0] sco_moduleimpl.do_moduleimpl_inscription_create( {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, - REQUEST=REQUEST, formsemestre_id=mod["formsemestre_id"], ) # desinscriptions diff --git a/app/scodoc/sco_groups.py b/app/scodoc/sco_groups.py index aec10d82d..18c53e734 100644 --- a/app/scodoc/sco_groups.py +++ b/app/scodoc/sco_groups.py @@ -601,7 +601,7 @@ def set_group(etudid, group_id): return True -def change_etud_group_in_partition(etudid, group_id, partition=None, REQUEST=None): +def change_etud_group_in_partition(etudid, group_id, partition=None): """Inscrit etud au groupe de cette partition, et le desinscrit d'autres groupes de cette partition.""" log("change_etud_group_in_partition: etudid=%s group_id=%s" % (etudid, group_id)) @@ -632,16 +632,15 @@ def change_etud_group_in_partition(etudid, group_id, partition=None, REQUEST=Non # 3- log formsemestre_id = partition["formsemestre_id"] - if REQUEST: - cnx = ndb.GetDBConnexion() - logdb( - cnx, - method="changeGroup", - etudid=etudid, - msg="formsemestre_id=%s,partition_name=%s, group_name=%s" - % (formsemestre_id, partition["partition_name"], group["group_name"]), - ) - cnx.commit() + cnx = ndb.GetDBConnexion() + logdb( + cnx, + method="changeGroup", + etudid=etudid, + msg="formsemestre_id=%s,partition_name=%s, group_name=%s" + % (formsemestre_id, partition["partition_name"], group["group_name"]), + ) + cnx.commit() # 4- invalidate cache sco_cache.invalidate_formsemestre( formsemestre_id=formsemestre_id @@ -696,9 +695,7 @@ def setGroups( if (etudid not in etud_groups) or ( group_id != etud_groups[etudid].get(partition_id, "") ): # pas le meme groupe qu'actuel - change_etud_group_in_partition( - etudid, group_id, partition, REQUEST=REQUEST - ) + change_etud_group_in_partition(etudid, group_id, partition) # Retire les anciens membres: cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) @@ -734,7 +731,7 @@ def setGroups( group_id = createGroup(partition_id, group_name) # Place dans ce groupe les etudiants indiqués: for etudid in fs[1:-1]: - change_etud_group_in_partition(etudid, group_id, partition, REQUEST=REQUEST) + change_etud_group_in_partition(etudid, group_id, partition) REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) return ( @@ -1329,9 +1326,7 @@ def groups_auto_repartition(partition_id=None, REQUEST=None): etudid = listes[civilite].pop()[1] group_id = group_ids[igroup] igroup = (igroup + 1) % nbgroups - change_etud_group_in_partition( - etudid, group_id, partition, REQUEST=REQUEST - ) + change_etud_group_in_partition(etudid, group_id, partition) log("%s in group %s" % (etudid, group_id)) return flask.redirect(dest_url) diff --git a/app/scodoc/sco_import_etuds.py b/app/scodoc/sco_import_etuds.py index e224d3261..5e5016bcd 100644 --- a/app/scodoc/sco_import_etuds.py +++ b/app/scodoc/sco_import_etuds.py @@ -572,7 +572,6 @@ def _import_one_student( etudid, group_ids, etat="I", - REQUEST=REQUEST, method="import_csv_file", ) return args["formsemestre_id"] @@ -716,7 +715,7 @@ def scolars_import_admission( for group_id in group_ids: sco_groups.change_etud_group_in_partition( - args["etudid"], group_id, REQUEST=REQUEST + args["etudid"], group_id ) # diag.append("import de %s" % (etud["nomprenom"])) diff --git a/app/scodoc/sco_inscr_passage.py b/app/scodoc/sco_inscr_passage.py index 9efaabce2..60787c5f9 100644 --- a/app/scodoc/sco_inscr_passage.py +++ b/app/scodoc/sco_inscr_passage.py @@ -157,7 +157,7 @@ def list_inscrits_date(sem): return [x[0] for x in cursor.fetchall()] -def do_inscrit(sem, etudids, REQUEST=None, inscrit_groupes=False): +def do_inscrit(sem, etudids, inscrit_groupes=False): """Inscrit ces etudiants dans ce semestre (la liste doit avoir été vérifiée au préalable) En option: inscrit aux mêmes groupes que dans le semestre origine @@ -168,7 +168,6 @@ def do_inscrit(sem, etudids, REQUEST=None, inscrit_groupes=False): sem["formsemestre_id"], etudid, etat="I", - REQUEST=REQUEST, method="formsemestre_inscr_passage", ) if inscrit_groupes: @@ -208,15 +207,14 @@ def do_inscrit(sem, etudids, REQUEST=None, inscrit_groupes=False): etudid, partition_group["group_id"], partition_group, - REQUEST=REQUEST, ) -def do_desinscrit(sem, etudids, REQUEST): +def do_desinscrit(sem, etudids): log("do_desinscrit: %s" % etudids) for etudid in etudids: sco_formsemestre_inscriptions.do_formsemestre_desinscription( - etudid, sem["formsemestre_id"], REQUEST=REQUEST + etudid, sem["formsemestre_id"] ) @@ -361,12 +359,11 @@ def formsemestre_inscr_passage( do_inscrit( sem, a_inscrire, - REQUEST=REQUEST, inscrit_groupes=inscrit_groupes, ) # Desincriptions: - do_desinscrit(sem, a_desinscrire, REQUEST) + do_desinscrit(sem, a_desinscrire) H.append( """

Opération effectuée

diff --git a/app/scodoc/sco_moduleimpl.py b/app/scodoc/sco_moduleimpl.py index 7d82744a6..fbb4b350f 100644 --- a/app/scodoc/sco_moduleimpl.py +++ b/app/scodoc/sco_moduleimpl.py @@ -218,7 +218,7 @@ _moduleimpl_inscriptionEditor = ndb.EditableTable( ) -def do_moduleimpl_inscription_create(args, REQUEST=None, formsemestre_id=None): +def do_moduleimpl_inscription_create(args, formsemestre_id=None): "create a moduleimpl_inscription" cnx = ndb.GetDBConnexion() log("do_moduleimpl_inscription_create: " + str(args)) @@ -226,14 +226,13 @@ def do_moduleimpl_inscription_create(args, REQUEST=None, formsemestre_id=None): sco_cache.invalidate_formsemestre( formsemestre_id=formsemestre_id ) # > moduleimpl_inscription - if REQUEST: - scolog.logdb( - cnx, - method="moduleimpl_inscription", - etudid=args["etudid"], - msg="inscription module %s" % args["moduleimpl_id"], - commit=False, - ) + scolog.logdb( + cnx, + method="moduleimpl_inscription", + etudid=args["etudid"], + msg="inscription module %s" % args["moduleimpl_id"], + commit=False, + ) return r @@ -283,7 +282,6 @@ def do_moduleimpl_inscrit_etuds( if not etudid in inmod_set: do_moduleimpl_inscription_create( {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, - REQUEST=REQUEST, formsemestre_id=formsemestre_id, ) diff --git a/app/scodoc/sco_moduleimpl_inscriptions.py b/app/scodoc/sco_moduleimpl_inscriptions.py index 42d2fff0c..ce1d972c1 100644 --- a/app/scodoc/sco_moduleimpl_inscriptions.py +++ b/app/scodoc/sco_moduleimpl_inscriptions.py @@ -582,6 +582,5 @@ def do_etud_inscrit_ue(etudid, formsemestre_id, ue_id, REQUEST=None): for moduleimpl_id in [x["moduleimpl_id"] for x in res]: sco_moduleimpl.do_moduleimpl_inscription_create( {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, - REQUEST=REQUEST, formsemestre_id=formsemestre_id, ) diff --git a/app/scodoc/sco_synchro_etuds.py b/app/scodoc/sco_synchro_etuds.py index db54f84cf..b3a158f52 100644 --- a/app/scodoc/sco_synchro_etuds.py +++ b/app/scodoc/sco_synchro_etuds.py @@ -32,7 +32,8 @@ import time import pprint from operator import itemgetter -from flask import g, url_for +from flask import g, url_for, send_file +from flask_login import current_user import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb @@ -55,7 +56,7 @@ EKEY_APO = "nip" EKEY_SCO = "code_nip" EKEY_NAME = "code NIP" - +# view: def formsemestre_synchro_etuds( formsemestre_id, etuds=[], # liste des codes NIP des etudiants a inscrire (ou deja inscrits) @@ -65,7 +66,6 @@ def formsemestre_synchro_etuds( dialog_confirmed=False, export_cat_xls=None, read_only=False, # Affiche sans permettre modifications - REQUEST=None, ): """Synchronise les étudiants de ce semestre avec ceux d'Apogée. On a plusieurs cas de figure: L'étudiant peut être @@ -85,15 +85,14 @@ def formsemestre_synchro_etuds( - l'utilisateur valide (cocher les étudiants à importer/inscrire) - go - etuds: apres selection par utilisateur, la liste des etudiants selectionnes + etuds: apres sélection par l'utilisateur, la liste des étudiants selectionnés que l'on va importer/inscrire """ log("formsemestre_synchro_etuds: formsemestre_id=%s" % formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem["etape_apo_str"] = sco_formsemestre.formsemestre_etape_apo_str(sem) # Write access ? - authuser = REQUEST.AUTHENTICATED_USER - if not authuser.has_permission(Permission.ScoEtudInscrit): + if not current_user.has_permission(Permission.ScoEtudInscrit): read_only = True if read_only: submitted = False @@ -110,9 +109,11 @@ def formsemestre_synchro_etuds( ) header = html_sco_header.sco_header(page_title="Synchronisation étudiants") footer = html_sco_header.sco_footer() - base_url = "%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id) - if anneeapogee: - base_url += "&anneeapogee=%s" % anneeapogee + base_url = url_for( + "notes.formsemestre_synchro_etuds", + scodoc_dept=g.scodoc_dept, + anneeapogee=anneeapogee or None, # si None, le param n'est pas dans l'URL + ) if anneeapogee is None: # année d'inscription par défaut anneeapogee = scu.annee_scolaire_debut( @@ -145,7 +146,12 @@ def formsemestre_synchro_etuds( base_url=base_url, read_only=read_only, ) - return sco_excel.send_excel_file(REQUEST, xls, filename + scu.XLSX_SUFFIX) + return send_file( + xls, + mimetype=scu.XLS_MIMETYPE, + download_name=scu.sanitize_filename(filename + scu.XLSX_SUFFIX), + as_attachment=True, + ) H = [header] if not submitted: @@ -235,9 +241,10 @@ def formsemestre_synchro_etuds( etudids_a_desinscrire = [nip2etudid(x) for x in a_desinscrire] etudids_a_desinscrire += a_desinscrire_without_key # - do_import_etuds_from_portal(sem, a_importer, etudsapo_ident, REQUEST) - sco_inscr_passage.do_inscrit(sem, etudids_a_inscrire, REQUEST) - sco_inscr_passage.do_desinscrit(sem, etudids_a_desinscrire, REQUEST) + with sco_cache.DefferedSemCacheManager(): + do_import_etuds_from_portal(sem, a_importer, etudsapo_ident) + sco_inscr_passage.do_inscrit(sem, etudids_a_inscrire) + sco_inscr_passage.do_desinscrit(sem, etudids_a_desinscrire) H.append( """

Opération effectuée

@@ -522,9 +529,9 @@ def formsemestre_synchro_etuds_help(sem): href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titreannee)s les étudiants inscrits dans l'étape Apogée correspondante (%(etape_apo_str)s)

-

Au départ, tous les étudiants d'Apogée sont sélectionnés; vous pouvez - en déselectionner certains. Tous les étudiants cochés seront inscrits au semestre ScoDoc, - les autres seront si besoin désinscrits. Aucune modification n'est effectuée avant +

Au départ, tous les étudiants d'Apogée sont sélectionnés; vous pouvez + en déselectionner certains. Tous les étudiants cochés seront inscrits au semestre ScoDoc, + les autres seront si besoin désinscrits. Aucune modification n'est effectuée avant d'appuyer sur le bouton "Appliquer les modifications".

Autres fonctions utiles

@@ -557,16 +564,17 @@ def get_opt_str(etud, k): return v.strip() -def get_annee_naissance(ddmmyyyyy): # stokee en dd/mm/yyyy dans le XML portail +def get_annee_naissance(ddmmyyyyy: str) -> int: + """Extrait l'année de la date stockée en dd/mm/yyyy dans le XML portail""" if not ddmmyyyyy: return None try: return int(ddmmyyyyy.split("/")[2]) - except: + except (ValueError, IndexError): return None -def do_import_etuds_from_portal(sem, a_importer, etudsapo_ident, REQUEST): +def do_import_etuds_from_portal(sem, a_importer, etudsapo_ident): """Inscrit les etudiants Apogee dans ce semestre.""" log("do_import_etuds_from_portal: a_importer=%s" % a_importer) if not a_importer: @@ -623,7 +631,6 @@ def do_import_etuds_from_portal(sem, a_importer, etudsapo_ident, REQUEST): args["etudid"], etat="I", etape=args["etape"], - REQUEST=REQUEST, method="synchro_apogee", ) except: @@ -838,16 +845,3 @@ def formsemestre_import_etud_admission( unknowns.append(code_nip) sco_cache.invalidate_formsemestre(formsemestre_id=sem["formsemestre_id"]) return no_nip, unknowns, changed_mails - - -def do_synch_inscrits_etuds(sem, etuds, REQUEST=None): # unused ? - """inscrits ces etudiants (déja dans ScoDoc) au semestre""" - log("do_synch_inscrits_etuds: inscription de %d etudiants" % len(etuds)) - for etud in etuds: - sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( - sem["formsemestre_id"], - etud["etudid"], - etat="I", - REQUEST=REQUEST, - method="synchro_apogee", - ) diff --git a/app/views/notes.py b/app/views/notes.py index 9045a94dc..7e80550b5 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -1358,7 +1358,7 @@ def formsemestre_desinscription( ) sco_formsemestre_inscriptions.do_formsemestre_desinscription( - etudid, formsemestre_id, REQUEST=REQUEST + etudid, formsemestre_id ) return (