forked from ScoDoc/ScoDoc
Edition étudiant: interrogation Apgée avec portail v2 (utilise nip)
This commit is contained in:
parent
17940d988d
commit
f34996c8a7
@ -202,8 +202,7 @@ def get_inscrits_etape(
|
||||
return False
|
||||
else:
|
||||
log(
|
||||
"get_inscrits_etape: pas inscription dans code_etape=%s e=%s"
|
||||
% (code_etape, e)
|
||||
"get_inscrits_etape: pas inscription dans code_etape={code_etape} e={e}"
|
||||
)
|
||||
return False # ??? pas d'annee d'inscription dans la réponse
|
||||
|
||||
@ -215,8 +214,7 @@ def get_inscrits_etape(
|
||||
|
||||
def query_apogee_portal(**args):
|
||||
"""Recupere les infos sur les etudiants nommés
|
||||
args: nom, prenom, code_nip
|
||||
(nom et prenom matchent des parties de noms)
|
||||
args: nom, prenom, code_ine, code_nip
|
||||
"""
|
||||
etud_url = get_etud_url()
|
||||
api_ver = get_portal_api_version()
|
||||
@ -225,7 +223,6 @@ def query_apogee_portal(**args):
|
||||
if api_ver > 1:
|
||||
if args["nom"] or args["prenom"]:
|
||||
# Ne fonctionne pas avec l'API 2 sur nom et prenom
|
||||
# XXX TODO : va poser problème pour la page modif données étudiants : A VOIR
|
||||
return []
|
||||
portal_timeout = sco_preferences.get_preference("portal_timeout")
|
||||
req = etud_url + "?" + urllib.parse.urlencode(list(args.items()))
|
||||
@ -243,22 +240,21 @@ def xml_to_list_of_dicts(doc, req=None):
|
||||
"& ": "& ", # only when followed by a space (avoid affecting entities)
|
||||
# to be completed...
|
||||
}
|
||||
for k in invalid_entities:
|
||||
doc = doc.replace(k, invalid_entities[k])
|
||||
for k, repl in invalid_entities.items():
|
||||
doc = doc.replace(k, repl)
|
||||
#
|
||||
try:
|
||||
dom = xml.dom.minidom.parseString(doc)
|
||||
except xml.parsers.expat.ExpatError as e:
|
||||
except xml.parsers.expat.ExpatError as exc:
|
||||
# Find faulty part
|
||||
err_zone = doc.splitlines()[e.lineno - 1][e.offset : e.offset + 20]
|
||||
err_zone = doc.splitlines()[exc.lineno - 1][exc.offset : exc.offset + 20]
|
||||
# catch bug: log and re-raise exception
|
||||
log(
|
||||
"xml_to_list_of_dicts: exception in XML parseString\ndoc:\n%s\n(end xml doc)\n"
|
||||
% doc
|
||||
f"xml_to_list_of_dicts: exception in XML parseString\ndoc:\n{doc}\n(end xml doc)\n"
|
||||
)
|
||||
raise ScoValueError(
|
||||
'erreur dans la réponse reçue du portail ! (peut être : "%s")' % err_zone
|
||||
)
|
||||
f'erreur dans la réponse reçue du portail ! (peut être : "{err_zone}")'
|
||||
) from exc
|
||||
infos = []
|
||||
try:
|
||||
if dom.childNodes[0].nodeName != "etudiants":
|
||||
@ -267,17 +263,19 @@ def xml_to_list_of_dicts(doc, req=None):
|
||||
for etudiant in etudiants:
|
||||
d = {}
|
||||
# recupere toutes les valeurs <valeur>XXX</valeur>
|
||||
for e in etudiant.childNodes:
|
||||
if e.nodeType == e.ELEMENT_NODE:
|
||||
childs = e.childNodes
|
||||
for exc in etudiant.childNodes:
|
||||
if exc.nodeType == exc.ELEMENT_NODE:
|
||||
childs = exc.childNodes
|
||||
if len(childs):
|
||||
d[str(e.nodeName)] = childs[0].nodeValue
|
||||
d[str(exc.nodeName)] = childs[0].nodeValue
|
||||
infos.append(d)
|
||||
except:
|
||||
except Exception as exc:
|
||||
log("*** invalid XML response from Etudiant Web Service")
|
||||
log("req=%s" % req)
|
||||
log("doc=%s" % doc)
|
||||
raise ValueError("invalid XML response from Etudiant Web Service\n%s" % doc)
|
||||
log(f"req={req}")
|
||||
log(f"doc={doc}")
|
||||
raise ValueError(
|
||||
f"invalid XML response from Etudiant Web Service\n{doc}"
|
||||
) from exc
|
||||
return infos
|
||||
|
||||
|
||||
@ -301,8 +299,8 @@ def get_infos_apogee_allaccents(nom, prenom):
|
||||
return infos
|
||||
|
||||
|
||||
def get_infos_apogee(nom, prenom):
|
||||
"""recupere les codes Apogee en utilisant le web service CRIT"""
|
||||
def get_etuds_apogee_for_nom_prenom(nom: str, prenom: str) -> list[dict]:
|
||||
"""Récupere les codes Apogee en utilisant le portail Apogée"""
|
||||
if (not nom) and (not prenom):
|
||||
return []
|
||||
# essaie plusieurs codages: tirets, accents
|
||||
@ -326,27 +324,27 @@ def get_infos_apogee(nom, prenom):
|
||||
return infos
|
||||
|
||||
|
||||
def get_etud_apogee(code_nip):
|
||||
def get_etuds_apogee_from_nip(code_nip: str) -> list[dict]:
|
||||
"""Informations à partir du code NIP.
|
||||
None si pas d'infos sur cet etudiant.
|
||||
Liste des étudiants ayant ce code NIP.
|
||||
Exception si reponse invalide.
|
||||
"""
|
||||
if not code_nip:
|
||||
return {}
|
||||
return []
|
||||
etud_url = get_etud_url()
|
||||
if not etud_url:
|
||||
return {}
|
||||
return []
|
||||
portal_timeout = sco_preferences.get_preference("portal_timeout")
|
||||
req = etud_url + "?" + urllib.parse.urlencode((("nip", code_nip),))
|
||||
doc = scu.query_portal(req, timeout=portal_timeout)
|
||||
d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
|
||||
if not d:
|
||||
return None
|
||||
return []
|
||||
if len(d) > 1:
|
||||
log(f"get_etud_apogee({code_nip}): {len(d)} etudiants !\n{doc}")
|
||||
flash("Attention: plusieurs étudiants inscrits avec le NIP {code_nip}")
|
||||
log(f"get_etuds_apogee_from_nip({code_nip}): {len(d)} etudiants !\n{doc}")
|
||||
flash(f"Attention: plusieurs étudiants inscrits avec le NIP {code_nip}")
|
||||
# dans ce cas, renvoie le premier étudiant
|
||||
return d[0]
|
||||
return d
|
||||
|
||||
|
||||
def get_default_etapes():
|
||||
@ -413,14 +411,14 @@ def get_etapes_apogee():
|
||||
SCO_CACHE_ETAPE_FILENAME, "w", encoding=scu.SCO_ENCODING
|
||||
) as f:
|
||||
f.write(doc)
|
||||
except:
|
||||
except Exception:
|
||||
log(f"invalid XML response from getEtapes Web Service\n{etapes_url}")
|
||||
# Avons-nous la copie d'une réponse récente ?
|
||||
try:
|
||||
doc = open(SCO_CACHE_ETAPE_FILENAME, encoding=scu.SCO_ENCODING).read()
|
||||
infos = _parse_etapes_from_xml(doc)
|
||||
log(f"using last saved version from {SCO_CACHE_ETAPE_FILENAME}")
|
||||
except:
|
||||
except Exception:
|
||||
infos = {}
|
||||
else:
|
||||
# Pas de portail: utilise étapes par défaut livrées avec ScoDoc
|
||||
@ -452,7 +450,7 @@ def get_etapes_apogee_dept():
|
||||
xml_etapes_by_dept = sco_preferences.get_preference("xml_etapes_by_dept")
|
||||
if xml_etapes_by_dept:
|
||||
portal_dept_name = sco_preferences.get_preference("portal_dept_name")
|
||||
log('get_etapes_apogee_dept: portal_dept_name="%s"' % portal_dept_name)
|
||||
log(f'get_etapes_apogee_dept: portal_dept_name="{portal_dept_name}"')
|
||||
else:
|
||||
portal_dept_name = ""
|
||||
log("get_etapes_apogee_dept: pas de sections par departement")
|
||||
@ -460,8 +458,7 @@ def get_etapes_apogee_dept():
|
||||
infos = get_etapes_apogee()
|
||||
if portal_dept_name and portal_dept_name not in infos:
|
||||
log(
|
||||
"get_etapes_apogee_dept: pas de section '%s' dans la reponse portail"
|
||||
% portal_dept_name
|
||||
f"get_etapes_apogee_dept: pas de section '{portal_dept_name}' dans la reponse portail"
|
||||
)
|
||||
return []
|
||||
if portal_dept_name:
|
||||
@ -469,8 +466,8 @@ def get_etapes_apogee_dept():
|
||||
else:
|
||||
# prend toutes les etapes
|
||||
etapes = []
|
||||
for k in infos.keys():
|
||||
etapes += list(infos[k].items())
|
||||
for info in infos.values():
|
||||
etapes += list(info.items())
|
||||
|
||||
etapes.sort() # tri sur le code etape
|
||||
return etapes
|
||||
@ -571,8 +568,8 @@ def check_paiement_etuds(etuds):
|
||||
etud["etape"] = None
|
||||
else:
|
||||
# Modifie certains champs de l'étudiant:
|
||||
infos = get_etud_apogee(etud["code_nip"])
|
||||
if infos:
|
||||
etuds_apo = get_etuds_apogee_from_nip(etud["code_nip"])
|
||||
if etuds_apo:
|
||||
for k in (
|
||||
"paiementinscription",
|
||||
"paiementinscription_str",
|
||||
@ -580,7 +577,7 @@ def check_paiement_etuds(etuds):
|
||||
"datefinalisationinscription_str",
|
||||
"etape",
|
||||
):
|
||||
etud[k] = infos[k]
|
||||
etud[k] = etuds_apo[0][k]
|
||||
else:
|
||||
etud["datefinalisationinscription"] = None
|
||||
etud["datefinalisationinscription_str"] = "Erreur"
|
||||
|
@ -837,7 +837,7 @@ def formsemestre_import_etud_admission(
|
||||
|
||||
# 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
|
||||
# rapide que les requetes individuelles get_etuds_apogee_from_nip
|
||||
annee_apogee = str(
|
||||
scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])
|
||||
)
|
||||
@ -858,7 +858,8 @@ def formsemestre_import_etud_admission(
|
||||
data_apo = apo_etuds.get(code_nip)
|
||||
if not data_apo:
|
||||
# pas vu dans les etudiants de l'étape, tente en individuel
|
||||
data_apo = sco_portal_apogee.get_etud_apogee(code_nip)
|
||||
etuds_apo = sco_portal_apogee.get_etuds_apogee_from_nip(code_nip)
|
||||
data_apo = etuds_apo[0] if etuds_apo else None
|
||||
if data_apo:
|
||||
update_etape_formsemestre_inscription(i, data_apo)
|
||||
do_import_etud_admission(
|
||||
|
@ -1374,15 +1374,17 @@ def _etudident_create_or_edit_form(edit):
|
||||
submitlabel = "Ajouter cet étudiant"
|
||||
H.append(
|
||||
"""<h2>Création d'un étudiant</h2>
|
||||
<p class="warning">En général, il est <b>recommandé</b> d'importer les
|
||||
étudiants depuis Apogée ou via un fichier Excel (menu <b>Inscriptions</b>
|
||||
dans le semestre).
|
||||
</p>
|
||||
<p>
|
||||
N'utilisez ce formulaire au cas par cas que <b>pour les cas particuliers</b>
|
||||
ou si votre établissement n'utilise pas d'autre logiciel de gestion des
|
||||
inscriptions.
|
||||
</p>
|
||||
<div class="scobox warning">Attention
|
||||
<p>En général, il est <b>recommandé</b> d'importer les
|
||||
étudiants depuis Apogée ou via un fichier Excel (menu <b>Inscriptions</b>
|
||||
dans le semestre).
|
||||
</p>
|
||||
<p>
|
||||
N'utilisez ce formulaire au cas par cas que <b>pour les cas particuliers</b>
|
||||
ou si votre établissement n'utilise pas d'autre logiciel de gestion des
|
||||
inscriptions.
|
||||
</p>
|
||||
</div>
|
||||
<p class"warning"><em>L'étudiant créé ne sera pas inscrit.
|
||||
Pensez à l'inscrire dans un semestre !</em></p>
|
||||
"""
|
||||
@ -1395,63 +1397,13 @@ def _etudident_create_or_edit_form(edit):
|
||||
etud_o: Identite = Identite.get_etud(etudid)
|
||||
descr.append(("etudid", {"default": etudid, "input_type": "hidden"}))
|
||||
H.append(f"""<h2>Modification des données de {etud_o.html_link_fiche()}</h2>""")
|
||||
initvalues = sco_etud.etudident_list(cnx, {"etudid": etudid})
|
||||
initvalues = sco_etud.etudident_list(cnx, {"etudid": etudid}) # XXX TODO
|
||||
assert len(initvalues) == 1
|
||||
initvalues = initvalues[0]
|
||||
submitlabel = "Modifier les données"
|
||||
|
||||
infos_apogee_html = _infos_apogee_html_etuds(scu.get_request_args(), initvalues)
|
||||
vals = scu.get_request_args()
|
||||
nom = vals.get("nom", None)
|
||||
if nom is None:
|
||||
nom = initvalues.get("nom", None)
|
||||
if nom is None:
|
||||
infos = []
|
||||
else:
|
||||
prenom = vals.get("prenom", "")
|
||||
if vals.get("tf_submitted", False) and not prenom:
|
||||
prenom = initvalues.get("prenom", "")
|
||||
infos = sco_portal_apogee.get_infos_apogee(nom, prenom)
|
||||
|
||||
if infos:
|
||||
formatted_infos = [
|
||||
"""
|
||||
<script type="text/javascript">
|
||||
function copy_nip(nip) {
|
||||
document.tf.code_nip.value = nip;
|
||||
}
|
||||
</script>
|
||||
<ol>"""
|
||||
]
|
||||
nanswers = len(infos)
|
||||
nmax = 10 # nb max de reponse montrées
|
||||
infos = infos[:nmax]
|
||||
for i in infos:
|
||||
formatted_infos.append("<li><ul>")
|
||||
for k in i.keys():
|
||||
if k != "nip":
|
||||
item = "<li>%s : %s</li>" % (k, i[k])
|
||||
else:
|
||||
item = (
|
||||
'<li><form>%s : %s <input type="button" value="copier ce code" onmousedown="copy_nip(%s);"/></form></li>'
|
||||
% (k, i[k], i[k])
|
||||
)
|
||||
formatted_infos.append(item)
|
||||
|
||||
formatted_infos.append("</ul></li>")
|
||||
formatted_infos.append("</ol>")
|
||||
m = "%d étudiants trouvés" % nanswers
|
||||
if len(infos) != nanswers:
|
||||
m += " (%d montrés)" % len(infos)
|
||||
A = """<div class="infoapogee">
|
||||
<h5>Informations Apogée</h5>
|
||||
<p>%s</p>
|
||||
%s
|
||||
</div>""" % (
|
||||
m,
|
||||
"\n".join(formatted_infos),
|
||||
)
|
||||
else:
|
||||
A = """<div class="infoapogee"><p>Pas d'informations d'Apogée</p></div>"""
|
||||
|
||||
require_ine = sco_preferences.get_preference("always_require_ine")
|
||||
|
||||
@ -1727,7 +1679,7 @@ def _etudident_create_or_edit_form(edit):
|
||||
if tf[0] in (0, -1):
|
||||
return render_template(
|
||||
"sco_page_dept.j2",
|
||||
content="\n".join(H) + tf[1] + "<p>" + A,
|
||||
content="\n".join(H) + tf[1] + infos_apogee_html,
|
||||
title="Création/édition d'étudiant",
|
||||
)
|
||||
else:
|
||||
@ -1746,8 +1698,7 @@ def _etudident_create_or_edit_form(edit):
|
||||
content="\n".join(H)
|
||||
+ tf_error_message("Nom ou prénom invalide")
|
||||
+ tf[1]
|
||||
+ "<p>"
|
||||
+ A,
|
||||
+ infos_apogee_html,
|
||||
title="Création/édition d'étudiant",
|
||||
)
|
||||
if not tf[2]["dont_check_homonyms"] and nb_homonyms > 0:
|
||||
@ -1773,9 +1724,8 @@ def _etudident_create_or_edit_form(edit):
|
||||
"""
|
||||
)
|
||||
+ tf[1]
|
||||
+ "<p>"
|
||||
+ A
|
||||
+ homonyms_html
|
||||
+ infos_apogee_html
|
||||
),
|
||||
)
|
||||
tf[2]["date_naissance"] = (
|
||||
@ -1796,19 +1746,70 @@ def _etudident_create_or_edit_form(edit):
|
||||
etud_o.admission = admission
|
||||
admission.from_dict(tf[2])
|
||||
db.session.commit()
|
||||
|
||||
etud = sco_etud.etudident_list(cnx, {"etudid": etud_o.id})[0]
|
||||
sco_etud.fill_etuds_info([etud])
|
||||
# Inval semesters with this student:
|
||||
to_inval = [s["formsemestre_id"] for s in etud["sems"]]
|
||||
for formsemestre_id in to_inval:
|
||||
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id)
|
||||
#
|
||||
# Inval semesters with this student:
|
||||
for inscription in etud_o.formsemestre_inscriptions:
|
||||
sco_cache.invalidate_formsemestre(
|
||||
formsemestre_id=inscription.formsemestre_id
|
||||
)
|
||||
#
|
||||
return flask.redirect(
|
||||
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||
)
|
||||
|
||||
|
||||
def _infos_apogee_html_etuds(vals: dict, initvalues: dict) -> str:
|
||||
"fragment de html pour lister les étudiants correspondants"
|
||||
nom = vals.get("nom", initvalues.get("nom", None))
|
||||
nip = vals.get("code_nip", initvalues.get("code_nip", "")).strip()
|
||||
if nom is None and nip is None:
|
||||
etuds_apo = []
|
||||
elif nip:
|
||||
etuds_apo = sco_portal_apogee.get_etuds_apogee_from_nip(nip)
|
||||
else:
|
||||
prenom = vals.get("prenom", "")
|
||||
if vals.get("tf_submitted", False) and not prenom:
|
||||
prenom = initvalues.get("prenom", "")
|
||||
etuds_apo = sco_portal_apogee.get_etuds_apogee_for_nom_prenom(nom, prenom)
|
||||
|
||||
if etuds_apo:
|
||||
formatted_infos = [
|
||||
"""
|
||||
<script type="text/javascript">
|
||||
function copy_nip(nip) {
|
||||
document.tf.code_nip.value = nip;
|
||||
}
|
||||
</script>
|
||||
<ol>"""
|
||||
]
|
||||
nanswers = len(etuds_apo)
|
||||
nmax = 10 # nb max de réponse montrées
|
||||
etuds_apo = etuds_apo[:nmax]
|
||||
for i in etuds_apo:
|
||||
formatted_infos.append("<li><ul>")
|
||||
for k in i.keys():
|
||||
if k != "nip":
|
||||
item = f"<li><tt>{k}</tt> : {i[k]}</li>"
|
||||
else:
|
||||
item = f"""<li><form><tt>{k}</tt> : {i[k]}
|
||||
<input type="button" value="copier ce code" onmousedown="copy_nip({i[k]});"/>
|
||||
</form>
|
||||
</li>"""
|
||||
formatted_infos.append(item)
|
||||
|
||||
formatted_infos.append("</ul></li>")
|
||||
formatted_infos.append("</ol>")
|
||||
m = f"{nanswers} étudiants trouvés"
|
||||
if len(etuds_apo) != nanswers:
|
||||
m += " ({len(etuds_apo)} affichés)"
|
||||
return f"""
|
||||
<div class="scobox infoapogee">
|
||||
<div class="scobox-title">Informations Apogée</div>
|
||||
<p>{m}</p>
|
||||
{''.join(formatted_infos)}
|
||||
</div>"""
|
||||
return """<div class="scobox infoapogee">Pas d'informations d'Apogée</div>"""
|
||||
|
||||
|
||||
@bp.route("/etud_copy_in_other_dept/<int:etudid>", methods=["GET", "POST"])
|
||||
@scodoc
|
||||
@permission_required(
|
||||
@ -1985,7 +1986,7 @@ def check_group_apogee(group_id, etat=None, fix=False, fixmail=False):
|
||||
t["email"],
|
||||
t["code_nip"],
|
||||
)
|
||||
infos = sco_portal_apogee.get_infos_apogee(nom, prenom)
|
||||
infos = sco_portal_apogee.get_etuds_apogee_for_nom_prenom(nom, prenom)
|
||||
if not infos:
|
||||
info_apogee = f"""<b>Pas d'information</b>
|
||||
(<a class="stdlink" href="{
|
||||
|
Loading…
x
Reference in New Issue
Block a user