Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
3 changed files with 59 additions and 23 deletions
Showing only changes of commit fbff151be0 - Show all commits

View File

@ -551,7 +551,7 @@ class Identite(models.ScoDocModel):
.all() .all()
) )
def inscription_courante(self): def inscription_courante(self) -> "FormSemestreInscription | None":
"""La première inscription à un formsemestre _actuellement_ en cours. """La première inscription à un formsemestre _actuellement_ en cours.
None s'il n'y en a pas (ou plus, ou pas encore). None s'il n'y en a pas (ou plus, ou pas encore).
""" """

View File

@ -32,8 +32,7 @@ from flask import url_for, g, request
from flask_login import current_user from flask_login import current_user
import app import app
from app.models import Departement from app.models import Departement, Identite
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
@ -55,7 +54,9 @@ def form_search_etud(
"form recherche par nom" "form recherche par nom"
H = [] H = []
H.append( H.append(
f"""<form action="{ url_for("scolar.search_etud_in_dept", scodoc_dept=g.scodoc_dept) }" method="POST"> f"""<form action="{
url_for("scolar.search_etud_in_dept", scodoc_dept=g.scodoc_dept)
}" method="POST">
<b>{title}</b> <b>{title}</b>
<input type="text" name="expnom" class="in-expnom" width="12" spellcheck="false" value=""> <input type="text" name="expnom" class="in-expnom" width="12" spellcheck="false" value="">
<input type="submit" value="Chercher"> <input type="submit" value="Chercher">
@ -100,9 +101,9 @@ def form_search_etud(
return "\n".join(H) return "\n".join(H)
def search_etuds_infos_from_exp(expnom: str = "") -> list[dict]: def search_etuds_infos_from_exp(expnom: str = "") -> list[Identite]:
"""Cherche étudiants, expnom peut être, dans cet ordre: """Cherche étudiants, expnom peut être, dans cet ordre:
un etudid (int), un code NIP, ou le début d'un nom. un etudid (int), un code NIP, ou une partie d'un nom (case insensitive).
""" """
if not isinstance(expnom, int) and len(expnom) <= 1: if not isinstance(expnom, int) and len(expnom) <= 1:
return [] # si expnom est trop court, n'affiche rien return [] # si expnom est trop court, n'affiche rien
@ -111,13 +112,22 @@ def search_etuds_infos_from_exp(expnom: str = "") -> list[dict]:
except ValueError: except ValueError:
etudid = None etudid = None
if etudid is not None: if etudid is not None:
etuds = sco_etud.get_etud_info(filled=True, etudid=expnom) etud = Identite.query.filter_by(dept_id=g.scodoc_dept_id, id=etudid).first()
if len(etuds) == 1: if etud:
return etuds return [etud]
expnom_str = str(expnom) expnom_str = str(expnom)
if scu.is_valid_code_nip(expnom_str): if scu.is_valid_code_nip(expnom_str):
return search_etuds_infos(code_nip=expnom_str) etuds = Identite.query.filter_by(
return search_etuds_infos(expnom=expnom_str) dept_id=g.scodoc_dept_id, code_nip=expnom_str
).all()
if etuds:
return etuds
return (
Identite.query.filter_by(dept_id=g.scodoc_dept_id)
.filter(Identite.nom.op("~*")(expnom_str))
.all()
)
def search_etud_in_dept(expnom=""): def search_etud_in_dept(expnom=""):
@ -152,7 +162,7 @@ def search_etud_in_dept(expnom=""):
if len(etuds) == 1: if len(etuds) == 1:
# va directement a la fiche # va directement a la fiche
url_args["etudid"] = etuds[0]["etudid"] url_args["etudid"] = etuds[0].id
return flask.redirect(url_for(endpoint, **url_args)) return flask.redirect(url_for(endpoint, **url_args))
H = [ H = [
@ -179,14 +189,39 @@ def search_etud_in_dept(expnom=""):
) )
if len(etuds) > 0: if len(etuds) > 0:
# Choix dans la liste des résultats: # Choix dans la liste des résultats:
rows = []
e: Identite
for e in etuds: for e in etuds:
url_args["etudid"] = e["etudid"] url_args["etudid"] = e.id
target = url_for(endpoint, **url_args) target = url_for(endpoint, **url_args)
e["_nomprenom_target"] = target cur_inscription = e.inscription_courante()
e["inscription_target"] = target inscription = (
e["_nomprenom_td_attrs"] = 'id="%s" class="etudinfo"' % (e["etudid"]) e.inscription_descr().get("inscription_str", "")
sco_groups.etud_add_group_infos( if cur_inscription
e, e["cursem"]["formsemestre_id"] if e["cursem"] else None else ""
)
groupes = (
", ".join(
gr.group_name
for gr in sco_groups.get_etud_formsemestre_groups(
e, cur_inscription.formsemestre
)
)
if cur_inscription
else ""
)
rows.append(
{
"code_nip": e.code_nip or "",
"etudid": e.id,
"inscription": inscription,
"inscription_target": target,
"groupes": groupes,
"nomprenom": e.nomprenom,
"_nomprenom_target": target,
"_nomprenom_td_attrs": f'id="{e.id}" class="etudinfo"',
}
) )
tab = GenTable( tab = GenTable(
@ -197,7 +232,7 @@ def search_etud_in_dept(expnom=""):
"inscription": "Inscription", "inscription": "Inscription",
"groupes": "Groupes", "groupes": "Groupes",
}, },
rows=etuds, rows=rows,
html_sortable=True, html_sortable=True,
html_class="table_leftalign", html_class="table_leftalign",
preferences=sco_preferences.SemPreferences(), preferences=sco_preferences.SemPreferences(),
@ -213,15 +248,16 @@ def search_etud_in_dept(expnom=""):
) )
) )
else: else:
H.append('<h2 style="color: red;">Aucun résultat pour "%s".</h2>' % expnom) H.append(f'<h2 style="color: red;">Aucun résultat pour "{expnom}".</h2>')
H.append( H.append(
"""<p class="help">La recherche porte sur tout ou partie du NOM ou du NIP de l'étudiant. Saisir au moins deux caractères.</p>""" """<p class="help">La recherche porte sur tout ou partie du NOM ou du NIP
de l'étudiant. Saisir au moins deux caractères.</p>"""
) )
return "\n".join(H) + html_sco_header.sco_footer() return "\n".join(H) + html_sco_header.sco_footer()
# Was chercheEtudsInfo() # Was chercheEtudsInfo()
def search_etuds_infos(expnom=None, code_nip=None): def search_etuds_infos(expnom=None, code_nip=None) -> list[dict]:
"""recherche les étudiants correspondants à expnom ou au code_nip """recherche les étudiants correspondants à expnom ou au code_nip
et ramene liste de mappings utilisables en DTML. et ramene liste de mappings utilisables en DTML.
""" """

View File

@ -843,7 +843,7 @@ FORBIDDEN_CHARS_EXP = re.compile(r"[*\|~\(\)\\]")
ALPHANUM_EXP = re.compile(r"^[\w-]+$", re.UNICODE) ALPHANUM_EXP = re.compile(r"^[\w-]+$", re.UNICODE)
def is_valid_code_nip(s: str) -> bool: def is_valid_code_nip(s: str) -> bool | None:
"""True si s peut être un code NIP: au moins 6 chiffres décimaux""" """True si s peut être un code NIP: au moins 6 chiffres décimaux"""
if not s: if not s:
return False return False