Accelerate resync data ident with Apo
This commit is contained in:
parent
1c1e157761
commit
0ddf1faed4
@ -99,8 +99,7 @@ class PortalInterface:
|
|||||||
return photo_url
|
return photo_url
|
||||||
|
|
||||||
def get_maquette_url(self, context):
|
def get_maquette_url(self, context):
|
||||||
"""Full URL of service giving Apogee maquette pour une étape (fichier "CSV")
|
"""Full URL of service giving Apogee maquette pour une étape (fichier "CSV")"""
|
||||||
"""
|
|
||||||
maquette_url = context.get_preference("maquette_url")
|
maquette_url = context.get_preference("maquette_url")
|
||||||
if not maquette_url:
|
if not maquette_url:
|
||||||
# Default:
|
# Default:
|
||||||
@ -128,9 +127,10 @@ get_maquette_url = _PI.get_maquette_url
|
|||||||
get_portal_api_version = _PI.get_portal_api_version
|
get_portal_api_version = _PI.get_portal_api_version
|
||||||
|
|
||||||
|
|
||||||
def get_inscrits_etape(context, code_etape, anneeapogee=None):
|
def get_inscrits_etape(context, code_etape, anneeapogee=None, ntrials=2):
|
||||||
"""Liste des inscrits à une étape Apogée
|
"""Liste des inscrits à une étape Apogée
|
||||||
Result = list of dicts
|
Result = list of dicts
|
||||||
|
ntrials: try several time the same request, useful for some bad web services
|
||||||
"""
|
"""
|
||||||
log("get_inscrits_etape: code=%s anneeapogee=%s" % (code_etape, anneeapogee))
|
log("get_inscrits_etape: code=%s anneeapogee=%s" % (code_etape, anneeapogee))
|
||||||
if anneeapogee is None:
|
if anneeapogee is None:
|
||||||
@ -149,7 +149,13 @@ def get_inscrits_etape(context, code_etape, anneeapogee=None):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
req = etud_url + "?" + urllib.urlencode((("etape", code_etape),))
|
req = etud_url + "?" + urllib.urlencode((("etape", code_etape),))
|
||||||
doc = query_portal(req, timeout=portal_timeout)
|
actual_timeout = float(portal_timeout) / ntrials
|
||||||
|
if portal_timeout > 0:
|
||||||
|
actual_timeout = max(1, actual_timeout)
|
||||||
|
for _ntrial in range(ntrials):
|
||||||
|
doc = query_portal(req, timeout=actual_timeout)
|
||||||
|
if doc:
|
||||||
|
break
|
||||||
if not doc:
|
if not doc:
|
||||||
raise ScoValueError("pas de réponse du portail ! (timeout=%s)" % portal_timeout)
|
raise ScoValueError("pas de réponse du portail ! (timeout=%s)" % portal_timeout)
|
||||||
etuds = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
|
etuds = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
|
||||||
@ -197,30 +203,31 @@ def query_apogee_portal(context, **args):
|
|||||||
|
|
||||||
|
|
||||||
def xml_to_list_of_dicts(doc, req=None):
|
def xml_to_list_of_dicts(doc, req=None):
|
||||||
"""Convert an XML 1.0 str to a list of dicts.
|
"""Convert an XML 1.0 str to a list of dicts."""
|
||||||
"""
|
|
||||||
if not doc:
|
if not doc:
|
||||||
return []
|
return []
|
||||||
# Fix for buggy XML returned by some APIs (eg USPN)
|
# Fix for buggy XML returned by some APIs (eg USPN)
|
||||||
invalid_entities = {
|
invalid_entities = {
|
||||||
'Ç' : 'Ç',
|
"Ç": "Ç",
|
||||||
'& ' : '& ', # only when followed by a space (avoid affecting entities)
|
"& ": "& ", # only when followed by a space (avoid affecting entities)
|
||||||
# to be completed...
|
# to be completed...
|
||||||
}
|
}
|
||||||
for k in invalid_entities:
|
for k in invalid_entities:
|
||||||
doc = doc.replace(k,invalid_entities[k])
|
doc = doc.replace(k, invalid_entities[k])
|
||||||
#
|
#
|
||||||
try:
|
try:
|
||||||
dom = xml.dom.minidom.parseString(doc)
|
dom = xml.dom.minidom.parseString(doc)
|
||||||
except xml.parsers.expat.ExpatError as e:
|
except xml.parsers.expat.ExpatError as e:
|
||||||
# Find faulty part
|
# Find faulty part
|
||||||
err_zone = doc.splitlines()[e.lineno-1][e.offset:e.offset+20]
|
err_zone = doc.splitlines()[e.lineno - 1][e.offset : e.offset + 20]
|
||||||
# catch bug: log and re-raise exception
|
# catch bug: log and re-raise exception
|
||||||
log(
|
log(
|
||||||
"xml_to_list_of_dicts: exception in XML parseString\ndoc:\n%s\n(end xml doc)\n"
|
"xml_to_list_of_dicts: exception in XML parseString\ndoc:\n%s\n(end xml doc)\n"
|
||||||
% doc
|
% doc
|
||||||
)
|
)
|
||||||
raise ScoValueError("erreur dans la réponse reçue du portail ! (peut être : \"%s\")" % err_zone)
|
raise ScoValueError(
|
||||||
|
'erreur dans la réponse reçue du portail ! (peut être : "%s")' % err_zone
|
||||||
|
)
|
||||||
infos = []
|
infos = []
|
||||||
try:
|
try:
|
||||||
if dom.childNodes[0].nodeName != u"etudiants":
|
if dom.childNodes[0].nodeName != u"etudiants":
|
||||||
@ -275,8 +282,7 @@ def get_infos_apogee_allaccents(context, nom, prenom):
|
|||||||
|
|
||||||
|
|
||||||
def get_infos_apogee(context, nom, prenom):
|
def get_infos_apogee(context, nom, prenom):
|
||||||
"""recupere les codes Apogee en utilisant le web service CRIT
|
"""recupere les codes Apogee en utilisant le web service CRIT"""
|
||||||
"""
|
|
||||||
if (not nom) and (not prenom):
|
if (not nom) and (not prenom):
|
||||||
return []
|
return []
|
||||||
# essaie plusieurs codages: tirets, accents
|
# essaie plusieurs codages: tirets, accents
|
||||||
@ -322,8 +328,7 @@ def get_etud_apogee(context, code_nip):
|
|||||||
|
|
||||||
|
|
||||||
def get_default_etapes(context):
|
def get_default_etapes(context):
|
||||||
"""Liste par défaut: devrait etre lue d'un fichier de config
|
"""Liste par défaut: devrait etre lue d'un fichier de config"""
|
||||||
"""
|
|
||||||
filename = context.file_path + "/config/default-etapes.txt"
|
filename = context.file_path + "/config/default-etapes.txt"
|
||||||
log("get_default_etapes: reading %s" % filename)
|
log("get_default_etapes: reading %s" % filename)
|
||||||
f = open(filename)
|
f = open(filename)
|
||||||
@ -417,7 +422,7 @@ def get_etapes_apogee_dept(context):
|
|||||||
|
|
||||||
Si xml_etapes_by_dept est faux (nouveau format XML depuis sept 2014),
|
Si xml_etapes_by_dept est faux (nouveau format XML depuis sept 2014),
|
||||||
le departement n'est pas utilisé: toutes les étapes sont présentées.
|
le departement n'est pas utilisé: toutes les étapes sont présentées.
|
||||||
|
|
||||||
Returns [ ( code, intitule) ], ordonnée
|
Returns [ ( code, intitule) ], ordonnée
|
||||||
"""
|
"""
|
||||||
xml_etapes_by_dept = context.get_preference("xml_etapes_by_dept")
|
xml_etapes_by_dept = context.get_preference("xml_etapes_by_dept")
|
||||||
@ -466,7 +471,7 @@ def _normalize_apo_fields(infolist):
|
|||||||
infolist: liste de dict renvoyés par le portail Apogee
|
infolist: liste de dict renvoyés par le portail Apogee
|
||||||
|
|
||||||
recode les champs: paiementinscription (-> booleen), datefinalisationinscription (date)
|
recode les champs: paiementinscription (-> booleen), datefinalisationinscription (date)
|
||||||
ajoute le champs 'paiementinscription_str' : 'ok', 'Non' ou '?'
|
ajoute le champs 'paiementinscription_str' : 'ok', 'Non' ou '?'
|
||||||
ajuoute le champs 'etape' (= None) s'il n'est pas présent
|
ajuoute le champs 'etape' (= None) s'il n'est pas présent
|
||||||
"""
|
"""
|
||||||
for infos in infolist:
|
for infos in infolist:
|
||||||
@ -503,7 +508,7 @@ def check_paiement_etuds(context, etuds):
|
|||||||
"""Interroge le portail pour vérifier l'état de "paiement" et l'étape d'inscription.
|
"""Interroge le portail pour vérifier l'état de "paiement" et l'étape d'inscription.
|
||||||
|
|
||||||
Seuls les etudiants avec code NIP sont renseignés.
|
Seuls les etudiants avec code NIP sont renseignés.
|
||||||
|
|
||||||
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud.
|
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud.
|
||||||
|
|
||||||
En sortie: modif les champs de chaque etud
|
En sortie: modif les champs de chaque etud
|
||||||
@ -539,8 +544,7 @@ def check_paiement_etuds(context, etuds):
|
|||||||
|
|
||||||
|
|
||||||
def get_maquette_apogee(context, etape="", annee_scolaire=""):
|
def get_maquette_apogee(context, etape="", annee_scolaire=""):
|
||||||
"""Maquette CSV Apogee pour une étape et une annee scolaire
|
"""Maquette CSV Apogee pour une étape et une annee scolaire"""
|
||||||
"""
|
|
||||||
maquette_url = get_maquette_url(context)
|
maquette_url = get_maquette_url(context)
|
||||||
if not maquette_url:
|
if not maquette_url:
|
||||||
return None
|
return None
|
||||||
|
@ -778,6 +778,17 @@ def formsemestre_import_etud_admission(
|
|||||||
changed_mails = [] # modification d'adresse mails
|
changed_mails = [] # modification d'adresse mails
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
|
|
||||||
|
# Essaie de recuperer les etudiants des étapes, car
|
||||||
|
# la requete get_inscrits_etape est en général beaucoup plus
|
||||||
|
# rapide que les requetes individuelles get_etud_apogee
|
||||||
|
anneeapogee = str(annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]))
|
||||||
|
apo_etuds = {} # nip : etud apo
|
||||||
|
for etape in sem["etapes"]:
|
||||||
|
etudsapo = sco_portal_apogee.get_inscrits_etape(
|
||||||
|
context, etape, anneeapogee=anneeapogee
|
||||||
|
)
|
||||||
|
apo_etuds.update({e["nip"]: e for e in etudsapo})
|
||||||
|
|
||||||
for i in ins:
|
for i in ins:
|
||||||
etudid = i["etudid"]
|
etudid = i["etudid"]
|
||||||
info = context.getEtudInfo(etudid=etudid, filled=1)[0]
|
info = context.getEtudInfo(etudid=etudid, filled=1)[0]
|
||||||
@ -785,7 +796,10 @@ def formsemestre_import_etud_admission(
|
|||||||
if not code_nip:
|
if not code_nip:
|
||||||
no_nip.append(etudid)
|
no_nip.append(etudid)
|
||||||
else:
|
else:
|
||||||
etud = sco_portal_apogee.get_etud_apogee(context, code_nip)
|
etud = apo_etuds.get(code_nip)
|
||||||
|
if not etud:
|
||||||
|
# pas vu dans les etudiants de l'étape, tente en individuel
|
||||||
|
etud = sco_portal_apogee.get_etud_apogee(context, code_nip)
|
||||||
if etud:
|
if etud:
|
||||||
do_import_etud_admission(
|
do_import_etud_admission(
|
||||||
context,
|
context,
|
||||||
@ -818,6 +832,7 @@ def formsemestre_import_etud_admission(
|
|||||||
changed_mails.append((info, etud["mail"]))
|
changed_mails.append((info, etud["mail"]))
|
||||||
else:
|
else:
|
||||||
unknowns.append(code_nip)
|
unknowns.append(code_nip)
|
||||||
|
context._inval_cache(formsemestre_id=sem["formsemestre_id"])
|
||||||
return no_nip, unknowns, changed_mails
|
return no_nip, unknowns, changed_mails
|
||||||
|
|
||||||
|
|
||||||
|
@ -836,8 +836,9 @@ def sort_dates(L, reverse=False):
|
|||||||
|
|
||||||
|
|
||||||
def query_portal(req, msg="Portail Apogee", timeout=3):
|
def query_portal(req, msg="Portail Apogee", timeout=3):
|
||||||
"""retreive external data using http request
|
"""Retreives external data using HTTP request
|
||||||
(used to connect to Apogee portal, or ScoDoc server)
|
(used to connect to Apogee portal, or ScoDoc server)
|
||||||
|
returns a string, "" on error
|
||||||
"""
|
"""
|
||||||
log("query_portal: %s" % req)
|
log("query_portal: %s" % req)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user