From afaab2d5e0464fe067a65eff4662731dbedd2fdb Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet
Date: Thu, 2 Sep 2021 18:05:22 +0200
Subject: [PATCH] Optimisation de la synchro inscription
---
app/scodoc/sco_cache.py | 25 +++++++++
app/scodoc/sco_formsemestre_exterieurs.py | 1 -
app/scodoc/sco_formsemestre_inscriptions.py | 21 +++-----
app/scodoc/sco_groups.py | 31 +++++------
app/scodoc/sco_import_etuds.py | 3 +-
app/scodoc/sco_inscr_passage.py | 11 ++--
app/scodoc/sco_moduleimpl.py | 18 +++----
app/scodoc/sco_moduleimpl_inscriptions.py | 1 -
app/scodoc/sco_synchro_etuds.py | 60 ++++++++++-----------
app/views/notes.py | 2 +-
10 files changed, 87 insertions(+), 86 deletions(-)
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 (