535 lines
17 KiB
Python
535 lines
17 KiB
Python
##############################################################################
|
|
# ScoDoc
|
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
|
# See LICENSE
|
|
##############################################################################
|
|
|
|
"""
|
|
API : accès aux étudiants
|
|
"""
|
|
|
|
from flask import jsonify
|
|
|
|
import app
|
|
from app.api import bp
|
|
from app.api.errors import error_response
|
|
from app.api.auth import token_auth, token_permission_required
|
|
from app.models import Departement, FormSemestreInscription, FormSemestre, Identite
|
|
from app.scodoc import sco_bulletins
|
|
from app.scodoc import sco_groups
|
|
from app.scodoc.sco_permissions import Permission
|
|
|
|
|
|
@bp.route("/etudiants/courant", defaults={"long": False})
|
|
@bp.route("/etudiants/courant/long", defaults={"long": True})
|
|
@token_auth.login_required
|
|
@token_permission_required(Permission.APIView)
|
|
def etudiants_courant(long=False):
|
|
"""
|
|
Liste des étudiants inscrits dans un formsemestre actuellement en cours.
|
|
|
|
Exemple de résultat :
|
|
[
|
|
{
|
|
"id": 1,
|
|
"nip": 1,
|
|
"nom": "MOREL",
|
|
"prenom": "JACQUES",
|
|
"civilite": "X",
|
|
},
|
|
{
|
|
"id": 2,
|
|
"nip": 2,
|
|
"nom": "GILLES",
|
|
"prenom": "MAXIME",
|
|
"civilite": "X",
|
|
},
|
|
...
|
|
]
|
|
"""
|
|
etuds = Identite.query.filter(
|
|
Identite.id == FormSemestreInscription.etudid,
|
|
FormSemestreInscription.formsemestre_id == FormSemestre.id,
|
|
FormSemestre.date_debut <= app.db.func.now(),
|
|
FormSemestre.date_fin >= app.db.func.now(),
|
|
)
|
|
if long:
|
|
data = [etud.to_dict_bul(include_urls=False) for etud in etuds]
|
|
else:
|
|
data = [etud.to_dict_short() for etud in etuds]
|
|
return jsonify(data)
|
|
|
|
|
|
@bp.route("/etudiant/etudid/<int:etudid>", methods=["GET"])
|
|
@bp.route("/etudiant/nip/<string:nip>", methods=["GET"])
|
|
@bp.route("/etudiant/ine/<string:ine>", methods=["GET"])
|
|
@token_auth.login_required
|
|
@token_permission_required(Permission.APIView)
|
|
def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
|
"""
|
|
Retourne les informations de l'étudiant correspondant, ou 404 si non trouvé.
|
|
|
|
etudid : l'etudid de l'étudiant
|
|
nip : le code nip de l'étudiant
|
|
ine : le code ine de l'étudiant
|
|
|
|
Les codes INE et NIP sont uniques au sein d'un département.
|
|
Si plusieurs objets ont le même code, on ramène le plus récemment inscrit.
|
|
|
|
Exemple de résultat :
|
|
{
|
|
"civilite": "X",
|
|
"code_ine": "1",
|
|
"code_nip": "1",
|
|
"date_naissance": "",
|
|
"email": "SACHA.COSTA@example.com",
|
|
"emailperso": "",
|
|
"etudid": 1,
|
|
"nom": "COSTA",
|
|
"prenom": "SACHA",
|
|
"nomprenom": "Sacha COSTA",
|
|
"lieu_naissance": "",
|
|
"dept_naissance": "",
|
|
"nationalite": "",
|
|
"boursier": "",
|
|
"id": 1,
|
|
"codepostaldomicile": "",
|
|
"paysdomicile": "",
|
|
"telephonemobile": "",
|
|
"typeadresse": "domicile",
|
|
"domicile": "",
|
|
"villedomicile": "",
|
|
"telephone": "",
|
|
"fax": "",
|
|
"description": ""
|
|
}
|
|
"""
|
|
if etudid is not None:
|
|
etud = Identite.query.get(etudid)
|
|
else:
|
|
if nip is not None:
|
|
query = Identite.query.filter_by(code_nip=nip)
|
|
elif ine is not None:
|
|
query = Identite.query.filter_by(code_ine=ine)
|
|
else:
|
|
return error_response(
|
|
404,
|
|
message="parametre manquant",
|
|
)
|
|
if query.count() > 1: # cas rare d'un étudiant présent dans plusieurs depts
|
|
etuds = []
|
|
for e in query:
|
|
admission = e.admission.first()
|
|
etuds.append((((admission.annee or 0) if admission else 0), e))
|
|
etuds.sort()
|
|
etud = etuds[-1][1]
|
|
else:
|
|
etud = query.first()
|
|
|
|
if etud is None:
|
|
return error_response(
|
|
404,
|
|
message="étudiant inconnu",
|
|
)
|
|
|
|
return jsonify(etud.to_dict_bul(include_urls=False))
|
|
|
|
|
|
@bp.route("/etudiants/etudid/<int:etudid>", methods=["GET"])
|
|
@bp.route("/etudiants/nip/<string:nip>", methods=["GET"])
|
|
@bp.route("/etudiants/ine/<string:ine>", methods=["GET"])
|
|
@token_auth.login_required
|
|
@token_permission_required(Permission.APIView)
|
|
def etudiants(etudid: int = None, nip: str = None, ine: str = None):
|
|
"""
|
|
Info sur le ou les étudiants correspondant. Comme /etudiant mais renvoie
|
|
toujours une liste.
|
|
Si non trouvé, liste vide, pas d'erreur.
|
|
Dans 99% des cas, la liste contient un seul étudiant, mais si l'étudiant a
|
|
été inscrit dans plusieurs départements, on a plusieurs objets (1 par dept.).
|
|
"""
|
|
if etudid is not None:
|
|
query = Identite.query.filter_by(id=etudid)
|
|
elif nip is not None:
|
|
query = Identite.query.filter_by(code_nip=nip)
|
|
elif ine is not None:
|
|
query = Identite.query.filter_by(code_ine=ine)
|
|
else:
|
|
return error_response(
|
|
404,
|
|
message="parametre manquant",
|
|
)
|
|
|
|
return jsonify([etud.to_dict_bul(include_urls=False) for etud in query])
|
|
|
|
|
|
@bp.route("/etudiant/etudid/<int:etudid>/formsemestres")
|
|
@bp.route("/etudiant/nip/<string:nip>/formsemestres")
|
|
@bp.route("/etudiant/ine/<string:ine>/formsemestres")
|
|
@token_auth.login_required
|
|
@token_permission_required(Permission.APIView)
|
|
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
|
|
"""
|
|
Liste des semestres qu'un étudiant a suivi, triés par ordre chronologique.
|
|
Accès par etudid, nip ou ine
|
|
|
|
Exemple de résultat :
|
|
[
|
|
{
|
|
"date_fin": "31/08/2022",
|
|
"resp_can_edit": false,
|
|
"dept_id": 1,
|
|
"etat": true,
|
|
"resp_can_change_ens": true,
|
|
"id": 1,
|
|
"modalite": "FI",
|
|
"ens_can_edit_eval": false,
|
|
"formation_id": 1,
|
|
"gestion_compensation": false,
|
|
"elt_sem_apo": null,
|
|
"semestre_id": 1,
|
|
"bul_hide_xml": false,
|
|
"elt_annee_apo": null,
|
|
"titre": "Semestre test",
|
|
"block_moyennes": false,
|
|
"scodoc7_id": null,
|
|
"date_debut": "01/09/2021",
|
|
"gestion_semestrielle": false,
|
|
"bul_bgcolor": "white",
|
|
"formsemestre_id": 1,
|
|
"titre_num": "Semestre test semestre 1",
|
|
"date_debut_iso": "2021-09-01",
|
|
"date_fin_iso": "2022-08-31",
|
|
"responsables": []
|
|
},
|
|
...
|
|
]
|
|
"""
|
|
if etudid is not None:
|
|
query = FormSemestre.query.filter(
|
|
FormSemestreInscription.etudid == etudid,
|
|
FormSemestreInscription.formsemestre_id == FormSemestre.id,
|
|
)
|
|
elif nip is not None:
|
|
query = FormSemestre.query.filter(
|
|
Identite.code_nip == nip,
|
|
FormSemestreInscription.etudid == Identite.id,
|
|
FormSemestreInscription.formsemestre_id == FormSemestre.id,
|
|
)
|
|
elif ine is not None:
|
|
query = FormSemestre.query.filter(
|
|
Identite.code_ine == ine,
|
|
FormSemestreInscription.etudid == Identite.id,
|
|
FormSemestreInscription.formsemestre_id == FormSemestre.id,
|
|
)
|
|
else:
|
|
return error_response(
|
|
404,
|
|
message="parametre manquant",
|
|
)
|
|
|
|
formsemestres = query.order_by(FormSemestre.date_debut)
|
|
|
|
return jsonify([formsemestre.to_dict() for formsemestre in formsemestres])
|
|
|
|
|
|
@bp.route(
|
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
|
|
methods=["GET"],
|
|
defaults={"version": "long"},
|
|
)
|
|
@bp.route(
|
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
|
|
methods=["GET"],
|
|
defaults={"version": "long"},
|
|
)
|
|
@bp.route(
|
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
|
|
methods=["GET"],
|
|
defaults={"version": "long"},
|
|
)
|
|
@bp.route(
|
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
|
methods=["GET"],
|
|
defaults={"version": "short"},
|
|
)
|
|
@bp.route(
|
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
|
methods=["GET"],
|
|
defaults={"version": "short"},
|
|
)
|
|
@bp.route(
|
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
|
methods=["GET"],
|
|
defaults={"version": "short"},
|
|
)
|
|
@token_auth.login_required
|
|
@token_permission_required(Permission.APIView)
|
|
def etudiant_bulletin_semestre(
|
|
formsemestre_id,
|
|
etudid: int = None,
|
|
nip: str = None,
|
|
ine: str = None,
|
|
version="long",
|
|
):
|
|
"""
|
|
Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné
|
|
|
|
formsemestre_id : l'id d'un formsemestre
|
|
etudid : l'etudid d'un étudiant
|
|
nip : le code nip d'un étudiant
|
|
ine : le code ine d'un étudiant
|
|
Exemple de résultat :
|
|
{
|
|
"version": "0",
|
|
"type": "BUT",
|
|
"date": "2022-04-27T07:18:16.450634Z",
|
|
"publie": true,
|
|
"etudiant": {
|
|
"civilite": "X",
|
|
"code_ine": "1",
|
|
"code_nip": "1",
|
|
"date_naissance": "",
|
|
"email": "SACHA.COSTA@example.com",
|
|
"emailperso": "",
|
|
"etudid": 1,
|
|
"nom": "COSTA",
|
|
"prenom": "SACHA",
|
|
"nomprenom": "Sacha COSTA",
|
|
"lieu_naissance": "",
|
|
"dept_naissance": "",
|
|
"nationalite": "",
|
|
"boursier": "",
|
|
"fiche_url": "/ScoDoc/TAPI/Scolarite/ficheEtud?etudid=1",
|
|
"photo_url": "/ScoDoc/TAPI/Scolarite/get_photo_image?etudid=1&size=small",
|
|
"id": 1,
|
|
"codepostaldomicile": "",
|
|
"paysdomicile": "",
|
|
"telephonemobile": "",
|
|
"typeadresse": "domicile",
|
|
"domicile": "",
|
|
"villedomicile": "",
|
|
"telephone": "",
|
|
"fax": "",
|
|
"description": "",
|
|
},
|
|
"formation": {
|
|
"id": 1,
|
|
"acronyme": "BUT R&T",
|
|
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
|
|
"titre": "BUT R&T",
|
|
},
|
|
"formsemestre_id": 1,
|
|
"etat_inscription": "I",
|
|
"options": {
|
|
"show_abs": true,
|
|
"show_abs_modules": false,
|
|
"show_ects": true,
|
|
"show_codemodules": false,
|
|
"show_matieres": false,
|
|
"show_rangs": true,
|
|
"show_ue_rangs": true,
|
|
"show_mod_rangs": true,
|
|
"show_moypromo": false,
|
|
"show_minmax": false,
|
|
"show_minmax_mod": false,
|
|
"show_minmax_eval": false,
|
|
"show_coef": true,
|
|
"show_ue_cap_details": false,
|
|
"show_ue_cap_current": true,
|
|
"show_temporary": true,
|
|
"temporary_txt": "Provisoire",
|
|
"show_uevalid": true,
|
|
"show_date_inscr": true,
|
|
},
|
|
"ressources": {
|
|
"R101": {
|
|
"id": 1,
|
|
"titre": "Initiation aux r\u00e9seaux informatiques",
|
|
"code_apogee": null,
|
|
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=1",
|
|
"moyenne": {},
|
|
"evaluations": [
|
|
{
|
|
"id": 1,
|
|
"description": "eval1",
|
|
"date": "2022-04-20",
|
|
"heure_debut": "08:00",
|
|
"heure_fin": "09:00",
|
|
"coef": "01.00",
|
|
"poids": {
|
|
"RT1.1": 1.0,
|
|
},
|
|
"note": {
|
|
"value": "12.00",
|
|
"min": "00.00",
|
|
"max": "18.00",
|
|
"moy": "10.88",
|
|
},
|
|
"url": "/ScoDoc/TAPI/Scolarite/Notes/evaluation_listenotes?evaluation_id=1",
|
|
}
|
|
],
|
|
},
|
|
},
|
|
"saes": {
|
|
"SAE11": {
|
|
"id": 2,
|
|
"titre": "Se sensibiliser \u00e0 l'hygi\u00e8ne informatique et \u00e0 la cybers\u00e9curit\u00e9",
|
|
"code_apogee": null,
|
|
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=2",
|
|
"moyenne": {},
|
|
"evaluations": [],
|
|
},
|
|
},
|
|
"ues": {
|
|
"RT1.1": {
|
|
"id": 1,
|
|
"titre": "Administrer les r\u00e9seaux et l\u2019Internet",
|
|
"numero": 1,
|
|
"type": 0,
|
|
"color": "#B80004",
|
|
"competence": null,
|
|
"moyenne": {
|
|
"value": "08.50",
|
|
"min": "06.00",
|
|
"max": "16.50",
|
|
"moy": "11.31",
|
|
"rang": "12",
|
|
"total": 16,
|
|
},
|
|
"bonus": "00.00",
|
|
"malus": "00.00",
|
|
"capitalise": null,
|
|
"ressources": {
|
|
"R101": {"id": 1, "coef": 12.0, "moyenne": "12.00"},
|
|
},
|
|
"saes": {
|
|
"SAE11": {"id": 2, "coef": 16.0, "moyenne": "~"},
|
|
},
|
|
"ECTS": {"acquis": 0.0, "total": 12.0},
|
|
},
|
|
"semestre": {
|
|
"etapes": [],
|
|
"date_debut": "2021-09-01",
|
|
"date_fin": "2022-08-31",
|
|
"annee_universitaire": "2021 - 2022",
|
|
"numero": 1,
|
|
"inscription": "",
|
|
"groupes": [],
|
|
"absences": {"injustifie": 1, "total": 2},
|
|
"ECTS": {"acquis": 0, "total": 30.0},
|
|
"notes": {"value": "10.60", "min": "02.40", "moy": "11.05", "max": "17.40"},
|
|
"rang": {"value": "10", "total": 16},
|
|
},
|
|
},
|
|
}
|
|
"""
|
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
|
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
|
|
|
if etudid is not None:
|
|
query = Identite.query.filter_by(id=etudid)
|
|
elif nip is not None:
|
|
query = Identite.query.filter_by(code_nip=nip, dept_id=dept.id)
|
|
elif ine is not None:
|
|
query = Identite.query.filter_by(code_ine=ine, dept_id=dept.id)
|
|
else:
|
|
return error_response(
|
|
404,
|
|
message="parametre manquant",
|
|
)
|
|
|
|
etud = query.first()
|
|
if etud is None:
|
|
return error_response(
|
|
404,
|
|
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
|
)
|
|
|
|
app.set_sco_dept(dept.acronym)
|
|
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
|
formsemestre, etud, version
|
|
)
|
|
|
|
|
|
@bp.route(
|
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups",
|
|
methods=["GET"],
|
|
)
|
|
@bp.route(
|
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/groups",
|
|
methods=["GET"],
|
|
)
|
|
@bp.route(
|
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/groups",
|
|
methods=["GET"],
|
|
)
|
|
@token_auth.login_required
|
|
@token_permission_required(Permission.APIView)
|
|
def etudiant_groups(
|
|
formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None
|
|
):
|
|
"""
|
|
Retourne la liste des groupes auxquels appartient l'étudiant dans le formsemestre indiqué
|
|
|
|
formsemestre_id : l'id d'un formsemestre
|
|
etudid : l'etudid d'un étudiant
|
|
nip : le code nip d'un étudiant
|
|
ine : le code ine d'un étudiant
|
|
|
|
Exemple de résultat :
|
|
[
|
|
{
|
|
"partition_id": 1,
|
|
"id": 1,
|
|
"formsemestre_id": 1,
|
|
"partition_name": null,
|
|
"numero": 0,
|
|
"bul_show_rank": false,
|
|
"show_in_lists": true,
|
|
"group_id": 1,
|
|
"group_name": null
|
|
},
|
|
{
|
|
"partition_id": 2,
|
|
"id": 2,
|
|
"formsemestre_id": 1,
|
|
"partition_name": "TD",
|
|
"numero": 1,
|
|
"bul_show_rank": false,
|
|
"show_in_lists": true,
|
|
"group_id": 2,
|
|
"group_name": "A"
|
|
}
|
|
]
|
|
"""
|
|
|
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
|
|
if formsemestre is None:
|
|
return error_response(
|
|
404,
|
|
message="formsemestre inconnu",
|
|
)
|
|
dept = Departement.query.get(formsemestre.dept_id)
|
|
if etudid is not None:
|
|
query = Identite.query.filter_by(id=etudid)
|
|
elif nip is not None:
|
|
query = Identite.query.filter_by(code_nip=nip, dept_id=dept.id)
|
|
elif ine is not None:
|
|
query = Identite.query.filter_by(code_ine=ine, dept_id=dept.id)
|
|
else:
|
|
return error_response(
|
|
404,
|
|
message="parametre manquant",
|
|
)
|
|
etud = query.first()
|
|
if etud is None:
|
|
return error_response(
|
|
404,
|
|
message="etudiant inconnu",
|
|
)
|
|
app.set_sco_dept(dept.acronym)
|
|
data = sco_groups.get_etud_groups(etud.id, formsemestre.id)
|
|
|
|
return jsonify(data)
|