Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into rangs_buls
This commit is contained in:
commit
ea6bf1f0f0
@ -5,26 +5,21 @@ from flask import jsonify
|
|||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.api.tools import get_etud_from_etudid_or_nip_or_ine
|
from app.models import Identite
|
||||||
from app.scodoc import notesdb as ndb
|
|
||||||
|
|
||||||
|
from app.scodoc import notesdb as ndb
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_abs
|
||||||
from app.scodoc.sco_groups import get_group_members
|
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/absences/etudid/<int:etudid>", methods=["GET"])
|
@bp.route("/absences/etudid/<int:etudid>", methods=["GET"])
|
||||||
@bp.route("/absences/nip/<string:nip>", methods=["GET"])
|
|
||||||
@bp.route("/absences/ine/<string:ine>", methods=["GET"])
|
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def absences(etudid: int = None, nip: int = None, ine: int = None):
|
def absences(etudid: int = None):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des absences d'un étudiant donné
|
Retourne la liste des absences d'un étudiant donné
|
||||||
|
|
||||||
etudid : l'etudid d'un étudiant
|
etudid : l'etudid d'un étudiant
|
||||||
nip: le code nip d'un étudiant
|
|
||||||
ine : le code ine d'un étudiant
|
|
||||||
|
|
||||||
Exemple de résultat:
|
Exemple de résultat:
|
||||||
[
|
[
|
||||||
@ -48,30 +43,24 @@ def absences(etudid: int = None, nip: int = None, ine: int = None):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
if etudid is None:
|
etud = Identite.query.get(etudid)
|
||||||
# Récupération de l'étudiant
|
|
||||||
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
|
||||||
if etud is None:
|
if etud is None:
|
||||||
return error_response(
|
return error_response(
|
||||||
404,
|
404,
|
||||||
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
||||||
)
|
)
|
||||||
etudid = etud.etudid
|
# Absences de l'étudiant
|
||||||
|
|
||||||
# Récupération des absences de l'étudiant
|
|
||||||
ndb.open_db_connection()
|
ndb.open_db_connection()
|
||||||
absences = sco_abs.list_abs_date(etudid)
|
absences = sco_abs.list_abs_date(etud.id)
|
||||||
for absence in absences:
|
for absence in absences:
|
||||||
absence["jour"] = absence["jour"].isoformat()
|
absence["jour"] = absence["jour"].isoformat()
|
||||||
return jsonify(absences)
|
return jsonify(absences)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
||||||
@bp.route("/absences/nip/<int:nip>/just", methods=["GET"])
|
|
||||||
@bp.route("/absences/ine/<int:ine>/just", methods=["GET"])
|
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def absences_just(etudid: int = None, nip: int = None, ine: int = None):
|
def absences_just(etudid: int = None):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des absences justifiées d'un étudiant donné
|
Retourne la liste des absences justifiées d'un étudiant donné
|
||||||
|
|
||||||
@ -101,18 +90,16 @@ def absences_just(etudid: int = None, nip: int = None, ine: int = None):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
if etudid is None:
|
etud = Identite.query.get(etudid)
|
||||||
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
|
||||||
if etud is None:
|
if etud is None:
|
||||||
return error_response(
|
return error_response(
|
||||||
404,
|
404,
|
||||||
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
||||||
)
|
)
|
||||||
etudid = etud.etudid
|
|
||||||
|
|
||||||
# Récupération des absences justifiées de l'étudiant
|
# Absences justifiées de l'étudiant
|
||||||
abs_just = [
|
abs_just = [
|
||||||
absence for absence in sco_abs.list_abs_date(etudid) if absence["estjust"]
|
absence for absence in sco_abs.list_abs_date(etud.id) if absence["estjust"]
|
||||||
]
|
]
|
||||||
for absence in abs_just:
|
for absence in abs_just:
|
||||||
absence["jour"] = absence["jour"].isoformat()
|
absence["jour"] = absence["jour"].isoformat()
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
#################################################### Etudiants ########################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
API : accès aux étudiants
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import models
|
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.api.tools import get_etud_from_etudid_or_nip_or_ine
|
from app.models import Departement, FormSemestreInscription, FormSemestre, Identite
|
||||||
from app.models import FormSemestreInscription, FormSemestre, Identite
|
|
||||||
from app.scodoc import sco_bulletins
|
from app.scodoc import sco_bulletins
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
@ -59,13 +65,16 @@ def etudiants_courant(long=False):
|
|||||||
@bp.route("/etudiant/ine/<string:ine>", methods=["GET"])
|
@bp.route("/etudiant/ine/<string:ine>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def etudiant(etudid: int = None, nip: int = None, ine: int = None):
|
def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
||||||
"""
|
"""
|
||||||
Retourne les informations de l'étudiant correspondant à l'id passé en paramètres.
|
Retourne les informations de l'étudiant correspondant, ou 404 si non trouvé.
|
||||||
|
|
||||||
etudid : l'etudid d'un étudiant
|
etudid : l'etudid de l'étudiant
|
||||||
nip : le code nip d'un étudiant
|
nip : le code nip de l'étudiant
|
||||||
ine : le code ine d'un é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 :
|
Exemple de résultat :
|
||||||
{
|
{
|
||||||
@ -95,17 +104,63 @@ def etudiant(etudid: int = None, nip: int = None, ine: int = None):
|
|||||||
"description": ""
|
"description": ""
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# Récupération de l'étudiant
|
if etudid is not None:
|
||||||
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
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:
|
if etud is None:
|
||||||
return error_response(
|
return error_response(
|
||||||
404,
|
404,
|
||||||
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
message="étudiant inconnu",
|
||||||
)
|
)
|
||||||
# Mise en forme des données
|
|
||||||
data = etud.to_dict_bul(include_urls=False)
|
|
||||||
|
|
||||||
return jsonify(data)
|
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/etudid/<int:etudid>/formsemestres")
|
||||||
@ -115,11 +170,8 @@ def etudiant(etudid: int = None, nip: int = None, ine: int = None):
|
|||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
|
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des semestres qu'un étudiant a suivis, triés par ordre chronologique.
|
Liste des semestres qu'un étudiant a suivi, triés par ordre chronologique.
|
||||||
|
Accès par etudid, nip ou ine
|
||||||
etudid : l'etudid d'un étudiant
|
|
||||||
nip : le code nip d'un étudiant
|
|
||||||
ine : le code ine d'un étudiant
|
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
@ -153,18 +205,30 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
# Récupération de l'étudiant
|
if etudid is not None:
|
||||||
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
query = FormSemestre.query.filter(
|
||||||
if etud is None:
|
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(
|
return error_response(
|
||||||
404,
|
404,
|
||||||
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
message="parametre manquant",
|
||||||
)
|
)
|
||||||
|
|
||||||
formsemestres = models.FormSemestre.query.filter(
|
formsemestres = query.order_by(FormSemestre.date_debut)
|
||||||
models.FormSemestreInscription.etudid == etud.id,
|
|
||||||
models.FormSemestreInscription.formsemestre_id == models.FormSemestre.id,
|
|
||||||
).order_by(models.FormSemestre.date_debut)
|
|
||||||
|
|
||||||
return jsonify([formsemestre.to_dict() for formsemestre in formsemestres])
|
return jsonify([formsemestre.to_dict() for formsemestre in formsemestres])
|
||||||
|
|
||||||
@ -204,8 +268,8 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
|
|||||||
def etudiant_bulletin_semestre(
|
def etudiant_bulletin_semestre(
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
etudid: int = None,
|
etudid: int = None,
|
||||||
nip: int = None,
|
nip: str = None,
|
||||||
ine: int = None,
|
ine: str = None,
|
||||||
version="long",
|
version="long",
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
@ -247,13 +311,13 @@ def etudiant_bulletin_semestre(
|
|||||||
"villedomicile": "",
|
"villedomicile": "",
|
||||||
"telephone": "",
|
"telephone": "",
|
||||||
"fax": "",
|
"fax": "",
|
||||||
"description": ""
|
"description": "",
|
||||||
},
|
},
|
||||||
"formation": {
|
"formation": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"acronyme": "BUT R&T",
|
"acronyme": "BUT R&T",
|
||||||
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
|
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
|
||||||
"titre": "BUT R&T"
|
"titre": "BUT R&T",
|
||||||
},
|
},
|
||||||
"formsemestre_id": 1,
|
"formsemestre_id": 1,
|
||||||
"etat_inscription": "I",
|
"etat_inscription": "I",
|
||||||
@ -276,7 +340,7 @@ def etudiant_bulletin_semestre(
|
|||||||
"show_temporary": true,
|
"show_temporary": true,
|
||||||
"temporary_txt": "Provisoire",
|
"temporary_txt": "Provisoire",
|
||||||
"show_uevalid": true,
|
"show_uevalid": true,
|
||||||
"show_date_inscr": true
|
"show_date_inscr": true,
|
||||||
},
|
},
|
||||||
"ressources": {
|
"ressources": {
|
||||||
"R101": {
|
"R101": {
|
||||||
@ -300,11 +364,11 @@ def etudiant_bulletin_semestre(
|
|||||||
"value": "12.00",
|
"value": "12.00",
|
||||||
"min": "00.00",
|
"min": "00.00",
|
||||||
"max": "18.00",
|
"max": "18.00",
|
||||||
"moy": "10.88"
|
"moy": "10.88",
|
||||||
},
|
},
|
||||||
"url": "/ScoDoc/TAPI/Scolarite/Notes/evaluation_listenotes?evaluation_id=1"
|
"url": "/ScoDoc/TAPI/Scolarite/Notes/evaluation_listenotes?evaluation_id=1",
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"saes": {
|
"saes": {
|
||||||
@ -314,7 +378,7 @@ def etudiant_bulletin_semestre(
|
|||||||
"code_apogee": null,
|
"code_apogee": null,
|
||||||
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=2",
|
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=2",
|
||||||
"moyenne": {},
|
"moyenne": {},
|
||||||
"evaluations": []
|
"evaluations": [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"ues": {
|
"ues": {
|
||||||
@ -331,29 +395,18 @@ def etudiant_bulletin_semestre(
|
|||||||
"max": "16.50",
|
"max": "16.50",
|
||||||
"moy": "11.31",
|
"moy": "11.31",
|
||||||
"rang": "12",
|
"rang": "12",
|
||||||
"total": 16
|
"total": 16,
|
||||||
},
|
},
|
||||||
"bonus": "00.00",
|
"bonus": "00.00",
|
||||||
"malus": "00.00",
|
"malus": "00.00",
|
||||||
"capitalise": null,
|
"capitalise": null,
|
||||||
"ressources": {
|
"ressources": {
|
||||||
"R101": {
|
"R101": {"id": 1, "coef": 12.0, "moyenne": "12.00"},
|
||||||
"id": 1,
|
|
||||||
"coef": 12.0,
|
|
||||||
"moyenne": "12.00"
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"saes": {
|
"saes": {
|
||||||
"SAE11": {
|
"SAE11": {"id": 2, "coef": 16.0, "moyenne": "~"},
|
||||||
"id": 2,
|
|
||||||
"coef": 16.0,
|
|
||||||
"moyenne": "~"
|
|
||||||
},
|
},
|
||||||
},
|
"ECTS": {"acquis": 0.0, "total": 12.0},
|
||||||
"ECTS": {
|
|
||||||
"acquis": 0.0,
|
|
||||||
"total": 12.0
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"semestre": {
|
"semestre": {
|
||||||
"etapes": [],
|
"etapes": [],
|
||||||
@ -363,41 +416,37 @@ def etudiant_bulletin_semestre(
|
|||||||
"numero": 1,
|
"numero": 1,
|
||||||
"inscription": "",
|
"inscription": "",
|
||||||
"groupes": [],
|
"groupes": [],
|
||||||
"absences": {
|
"absences": {"injustifie": 1, "total": 2},
|
||||||
"injustifie": 1,
|
"ECTS": {"acquis": 0, "total": 30.0},
|
||||||
"total": 2
|
"notes": {"value": "10.60", "min": "02.40", "moy": "11.05", "max": "17.40"},
|
||||||
|
"rang": {"value": "10", "total": 16},
|
||||||
},
|
},
|
||||||
"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 = models.FormSemestre.query.filter_by(
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
||||||
id=formsemestre_id
|
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
||||||
).first_or_404()
|
|
||||||
|
|
||||||
dept = models.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",
|
||||||
|
)
|
||||||
|
|
||||||
app.set_sco_dept(dept.acronym)
|
etud = query.first()
|
||||||
|
|
||||||
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
|
||||||
if etud is None:
|
if etud is None:
|
||||||
return error_response(
|
return error_response(
|
||||||
404,
|
404,
|
||||||
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.set_sco_dept(dept.acronym)
|
||||||
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
||||||
formsemestre, etud, version
|
formsemestre, etud, version
|
||||||
)
|
)
|
||||||
@ -454,19 +503,32 @@ def etudiant_groups(
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
if etudid is None:
|
|
||||||
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
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:
|
if etud is None:
|
||||||
return error_response(
|
return error_response(
|
||||||
404,
|
404,
|
||||||
message="id de l'étudiant (etudid, nip, ine) inconnu",
|
message="etudiant inconnu",
|
||||||
)
|
)
|
||||||
etudid = etud.etudid
|
|
||||||
|
|
||||||
# Récupération du formsemestre
|
|
||||||
sem = models.FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
|
||||||
dept = models.Departement.query.get(sem.dept_id)
|
|
||||||
app.set_sco_dept(dept.acronym)
|
app.set_sco_dept(dept.acronym)
|
||||||
data = sco_groups.get_etud_groups(etudid, sem.id)
|
data = sco_groups.get_etud_groups(etud.id, formsemestre.id)
|
||||||
|
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
@ -348,7 +348,7 @@ class User(UserMixin, db.Model):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def get_nom_fmt(self):
|
def get_nom_fmt(self):
|
||||||
"""Nom formatté: "Martin" """
|
"""Nom formaté: "Martin" """
|
||||||
if self.nom:
|
if self.nom:
|
||||||
return sco_etud.format_nom(self.nom, uppercase=False)
|
return sco_etud.format_nom(self.nom, uppercase=False)
|
||||||
else:
|
else:
|
||||||
|
@ -481,6 +481,19 @@ class BonusBezier(BonusSportAdditif):
|
|||||||
proportion_point = 0.03
|
proportion_point = 0.03
|
||||||
|
|
||||||
|
|
||||||
|
class BonusBlagnac(BonusSportAdditif):
|
||||||
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT de Blagnac.
|
||||||
|
|
||||||
|
Le bonus est égal à 5% des points au dessus de 10 à appliquer sur toutes
|
||||||
|
les UE du semestre, applicable dans toutes les formations (DUT, BUT, ...).
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "bonus_iutblagnac"
|
||||||
|
displayed_name = "IUT de Blagnac"
|
||||||
|
proportion_point = 0.05
|
||||||
|
classic_use_bonus_ues = True # toujours sur les UE
|
||||||
|
|
||||||
|
|
||||||
class BonusBordeaux1(BonusSportMultiplicatif):
|
class BonusBordeaux1(BonusSportMultiplicatif):
|
||||||
"""Calcul bonus modules optionnels (sport, culture), règle IUT Bordeaux 1,
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Bordeaux 1,
|
||||||
sur moyenne générale et UEs.
|
sur moyenne générale et UEs.
|
||||||
|
@ -178,6 +178,7 @@ class Identite(db.Model):
|
|||||||
"date_naissance": self.date_naissance.strftime("%d/%m/%Y")
|
"date_naissance": self.date_naissance.strftime("%d/%m/%Y")
|
||||||
if self.date_naissance
|
if self.date_naissance
|
||||||
else "",
|
else "",
|
||||||
|
"dept_id": self.dept_id,
|
||||||
"email": self.get_first_email() or "",
|
"email": self.get_first_email() or "",
|
||||||
"emailperso": self.get_first_email("emailperso"),
|
"emailperso": self.get_first_email("emailperso"),
|
||||||
"etudid": self.id,
|
"etudid": self.id,
|
||||||
|
@ -97,7 +97,7 @@ class SetTag(pe_tagtable.TableTag):
|
|||||||
"""Mémorise les semtag nécessaires au jury."""
|
"""Mémorise les semtag nécessaires au jury."""
|
||||||
self.SemTagDict = {fid: SemTagDict[fid] for fid in self.get_Fids_in_settag()}
|
self.SemTagDict = {fid: SemTagDict[fid] for fid in self.get_Fids_in_settag()}
|
||||||
if PE_DEBUG >= 1:
|
if PE_DEBUG >= 1:
|
||||||
pe_print(u" => %d semestres fusionnés" % len(self.SemTagDict))
|
pe_print(" => %d semestres fusionnés" % len(self.SemTagDict))
|
||||||
|
|
||||||
# -------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------
|
||||||
def comp_data_settag(self):
|
def comp_data_settag(self):
|
||||||
@ -210,7 +210,7 @@ class SetTagInterClasse(pe_tagtable.TableTag):
|
|||||||
# -------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------
|
||||||
def __init__(self, nom_combinaison, diplome):
|
def __init__(self, nom_combinaison, diplome):
|
||||||
|
|
||||||
pe_tagtable.TableTag.__init__(self, nom=nom_combinaison + "_%d" % diplome)
|
pe_tagtable.TableTag.__init__(self, nom=f"{nom_combinaison}_{diplome or ''}")
|
||||||
self.combinaison = nom_combinaison
|
self.combinaison = nom_combinaison
|
||||||
self.parcoursDict = {}
|
self.parcoursDict = {}
|
||||||
|
|
||||||
@ -243,7 +243,7 @@ class SetTagInterClasse(pe_tagtable.TableTag):
|
|||||||
fid: SetTagDict[fid] for fid in self.get_Fids_in_settag() if fid != None
|
fid: SetTagDict[fid] for fid in self.get_Fids_in_settag() if fid != None
|
||||||
}
|
}
|
||||||
if PE_DEBUG >= 1:
|
if PE_DEBUG >= 1:
|
||||||
pe_print(u" => %d semestres utilisés" % len(self.SetTagDict))
|
pe_print(" => %d semestres utilisés" % len(self.SetTagDict))
|
||||||
|
|
||||||
# -------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------
|
||||||
def comp_data_settag(self):
|
def comp_data_settag(self):
|
||||||
|
@ -208,25 +208,29 @@ def _build_results_list(dpv_by_sem, etuds_infos):
|
|||||||
return rows, titles, columns_ids
|
return rows, titles, columns_ids
|
||||||
|
|
||||||
|
|
||||||
def get_set_formsemestre_id_dates(start_date, end_date):
|
def get_set_formsemestre_id_dates(start_date, end_date) -> set:
|
||||||
"""Ensemble des formsemestre_id entre ces dates"""
|
"""Ensemble des formsemestre_id entre ces dates"""
|
||||||
s = ndb.SimpleDictFetch(
|
s = ndb.SimpleDictFetch(
|
||||||
"""SELECT id
|
"""SELECT id
|
||||||
FROM notes_formsemestre
|
FROM notes_formsemestre
|
||||||
WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s
|
WHERE date_debut >= %(start_date)s
|
||||||
|
AND date_fin <= %(end_date)s
|
||||||
|
AND dept_id = %(dept_id)s
|
||||||
""",
|
""",
|
||||||
{"start_date": start_date, "end_date": end_date},
|
{"start_date": start_date, "end_date": end_date, "dept_id": g.scodoc_dept_id},
|
||||||
)
|
)
|
||||||
return {x["id"] for x in s}
|
return {x["id"] for x in s}
|
||||||
|
|
||||||
|
|
||||||
def scodoc_table_results(start_date="", end_date="", types_parcours=[], format="html"):
|
def scodoc_table_results(
|
||||||
|
start_date="", end_date="", types_parcours: list = None, format="html"
|
||||||
|
):
|
||||||
"""Page affichant la table des résultats
|
"""Page affichant la table des résultats
|
||||||
Les dates sont en dd/mm/yyyy (datepicker javascript)
|
Les dates sont en dd/mm/yyyy (datepicker javascript)
|
||||||
types_parcours est la liste des types de parcours à afficher
|
types_parcours est la liste des types de parcours à afficher
|
||||||
(liste de chaines, eg ['100', '210'] )
|
(liste de chaines, eg ['100', '210'] )
|
||||||
"""
|
"""
|
||||||
log("scodoc_table_results: start_date=%s" % (start_date,)) # XXX
|
log(f"scodoc_table_results: start_date={start_date!r}")
|
||||||
if not types_parcours:
|
if not types_parcours:
|
||||||
types_parcours = []
|
types_parcours = []
|
||||||
if not isinstance(types_parcours, list):
|
if not isinstance(types_parcours, list):
|
||||||
|
@ -256,6 +256,8 @@ def formation_import_xml(doc: str, import_tags=True):
|
|||||||
mod_info[1]["formation_id"] = formation_id
|
mod_info[1]["formation_id"] = formation_id
|
||||||
mod_info[1]["matiere_id"] = mat_id
|
mod_info[1]["matiere_id"] = mat_id
|
||||||
mod_info[1]["ue_id"] = ue_id
|
mod_info[1]["ue_id"] = ue_id
|
||||||
|
if not "module_type" in mod_info[1]:
|
||||||
|
mod_info[1]["module_type"] = scu.ModuleType.STANDARD
|
||||||
mod_id = sco_edit_module.do_module_create(mod_info[1])
|
mod_id = sco_edit_module.do_module_create(mod_info[1])
|
||||||
if xml_module_id:
|
if xml_module_id:
|
||||||
modules_old2new[int(xml_module_id)] = mod_id
|
modules_old2new[int(xml_module_id)] = mod_id
|
||||||
|
@ -262,7 +262,7 @@ def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _make_page(etud, sem, tf, message=""):
|
def _make_page(etud: dict, sem, tf, message="") -> list:
|
||||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
moy_gen = nt.get_etud_moy_gen(etud["etudid"])
|
moy_gen = nt.get_etud_moy_gen(etud["etudid"])
|
||||||
@ -277,21 +277,20 @@ def _make_page(etud, sem, tf, message=""):
|
|||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
% etud,
|
% etud,
|
||||||
"""<p>La moyenne de ce semestre serait:
|
f"""<p>La moyenne de ce semestre serait:
|
||||||
<span class="ext_sem_moy"><span class="ext_sem_moy_val">%s</span> / 20</span>
|
<span class="ext_sem_moy"><span class="ext_sem_moy_val">{moy_gen}</span> / 20</span>
|
||||||
</p>
|
</p>
|
||||||
"""
|
""",
|
||||||
% moy_gen,
|
|
||||||
'<div id="formsemestre_ext_edit_ue_validations">',
|
'<div id="formsemestre_ext_edit_ue_validations">',
|
||||||
tf[1],
|
tf[1],
|
||||||
"</div>",
|
"</div>",
|
||||||
"""<div>
|
f"""<div>
|
||||||
<a class="stdlink"
|
<a class="stdlink"
|
||||||
href="formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s">
|
href="{url_for("notes.formsemestre_bulletinetud", scodoc_dept=g.scodoc_dept,
|
||||||
retour au bulletin de notes
|
formsemestre_id=formsemestre.id, etudid=etud['etudid']
|
||||||
</a></div>
|
)}">retour au bulletin de notes</a>
|
||||||
"""
|
</div>
|
||||||
% (sem["formsemestre_id"], etud["etudid"]),
|
""",
|
||||||
html_sco_header.sco_footer(),
|
html_sco_header.sco_footer(),
|
||||||
]
|
]
|
||||||
return H
|
return H
|
||||||
|
@ -133,7 +133,7 @@ def formsemestre_recapcomplet(
|
|||||||
for (format, label) in (
|
for (format, label) in (
|
||||||
("html", "Tableau"),
|
("html", "Tableau"),
|
||||||
("evals", "Avec toutes les évaluations"),
|
("evals", "Avec toutes les évaluations"),
|
||||||
("xlsx", "Excel (non formatté)"),
|
("xlsx", "Excel (non formaté)"),
|
||||||
("xlsall", "Excel avec évaluations"),
|
("xlsall", "Excel avec évaluations"),
|
||||||
("xml", "Bulletins XML (obsolète)"),
|
("xml", "Bulletins XML (obsolète)"),
|
||||||
("json", "Bulletins JSON"),
|
("json", "Bulletins JSON"),
|
||||||
|
@ -648,17 +648,6 @@ def formation_export(formation_id, export_ids=False, format=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formation_import_xml")
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoChangeFormation)
|
|
||||||
@scodoc7func
|
|
||||||
def formation_import_xml(file):
|
|
||||||
"import d'une formation en XML"
|
|
||||||
log("formation_import_xml")
|
|
||||||
doc = file.read()
|
|
||||||
return sco_formations.formation_import_xml(doc)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formation_import_xml_form", methods=["GET", "POST"])
|
@bp.route("/formation_import_xml_form", methods=["GET", "POST"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoChangeFormation)
|
@permission_required(Permission.ScoChangeFormation)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.2.19"
|
SCOVERSION = "9.2.20"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
@ -26,13 +26,17 @@ import urllib3
|
|||||||
from pprint import pprint as pp
|
from pprint import pprint as pp
|
||||||
|
|
||||||
# --- Lecture configuration (variables d'env ou .env)
|
# --- Lecture configuration (variables d'env ou .env)
|
||||||
|
try:
|
||||||
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
except NameError:
|
||||||
|
BASEDIR = "."
|
||||||
|
|
||||||
load_dotenv(os.path.join(BASEDIR, ".env"))
|
load_dotenv(os.path.join(BASEDIR, ".env"))
|
||||||
CHK_CERT = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
|
CHK_CERT = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
|
||||||
SCODOC_URL = os.environ["SCODOC_URL"]
|
SCODOC_URL = os.environ["SCODOC_URL"]
|
||||||
API_URL = SCODOC_URL + "/ScoDoc/api"
|
API_URL = SCODOC_URL + "/ScoDoc/api"
|
||||||
SCODOC_USER = os.environ["SCODOC_USER"]
|
SCODOC_USER = os.environ["SCODOC_USER"]
|
||||||
SCODOC_PASSWORD = os.environ["SCODOC_PASSWD"]
|
SCODOC_PASSWORD = os.environ["SCODOC_PASSWORD"]
|
||||||
print(f"SCODOC_URL={SCODOC_URL}")
|
print(f"SCODOC_URL={SCODOC_URL}")
|
||||||
print(f"API URL={API_URL}")
|
print(f"API URL={API_URL}")
|
||||||
|
|
||||||
@ -90,6 +94,23 @@ formsemestre_id = 1028 # A adapter
|
|||||||
etudid = 14721
|
etudid = 14721
|
||||||
bul_dut = GET(f"/etudiant/etudid/{etudid}/formsemestre/{formsemestre_id}/bulletin")
|
bul_dut = GET(f"/etudiant/etudid/{etudid}/formsemestre/{formsemestre_id}/bulletin")
|
||||||
|
|
||||||
|
|
||||||
|
# Infos sur un étudiant
|
||||||
|
etudid = 3561
|
||||||
|
code_nip = "11303314"
|
||||||
|
etud = GET(f"/etudiant/etudid/{etudid}")
|
||||||
|
print(etud)
|
||||||
|
|
||||||
|
etud = GET(f"/etudiant/nip/{code_nip}")
|
||||||
|
print(etud)
|
||||||
|
|
||||||
|
sems = GET(f"/etudiant/etudid/{etudid}/formsemestres")
|
||||||
|
print("\n".join([s["titre_num"] for s in sems]))
|
||||||
|
|
||||||
|
sems = GET(f"/etudiant/nip/{code_nip}/formsemestres")
|
||||||
|
print("\n".join([s["titre_num"] for s in sems]))
|
||||||
|
|
||||||
|
|
||||||
# # --- Recupere la liste de tous les semestres:
|
# # --- Recupere la liste de tous les semestres:
|
||||||
# sems = GET(s, "Notes/formsemestre_list?format=json", "Aucun semestre !")
|
# sems = GET(s, "Notes/formsemestre_list?format=json", "Aucun semestre !")
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@ from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
|||||||
|
|
||||||
# Etudiant pour les tests
|
# Etudiant pour les tests
|
||||||
ETUDID = 1
|
ETUDID = 1
|
||||||
INE = "1"
|
|
||||||
NIP = "1"
|
|
||||||
|
|
||||||
# absences
|
# absences
|
||||||
def test_absences(api_headers):
|
def test_absences(api_headers):
|
||||||
@ -37,20 +36,6 @@ def test_absences(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
r = requests.get(
|
|
||||||
f"{API_URL}/absences/nip/{NIP}",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
|
|
||||||
r = requests.get(
|
|
||||||
f"{API_URL}/absences/ine/{INE}",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
# absences_justify
|
# absences_justify
|
||||||
def test_absences_justify(api_headers):
|
def test_absences_justify(api_headers):
|
||||||
@ -65,22 +50,6 @@ def test_absences_justify(api_headers):
|
|||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
# TODO vérifier résultat
|
# TODO vérifier résultat
|
||||||
|
|
||||||
r = requests.get(
|
|
||||||
API_URL + f"/absences/nip/{NIP}/just",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
# TODO vérifier résultat
|
|
||||||
|
|
||||||
r = requests.get(
|
|
||||||
API_URL + f"/absences/ine/{INE}/just",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
# TODO vérifier résultat
|
|
||||||
|
|
||||||
|
|
||||||
# XXX TODO
|
# XXX TODO
|
||||||
# def test_abs_groupe_etat(api_headers):
|
# def test_abs_groupe_etat(api_headers):
|
||||||
|
@ -93,7 +93,7 @@ def test_etudiant(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud = r.json()
|
etud = r.json()
|
||||||
assert len(etud) == 24
|
assert len(etud) == 25
|
||||||
fields_ok = verify_fields(etud, ETUD_FIELDS)
|
fields_ok = verify_fields(etud, ETUD_FIELDS)
|
||||||
assert fields_ok is True
|
assert fields_ok is True
|
||||||
|
|
||||||
|
@ -24,6 +24,11 @@ from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
|||||||
from tests.api.tools_test_api import MODIMPL_FIELDS, verify_fields
|
from tests.api.tools_test_api import MODIMPL_FIELDS, verify_fields
|
||||||
from tests.api.tools_test_api import FSEM_FIELDS, UE_FIELDS, MODULE_FIELDS
|
from tests.api.tools_test_api import FSEM_FIELDS, UE_FIELDS, MODULE_FIELDS
|
||||||
|
|
||||||
|
# Etudiant pour les tests
|
||||||
|
ETUDID = 1
|
||||||
|
NIP = "1"
|
||||||
|
INE = "INE1"
|
||||||
|
|
||||||
|
|
||||||
def test_formsemestre(api_headers):
|
def test_formsemestre(api_headers):
|
||||||
"""
|
"""
|
||||||
@ -53,7 +58,7 @@ def test_etudiant_bulletin(api_headers):
|
|||||||
bull_a = r.json()
|
bull_a = r.json()
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/etudiant/nip/1/formsemestre/{formsemestre_id}/bulletin",
|
f"{API_URL}/etudiant/nip/{NIP}/formsemestre/{formsemestre_id}/bulletin",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -61,7 +66,7 @@ def test_etudiant_bulletin(api_headers):
|
|||||||
bull_b = r.json()
|
bull_b = r.json()
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/etudiant/ine/1/formsemestre/{formsemestre_id}/bulletin",
|
f"{API_URL}/etudiant/ine/{INE}/formsemestre/{formsemestre_id}/bulletin",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user