forked from ScoDoc/ScoDoc
Merge branch 'new_api_leonard' of https://scodoc.org/git/viennet/ScoDoc
This commit is contained in:
commit
adc086f83c
@ -1,20 +1,27 @@
|
|||||||
#################################################### Absences #########################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
"""ScoDoc 9 API : Absences
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
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 permission_required_api
|
||||||
from app.models import Identite
|
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"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def absences(etudid: 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é
|
||||||
@ -51,15 +58,14 @@ def absences(etudid: int = None):
|
|||||||
)
|
)
|
||||||
# Absences de l'étudiant
|
# Absences de l'étudiant
|
||||||
ndb.open_db_connection()
|
ndb.open_db_connection()
|
||||||
absences = sco_abs.list_abs_date(etud.id)
|
abs_list = sco_abs.list_abs_date(etud.id)
|
||||||
for absence in absences:
|
for absence in abs_list:
|
||||||
absence["jour"] = absence["jour"].isoformat()
|
absence["jour"] = absence["jour"].isoformat()
|
||||||
return jsonify(absences)
|
return jsonify(abs_list)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def absences_just(etudid: 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é
|
||||||
@ -106,40 +112,152 @@ def absences_just(etudid: int = None):
|
|||||||
return jsonify(abs_just)
|
return jsonify(abs_just)
|
||||||
|
|
||||||
|
|
||||||
# XXX TODO INACHEVEE
|
@bp.route(
|
||||||
|
"/absences/abs_group_etat/<int:group_id>",
|
||||||
|
methods=["GET"],
|
||||||
|
)
|
||||||
|
@bp.route(
|
||||||
|
"/absences/abs_group_etat/group_id/<int:group_id>/date_debut/<string:date_debut>/date_fin/<string:date_fin>",
|
||||||
|
methods=["GET"],
|
||||||
|
)
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def abs_groupe_etat(group_id: int, date_debut=None, date_fin=None):
|
||||||
|
"""
|
||||||
|
Liste des absences d'un groupe (possibilité de choisir entre deux dates)
|
||||||
|
|
||||||
|
group_id = l'id du groupe
|
||||||
|
date_debut = None par défaut, sinon la date ISO du début de notre filtre
|
||||||
|
date_fin = None par défaut, sinon la date ISO de la fin de notre filtre
|
||||||
|
|
||||||
|
Exemple de résultat :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"etudid": 1,
|
||||||
|
"list_abs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etudid": 2,
|
||||||
|
"list_abs": [
|
||||||
|
{
|
||||||
|
"jour": "Fri, 15 Apr 2022 00:00:00 GMT",
|
||||||
|
"matin": true,
|
||||||
|
"estabs": true,
|
||||||
|
"estjust": true,
|
||||||
|
"description": "",
|
||||||
|
"begin": "2022-04-15 08:00:00",
|
||||||
|
"end": "2022-04-15 11:59:59"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jour": "Fri, 15 Apr 2022 00:00:00 GMT",
|
||||||
|
"matin": false,
|
||||||
|
"estabs": true,
|
||||||
|
"estjust": false,
|
||||||
|
"description": "",
|
||||||
|
"begin": "2022-04-15 12:00:00",
|
||||||
|
"end": "2022-04-15 17:59:59"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
members = get_group_members(group_id)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
# Filtre entre les deux dates renseignées
|
||||||
|
for member in members:
|
||||||
|
absence = {
|
||||||
|
"etudid": member["etudid"],
|
||||||
|
"list_abs": sco_abs.list_abs_date(member["etudid"], date_debut, date_fin),
|
||||||
|
}
|
||||||
|
data.append(absence)
|
||||||
|
|
||||||
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
|
# XXX TODO EV: A REVOIR (data json dans le POST + modifier les routes)
|
||||||
# @bp.route(
|
# @bp.route(
|
||||||
# "/absences/abs_group_etat/<int:group_id>",
|
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs",
|
||||||
# methods=["GET"],
|
# methods=["POST"],
|
||||||
|
# defaults={"just_or_not": 0},
|
||||||
# )
|
# )
|
||||||
# @bp.route(
|
# @bp.route(
|
||||||
# "/absences/abs_group_etat/group_id/<int:group_id>/date_debut/<string:date_debut>/date_fin/<string:date_fin>",
|
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_not_just",
|
||||||
# methods=["GET"],
|
# methods=["POST"],
|
||||||
|
# defaults={"just_or_not": 1},
|
||||||
|
# )
|
||||||
|
# @bp.route(
|
||||||
|
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_just",
|
||||||
|
# methods=["POST"],
|
||||||
|
# defaults={"just_or_not": 2},
|
||||||
# )
|
# )
|
||||||
# @token_auth.login_required
|
# @token_auth.login_required
|
||||||
# @token_permission_required(Permission.APIView)
|
# @token_permission_required(Permission.APIAbsChange)
|
||||||
# def abs_groupe_etat( # XXX A REVOIR XXX
|
# def reset_etud_abs(etudid: int, list_abs: str, just_or_not: int = 0):
|
||||||
# group_id: int, date_debut, date_fin, with_boursier=True, format="html"
|
|
||||||
# ):
|
|
||||||
# """
|
# """
|
||||||
# Liste des absences d'un ou plusieurs groupes entre deux dates
|
# Set la liste des absences d'un étudiant sur tout un semestre.
|
||||||
|
# (les absences existant pour cet étudiant sur cette période sont effacées)
|
||||||
|
|
||||||
|
# etudid : l'id d'un étudiant
|
||||||
|
# list_abs : json d'absences
|
||||||
|
# just_or_not : 0 (pour les absences justifiées et non justifiées),
|
||||||
|
# 1 (pour les absences justifiées),
|
||||||
|
# 2 (pour les absences non justifiées)
|
||||||
# """
|
# """
|
||||||
# return error_response(501, message="Not implemented")
|
# # Toutes les absences
|
||||||
|
# if just_or_not == 0:
|
||||||
|
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
||||||
|
# for abs in list_abs:
|
||||||
|
# # Récupération de la date au format iso
|
||||||
|
# jour = abs["jour"].isoformat()
|
||||||
|
# if abs["matin"] is True:
|
||||||
|
# annule_absence(etudid, jour, True)
|
||||||
|
# annule_justif(etudid, jour, True)
|
||||||
|
# else:
|
||||||
|
# annule_absence(etudid, jour, False)
|
||||||
|
# annule_justif(etudid, jour, False)
|
||||||
|
|
||||||
# # Fonction utilisée : app.scodoc.sco_groups.get_group_members() et app.scodoc.sco_abs.list_abs_date()
|
# # Ajout de la liste d'absences en base
|
||||||
|
# add_abslist(list_abs)
|
||||||
|
|
||||||
# try:
|
# # Uniquement les absences justifiées
|
||||||
# # Utilisation de la fonction get_group_members
|
# elif just_or_not == 1:
|
||||||
# members = get_group_members(group_id)
|
# list_abs_not_just = []
|
||||||
# except ValueError:
|
# # Trie des absences justifiées
|
||||||
# return error_response(
|
# for abs in list_abs:
|
||||||
# 404, message="La requête ne peut être traitée en l’état actuel"
|
# if abs["estjust"] is False:
|
||||||
# )
|
# list_abs_not_just.append(abs)
|
||||||
|
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
||||||
|
# for abs in list_abs:
|
||||||
|
# # Récupération de la date au format iso
|
||||||
|
# jour = abs["jour"].isoformat()
|
||||||
|
# if abs["matin"] is True:
|
||||||
|
# annule_absence(etudid, jour, True)
|
||||||
|
# annule_justif(etudid, jour, True)
|
||||||
|
# else:
|
||||||
|
# annule_absence(etudid, jour, False)
|
||||||
|
# annule_justif(etudid, jour, False)
|
||||||
|
|
||||||
# data = []
|
# # Ajout de la liste d'absences en base
|
||||||
# # Filtre entre les deux dates renseignées
|
# add_abslist(list_abs_not_just)
|
||||||
# for member in members:
|
|
||||||
# abs = sco_abs.list_abs_date(member.id, date_debut, date_fin)
|
|
||||||
# data.append(abs)
|
|
||||||
|
|
||||||
# # return jsonify(data) # XXX TODO faire en sorte de pouvoir renvoyer sa (ex to_dict() dans absences)
|
# # Uniquement les absences non justifiées
|
||||||
# return error_response(501, message="Not implemented")
|
# elif just_or_not == 2:
|
||||||
|
# list_abs_just = []
|
||||||
|
# # Trie des absences non justifiées
|
||||||
|
# for abs in list_abs:
|
||||||
|
# if abs["estjust"] is True:
|
||||||
|
# list_abs_just.append(abs)
|
||||||
|
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
||||||
|
# for abs in list_abs:
|
||||||
|
# # Récupération de la date au format iso
|
||||||
|
# jour = abs["jour"].isoformat()
|
||||||
|
# if abs["matin"] is True:
|
||||||
|
# annule_absence(etudid, jour, True)
|
||||||
|
# annule_justif(etudid, jour, True)
|
||||||
|
# else:
|
||||||
|
# annule_absence(etudid, jour, False)
|
||||||
|
# annule_justif(etudid, jour, False)
|
||||||
|
|
||||||
|
# # Ajout de la liste d'absences en base
|
||||||
|
# add_abslist(list_abs_just)
|
||||||
|
@ -26,10 +26,9 @@
|
|||||||
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
from flask import abort
|
|
||||||
from flask import g
|
from flask import g
|
||||||
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
|
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
|
||||||
|
from flask_login import current_user
|
||||||
|
|
||||||
from app import log
|
from app import log
|
||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
@ -57,7 +56,10 @@ def basic_auth_error(status):
|
|||||||
|
|
||||||
@token_auth.verify_token
|
@token_auth.verify_token
|
||||||
def verify_token(token) -> User:
|
def verify_token(token) -> User:
|
||||||
"Retrouve l'utilisateur à partir du jeton"
|
"""Retrouve l'utilisateur à partir du jeton.
|
||||||
|
Si la requête n'a pas de jeton, token == "".
|
||||||
|
"""
|
||||||
|
|
||||||
user = User.check_token(token) if token else None
|
user = User.check_token(token) if token else None
|
||||||
g.current_user = user
|
g.current_user = user
|
||||||
return user
|
return user
|
||||||
@ -65,7 +67,7 @@ def verify_token(token) -> User:
|
|||||||
|
|
||||||
@token_auth.error_handler
|
@token_auth.error_handler
|
||||||
def token_auth_error(status):
|
def token_auth_error(status):
|
||||||
"rréponse en cas d'erreur d'auth."
|
"Réponse en cas d'erreur d'auth."
|
||||||
return error_response(status)
|
return error_response(status)
|
||||||
|
|
||||||
|
|
||||||
@ -75,7 +77,7 @@ def get_user_roles(user):
|
|||||||
|
|
||||||
|
|
||||||
def token_permission_required(permission):
|
def token_permission_required(permission):
|
||||||
"Décorateur pour les fontions de l'API ScoDoc"
|
"Décorateur pour les fonctions de l'API ScoDoc"
|
||||||
|
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
@ -84,13 +86,39 @@ def token_permission_required(permission):
|
|||||||
current_user = basic_auth.current_user()
|
current_user = basic_auth.current_user()
|
||||||
if not current_user or not current_user.has_permission(permission, None):
|
if not current_user or not current_user.has_permission(permission, None):
|
||||||
if current_user:
|
if current_user:
|
||||||
log(f"API permission denied (user {current_user})")
|
message = f"API permission denied (user {current_user})"
|
||||||
else:
|
else:
|
||||||
log("API permission denied (no user supplied)")
|
message = f"API permission denied (no user supplied)"
|
||||||
abort(403)
|
log(message)
|
||||||
|
# raise werkzeug.exceptions.Forbidden(description=message)
|
||||||
|
return error_response(403, message=None)
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
# return decorated_function(token_auth.login_required())
|
# return decorated_function(token_auth.login_required())
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def permission_required_api(permission_web, permission_api):
|
||||||
|
"""Décorateur pour les fonctions de l'API accessibles en mode jeton
|
||||||
|
ou en mode web.
|
||||||
|
Si cookie d'authentification web, utilise pour se logger et calculer les
|
||||||
|
permissions.
|
||||||
|
Sinon, tente le jeton jwt.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(f):
|
||||||
|
@wraps(f)
|
||||||
|
def decorated_function(*args, **kwargs):
|
||||||
|
scodoc_dept = getattr(g, "scodoc_dept", None)
|
||||||
|
if not current_user.has_permission(permission_web, scodoc_dept):
|
||||||
|
# try API
|
||||||
|
return token_auth.login_required(
|
||||||
|
token_permission_required(permission_api)(f)
|
||||||
|
)(*args, **kwargs)
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
|
return decorated_function
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
@ -5,7 +5,7 @@ from flask import jsonify
|
|||||||
import app
|
import app
|
||||||
from app import models
|
from app import models
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import permission_required_api
|
||||||
from app.models import Departement, FormSemestre
|
from app.models import Departement, FormSemestre
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
@ -21,20 +21,25 @@ def get_departement(dept_ident: str) -> Departement:
|
|||||||
return Departement.query.get_or_404(dept_id)
|
return Departement.query.get_or_404(dept_id)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/departements", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def departements():
|
||||||
|
"""Liste les départements"""
|
||||||
|
return jsonify([dept.to_dict() for dept in Departement.query])
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/departements_ids", methods=["GET"])
|
@bp.route("/departements_ids", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def departements_ids():
|
def departements_ids():
|
||||||
"""Liste des ids de départements"""
|
"""Liste des ids de départements"""
|
||||||
return jsonify([dept.id for dept in Departement.query])
|
return jsonify([dept.id for dept in Departement.query])
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/departement/<string:dept_ident>", methods=["GET"])
|
@bp.route("/departement/<string:acronym>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def departement(acronym: str):
|
||||||
def departement(dept_ident: str):
|
|
||||||
"""
|
"""
|
||||||
Info sur un département. Accès par id ou acronyme.
|
Info sur un département. Accès par acronyme.
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
{
|
{
|
||||||
@ -45,27 +50,27 @@ def departement(dept_ident: str):
|
|||||||
"date_creation": "Fri, 15 Apr 2022 12:19:28 GMT"
|
"date_creation": "Fri, 15 Apr 2022 12:19:28 GMT"
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
dept = get_departement(dept_ident)
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
||||||
return jsonify(dept.to_dict())
|
return jsonify(dept.to_dict())
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/departements", methods=["GET"])
|
@bp.route("/departement/id/<int:dept_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def departement_by_id(dept_id: int):
|
||||||
def departements():
|
"""
|
||||||
"""Liste les départements"""
|
Info sur un département. Accès par id.
|
||||||
return jsonify([dept.to_dict() for dept in Departement.query])
|
"""
|
||||||
|
dept = Departement.query.get_or_404(dept_id)
|
||||||
|
return jsonify(dept.to_dict())
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/departement/<string:dept_ident>/etudiants", methods=["GET"])
|
@bp.route("/departement/<string:acronym>/etudiants", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def dept_etudiants(acronym: str):
|
||||||
def list_etudiants(dept_ident: str):
|
|
||||||
"""
|
"""
|
||||||
Retourne la liste des étudiants d'un département
|
Retourne la liste des étudiants d'un département
|
||||||
|
|
||||||
dept: l'acronym d'un département
|
acronym: l'acronyme d'un département
|
||||||
formsemestre_id: l'id d'un formesemestre
|
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
@ -83,30 +88,41 @@ def list_etudiants(dept_ident: str):
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
# Le département, spécifié par un id ou un acronyme
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
||||||
dept = get_departement(dept_ident)
|
|
||||||
|
|
||||||
return jsonify([etud.to_dict_short() for etud in dept.etudiants])
|
return jsonify([etud.to_dict_short() for etud in dept.etudiants])
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/departement/<string:dept_ident>/formsemestres_ids", methods=["GET"])
|
@bp.route("/departement/id/<int:dept_id>/etudiants", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def dept_etudiants_by_id(dept_id: int):
|
||||||
def formsemestres_ids(dept_ident: str):
|
"""
|
||||||
|
Retourne la liste des étudiants d'un département d'id donné.
|
||||||
|
"""
|
||||||
|
dept = Departement.query.get_or_404(dept_id)
|
||||||
|
return jsonify([etud.to_dict_short() for etud in dept.etudiants])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/departement/<string:acronym>/formsemestres_ids", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def dept_formsemestres_ids(acronym: str):
|
||||||
"""liste des ids formsemestre du département"""
|
"""liste des ids formsemestre du département"""
|
||||||
# Le département, spécifié par un id ou un acronyme
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
||||||
dept = get_departement(dept_ident)
|
|
||||||
return jsonify([formsemestre.id for formsemestre in dept.formsemestres])
|
return jsonify([formsemestre.id for formsemestre in dept.formsemestres])
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/departement/<string:dept_ident>/formsemestres_courants", methods=["GET"])
|
@bp.route("/departement/id/<int:dept_id>/formsemestres_ids", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def dept_formsemestres_ids_by_id(dept_id: int):
|
||||||
def liste_semestres_courant(dept_ident: str):
|
"""liste des ids formsemestre du département"""
|
||||||
"""
|
dept = Departement.query.get_or_404(dept_id)
|
||||||
Liste des semestres actifs d'un départements donné
|
return jsonify([formsemestre.id for formsemestre in dept.formsemestres])
|
||||||
|
|
||||||
dept: l'acronym d'un département
|
|
||||||
|
@bp.route("/departement/<string:acronym>/formsemestres_courants", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def dept_formsemestres_courants(acronym: str):
|
||||||
|
"""
|
||||||
|
Liste des semestres actifs d'un département d'acronyme donné
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
@ -144,7 +160,7 @@ def liste_semestres_courant(dept_ident: str):
|
|||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
# Le département, spécifié par un id ou un acronyme
|
# Le département, spécifié par un id ou un acronyme
|
||||||
dept = get_departement(dept_ident)
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
||||||
|
|
||||||
# Les semestres en cours de ce département
|
# Les semestres en cours de ce département
|
||||||
formsemestres = models.FormSemestre.query.filter(
|
formsemestres = models.FormSemestre.query.filter(
|
||||||
@ -153,4 +169,23 @@ def liste_semestres_courant(dept_ident: str):
|
|||||||
FormSemestre.date_fin >= app.db.func.now(),
|
FormSemestre.date_fin >= app.db.func.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return jsonify([d.to_dict(convert_parcours=True) for d in formsemestres])
|
return jsonify([d.to_dict(convert_objects=True) for d in formsemestres])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/departement/id/<int:dept_id>/formsemestres_courants", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def dept_formsemestres_courants_by_id(dept_id: int):
|
||||||
|
"""
|
||||||
|
Liste des semestres actifs d'un département d'id donné
|
||||||
|
"""
|
||||||
|
# Le département, spécifié par un id ou un acronyme
|
||||||
|
dept = Departement.query.get_or_404(dept_id)
|
||||||
|
|
||||||
|
# Les semestres en cours de ce département
|
||||||
|
formsemestres = models.FormSemestre.query.filter(
|
||||||
|
FormSemestre.dept_id == dept.id,
|
||||||
|
FormSemestre.date_debut <= app.db.func.now(),
|
||||||
|
FormSemestre.date_fin >= app.db.func.now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify([d.to_dict(convert_objects=True) for d in formsemestres])
|
||||||
|
@ -27,6 +27,7 @@ from werkzeug.http import HTTP_STATUS_CODES
|
|||||||
|
|
||||||
|
|
||||||
def error_response(status_code, message=None):
|
def error_response(status_code, message=None):
|
||||||
|
"""Réponse sur erreur"""
|
||||||
payload = {"error": HTTP_STATUS_CODES.get(status_code, "Unknown error")}
|
payload = {"error": HTTP_STATUS_CODES.get(status_code, "Unknown error")}
|
||||||
if message:
|
if message:
|
||||||
payload["message"] = message
|
payload["message"] = message
|
||||||
@ -36,4 +37,5 @@ def error_response(status_code, message=None):
|
|||||||
|
|
||||||
|
|
||||||
def bad_request(message):
|
def bad_request(message):
|
||||||
|
"400 Bad Request response"
|
||||||
return error_response(400, message)
|
return error_response(400, message)
|
||||||
|
@ -13,18 +13,19 @@ from flask import jsonify
|
|||||||
import app
|
import app
|
||||||
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 permission_required_api
|
||||||
|
from app.api import tools
|
||||||
from app.models import Departement, FormSemestreInscription, FormSemestre, Identite
|
from app.models import Departement, 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_bulletins import do_formsemestre_bulletinetud
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/etudiants/courant", defaults={"long": False})
|
@bp.route("/etudiants/courants", defaults={"long": False})
|
||||||
@bp.route("/etudiants/courant/long", defaults={"long": True})
|
@bp.route("/etudiants/courants/long", defaults={"long": True})
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def etudiants_courants(long=False):
|
||||||
def etudiants_courant(long=False):
|
|
||||||
"""
|
"""
|
||||||
Liste des étudiants inscrits dans un formsemestre actuellement en cours.
|
Liste des étudiants inscrits dans un formsemestre actuellement en cours.
|
||||||
|
|
||||||
@ -63,8 +64,7 @@ def etudiants_courant(long=False):
|
|||||||
@bp.route("/etudiant/etudid/<int:etudid>", methods=["GET"])
|
@bp.route("/etudiant/etudid/<int:etudid>", methods=["GET"])
|
||||||
@bp.route("/etudiant/nip/<string:nip>", methods=["GET"])
|
@bp.route("/etudiant/nip/<string:nip>", methods=["GET"])
|
||||||
@bp.route("/etudiant/ine/<string:ine>", methods=["GET"])
|
@bp.route("/etudiant/ine/<string:ine>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
||||||
"""
|
"""
|
||||||
Retourne les informations de l'étudiant correspondant, ou 404 si non trouvé.
|
Retourne les informations de l'étudiant correspondant, ou 404 si non trouvé.
|
||||||
@ -104,27 +104,7 @@ def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
|||||||
"description": ""
|
"description": ""
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
if etudid is not None:
|
etud = tools.get_etud(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(
|
||||||
@ -138,8 +118,7 @@ def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
|||||||
@bp.route("/etudiants/etudid/<int:etudid>", methods=["GET"])
|
@bp.route("/etudiants/etudid/<int:etudid>", methods=["GET"])
|
||||||
@bp.route("/etudiants/nip/<string:nip>", methods=["GET"])
|
@bp.route("/etudiants/nip/<string:nip>", methods=["GET"])
|
||||||
@bp.route("/etudiants/ine/<string:ine>", methods=["GET"])
|
@bp.route("/etudiants/ine/<string:ine>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def etudiants(etudid: int = None, nip: str = None, ine: str = None):
|
def etudiants(etudid: int = None, nip: str = None, ine: str = None):
|
||||||
"""
|
"""
|
||||||
Info sur le ou les étudiants correspondant. Comme /etudiant mais renvoie
|
Info sur le ou les étudiants correspondant. Comme /etudiant mais renvoie
|
||||||
@ -166,41 +145,43 @@ def etudiants(etudid: int = None, nip: str = None, ine: str = None):
|
|||||||
@bp.route("/etudiant/etudid/<int:etudid>/formsemestres")
|
@bp.route("/etudiant/etudid/<int:etudid>/formsemestres")
|
||||||
@bp.route("/etudiant/nip/<string:nip>/formsemestres")
|
@bp.route("/etudiant/nip/<string:nip>/formsemestres")
|
||||||
@bp.route("/etudiant/ine/<string:ine>/formsemestres")
|
@bp.route("/etudiant/ine/<string:ine>/formsemestres")
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, 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):
|
||||||
"""
|
"""
|
||||||
Liste des semestres qu'un étudiant a suivi, triés par ordre chronologique.
|
Liste des semestres qu'un étudiant a suivi, triés par ordre chronologique.
|
||||||
|
Attention, si accès via NIP ou INE, les semestres peuvent être de départements différents
|
||||||
|
(si l'étudiant a changé de département). L'id du département est `dept_id`.
|
||||||
|
|
||||||
Accès par etudid, nip ou ine
|
Accès par etudid, nip ou ine
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"block_moyennes": false,
|
||||||
|
"bul_bgcolor": "white",
|
||||||
|
"bul_hide_xml": false,
|
||||||
|
"date_debut_iso": "2021-09-01",
|
||||||
|
"date_debut": "01/09/2021",
|
||||||
|
"date_fin_iso": "2022-08-31",
|
||||||
"date_fin": "31/08/2022",
|
"date_fin": "31/08/2022",
|
||||||
"resp_can_edit": false,
|
|
||||||
"dept_id": 1,
|
"dept_id": 1,
|
||||||
|
"elt_annee_apo": null,
|
||||||
|
"elt_sem_apo": null,
|
||||||
|
"ens_can_edit_eval": false,
|
||||||
"etat": true,
|
"etat": true,
|
||||||
"resp_can_change_ens": true,
|
"formation_id": 1,
|
||||||
|
"formsemestre_id": 1,
|
||||||
|
"gestion_compensation": false,
|
||||||
|
"gestion_semestrielle": false,
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"modalite": "FI",
|
"modalite": "FI",
|
||||||
"ens_can_edit_eval": false,
|
"resp_can_change_ens": true,
|
||||||
"formation_id": 1,
|
"resp_can_edit": false,
|
||||||
"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": []
|
"responsables": []
|
||||||
|
"scodoc7_id": null,
|
||||||
|
"semestre_id": 1,
|
||||||
|
"titre_num": "Semestre test semestre 1",
|
||||||
|
"titre": "Semestre test",
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
@ -231,48 +212,79 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
|
|||||||
formsemestres = query.order_by(FormSemestre.date_debut)
|
formsemestres = query.order_by(FormSemestre.date_debut)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
[formsemestre.to_dict(convert_parcours=True) for formsemestre in formsemestres]
|
[formsemestre.to_dict(convert_objects=True) for formsemestre in formsemestres]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "long"},
|
defaults={"version": "long", "pdf": False},
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "long"},
|
defaults={"version": "long", "pdf": False},
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "long"},
|
defaults={"version": "long", "pdf": False},
|
||||||
)
|
)
|
||||||
|
# Version PDF non fonctionnelle
|
||||||
|
@bp.route(
|
||||||
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
|
||||||
|
methods=["GET"],
|
||||||
|
defaults={"version": "long", "pdf": True},
|
||||||
|
)
|
||||||
|
# @bp.route(
|
||||||
|
# "/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
|
||||||
|
# methods=["GET"],
|
||||||
|
# defaults={"version": "long", "pdf": True},
|
||||||
|
# )
|
||||||
|
# @bp.route(
|
||||||
|
# "/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
|
||||||
|
# methods=["GET"],
|
||||||
|
# defaults={"version": "long", "pdf": True},
|
||||||
|
# )
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "short"},
|
defaults={"version": "short", "pdf": False},
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "short"},
|
defaults={"version": "short", "pdf": False},
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "short"},
|
defaults={"version": "short", "pdf": False},
|
||||||
)
|
)
|
||||||
@token_auth.login_required
|
@bp.route(
|
||||||
@token_permission_required(Permission.APIView)
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
||||||
def etudiant_bulletin_semestre(
|
methods=["GET"],
|
||||||
|
defaults={"version": "short", "pdf": True},
|
||||||
|
)
|
||||||
|
@bp.route(
|
||||||
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
||||||
|
methods=["GET"],
|
||||||
|
defaults={"version": "short", "pdf": True},
|
||||||
|
)
|
||||||
|
@bp.route(
|
||||||
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
||||||
|
methods=["GET"],
|
||||||
|
defaults={"version": "short", "pdf": True},
|
||||||
|
)
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def etudiant_bulletin_semestre( # XXX TODO Ajouter la possibilité de retourner en version pdf
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
etudid: int = None,
|
etudid: int = None,
|
||||||
nip: str = None,
|
nip: str = None,
|
||||||
ine: str = None,
|
ine: str = None,
|
||||||
version="long",
|
version="long",
|
||||||
|
pdf: bool = False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné
|
Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné
|
||||||
@ -281,150 +293,8 @@ def etudiant_bulletin_semestre(
|
|||||||
etudid : l'etudid d'un étudiant
|
etudid : l'etudid d'un étudiant
|
||||||
nip : le code nip d'un étudiant
|
nip : le code nip d'un étudiant
|
||||||
ine : le code ine d'un étudiant
|
ine : le code ine d'un étudiant
|
||||||
Exemple de résultat :
|
Exemple de résultat : voir https://scodoc.org/ScoDoc9API/#bulletin
|
||||||
{
|
|
||||||
"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()
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
||||||
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
||||||
@ -449,6 +319,13 @@ def etudiant_bulletin_semestre(
|
|||||||
)
|
)
|
||||||
|
|
||||||
app.set_sco_dept(dept.acronym)
|
app.set_sco_dept(dept.acronym)
|
||||||
|
|
||||||
|
if pdf:
|
||||||
|
pdf_response, _ = do_formsemestre_bulletinetud(
|
||||||
|
formsemestre, etudid, version=version, format="pdf"
|
||||||
|
)
|
||||||
|
return pdf_response
|
||||||
|
|
||||||
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
||||||
formsemestre, etud, version=version
|
formsemestre, etud, version=version
|
||||||
)
|
)
|
||||||
@ -466,8 +343,7 @@ def etudiant_bulletin_semestre(
|
|||||||
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/groups",
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/groups",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
)
|
)
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def etudiant_groups(
|
def etudiant_groups(
|
||||||
formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None
|
formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None
|
||||||
):
|
):
|
||||||
|
@ -1,23 +1,31 @@
|
|||||||
############################################### Evaluations ###########################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : accès aux évaluations
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
import app
|
import app
|
||||||
|
|
||||||
from app import models
|
from app import models
|
||||||
from app.models import Evaluation
|
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import permission_required_api
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
|
from app.models import Evaluation
|
||||||
from app.scodoc.sco_evaluation_db import do_evaluation_get_all_notes
|
from app.scodoc.sco_evaluation_db import do_evaluation_get_all_notes
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/evaluations/<int:moduleimpl_id>", methods=["GET"])
|
@bp.route("/evaluations/<int:moduleimpl_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def evaluations(moduleimpl_id: int):
|
def evaluations(moduleimpl_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des évaluations à partir de l'id d'un moduleimpl
|
Retourne la liste des évaluations d'un moduleimpl
|
||||||
|
|
||||||
moduleimpl_id : l'id d'un moduleimpl
|
moduleimpl_id : l'id d'un moduleimpl
|
||||||
|
|
||||||
@ -39,7 +47,7 @@ def evaluations(moduleimpl_id: int):
|
|||||||
"evaluation_id": 1,
|
"evaluation_id": 1,
|
||||||
"jouriso": "2022-04-20",
|
"jouriso": "2022-04-20",
|
||||||
"duree": "1h",
|
"duree": "1h",
|
||||||
"descrheure": " de 08h00 \u00e0 09h00",
|
"descrheure": " de 08h00 à 09h00",
|
||||||
"matin": 1,
|
"matin": 1,
|
||||||
"apresmidi": 0
|
"apresmidi": 0
|
||||||
},
|
},
|
||||||
@ -56,8 +64,7 @@ def evaluations(moduleimpl_id: int):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/evaluation/eval_notes/<int:evaluation_id>", methods=["GET"])
|
@bp.route("/evaluation/eval_notes/<int:evaluation_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def evaluation_notes(evaluation_id: int):
|
def evaluation_notes(evaluation_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des notes à partir de l'id d'une évaluation donnée
|
Retourne la liste des notes à partir de l'id d'une évaluation donnée
|
||||||
@ -87,16 +94,11 @@ def evaluation_notes(evaluation_id: int):
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# Fonction utilisée : app.scodoc.sco_evaluation_db.do_evaluation_get_all_notes()
|
|
||||||
|
|
||||||
evaluation = models.Evaluation.query.filter_by(id=evaluation_id).first_or_404()
|
evaluation = models.Evaluation.query.filter_by(id=evaluation_id).first_or_404()
|
||||||
dept = models.Departement.query.filter_by(
|
dept = evaluation.moduleimpl.formsemestre.departement
|
||||||
id=evaluation.moduleimpl.formsemestre.dept_id
|
|
||||||
).first()
|
|
||||||
app.set_sco_dept(dept.acronym)
|
app.set_sco_dept(dept.acronym)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Utilisation de la fonction do_evaluation_get_all_notes
|
|
||||||
data = do_evaluation_get_all_notes(evaluation_id)
|
data = do_evaluation_get_all_notes(evaluation_id)
|
||||||
except AttributeError: # ???
|
except AttributeError: # ???
|
||||||
return error_response(
|
return error_response(
|
||||||
|
@ -1,40 +1,53 @@
|
|||||||
##############################################" Formations ############################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : accès aux formations
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import models
|
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 permission_required_api
|
||||||
from app.models.formations import Formation
|
from app.models.formations import Formation
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formations_ids", methods=["GET"])
|
@bp.route("/formations", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def formations():
|
||||||
def formations_ids():
|
|
||||||
"""
|
"""
|
||||||
Retourne la liste de toutes les formations (tous départements)
|
Retourne la liste de toutes les formations (tous départements)
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = [d.to_dict() for d in models.Formation.query]
|
||||||
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/formations_ids", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def formations_ids():
|
||||||
|
"""
|
||||||
|
Retourne la liste de toutes les id de formations (tous départements)
|
||||||
|
|
||||||
Exemple de résultat : [ 17, 99, 32 ]
|
Exemple de résultat : [ 17, 99, 32 ]
|
||||||
"""
|
"""
|
||||||
# Récupération de toutes les formations
|
data = [d.id for d in models.Formation.query]
|
||||||
list_formations = models.Formation.query.all()
|
|
||||||
|
|
||||||
# Mise en forme des données
|
|
||||||
data = [d.id for d in list_formations]
|
|
||||||
|
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formation/<int:formation_id>", methods=["GET"])
|
@bp.route("/formation/<int:formation_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def formation_by_id(formation_id: int):
|
def formation_by_id(formation_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne une formation en fonction d'un id donné
|
La formation d'id donné
|
||||||
|
|
||||||
formation_id : l'id d'une formation
|
formation_id : l'id d'une formation
|
||||||
|
|
||||||
@ -42,7 +55,7 @@ def formation_by_id(formation_id: int):
|
|||||||
{
|
{
|
||||||
"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éseaux et télécommunications",
|
||||||
"formation_code": "V1RET",
|
"formation_code": "V1RET",
|
||||||
"code_specialite": null,
|
"code_specialite": null,
|
||||||
"dept_id": 1,
|
"dept_id": 1,
|
||||||
@ -53,13 +66,8 @@ def formation_by_id(formation_id: int):
|
|||||||
"formation_id": 1
|
"formation_id": 1
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# Récupération de la formation
|
formation = models.Formation.query.get_or_404(formation_id)
|
||||||
formation = models.Formation.query.filter_by(id=formation_id).first_or_404()
|
return jsonify(formation.to_dict())
|
||||||
|
|
||||||
# Mise en forme des données
|
|
||||||
data = formation.to_dict()
|
|
||||||
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
@ -72,13 +80,13 @@ def formation_by_id(formation_id: int):
|
|||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"export_ids": True},
|
defaults={"export_ids": True},
|
||||||
)
|
)
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def formation_export_by_formation_id(formation_id: int, export_ids=False):
|
def formation_export_by_formation_id(formation_id: int, export_ids=False):
|
||||||
"""
|
"""
|
||||||
Retourne la formation, avec UE, matières, modules
|
Retourne la formation, avec UE, matières, modules
|
||||||
|
|
||||||
formation_id : l'id d'une formation
|
formation_id : l'id d'une formation
|
||||||
|
export_ids : True ou False, si l'on veut ou non exporter les ids
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
{
|
{
|
||||||
@ -170,10 +178,8 @@ def formation_export_by_formation_id(formation_id: int, export_ids=False):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
formation = Formation.query.get_or_404(formation_id)
|
formation = Formation.query.get_or_404(formation_id)
|
||||||
dept = models.Departement.query.filter_by(id=formation.dept_id).first()
|
app.set_sco_dept(formation.departement.acronym)
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
try:
|
try:
|
||||||
# Utilisation de la fonction formation_export
|
|
||||||
data = sco_formations.formation_export(formation_id, export_ids)
|
data = sco_formations.formation_export(formation_id, export_ids)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return error_response(500, message="Erreur inconnue")
|
return error_response(500, message="Erreur inconnue")
|
||||||
@ -182,8 +188,7 @@ def formation_export_by_formation_id(formation_id: int, export_ids=False):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/formation/moduleimpl/<int:moduleimpl_id>", methods=["GET"])
|
@bp.route("/formation/moduleimpl/<int:moduleimpl_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def moduleimpl(moduleimpl_id: int):
|
def moduleimpl(moduleimpl_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne un module moduleimpl en fonction de son id
|
Retourne un module moduleimpl en fonction de son id
|
||||||
@ -219,26 +224,24 @@ def moduleimpl(moduleimpl_id: int):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
modimpl = models.ModuleImpl.query.filter_by(id=moduleimpl_id).first_or_404()
|
modimpl = models.ModuleImpl.query.get_or_404(moduleimpl_id)
|
||||||
data = modimpl.to_dict()
|
return jsonify(modimpl.to_dict())
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formation/<int:formation_id>/referentiel_competences",
|
"/formation/<int:formation_id>/referentiel_competences",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
)
|
)
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def referentiel_competences(formation_id: int):
|
def referentiel_competences(formation_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne le référentiel de compétences
|
Retourne le référentiel de compétences
|
||||||
|
|
||||||
formation_id : l'id d'une formation
|
formation_id : l'id d'une formation
|
||||||
|
|
||||||
return json, ou null si pas de référentiel associé.
|
return null si pas de référentiel associé.
|
||||||
"""
|
"""
|
||||||
formation = models.Formation.query.filter_by(id=formation_id).first_or_404()
|
formation = models.Formation.query.get_or_404(formation_id)
|
||||||
|
|
||||||
if formation.referentiel_competence is None:
|
if formation.referentiel_competence is None:
|
||||||
return jsonify(None)
|
return jsonify(None)
|
||||||
return jsonify(formation.referentiel_competence.to_dict())
|
return jsonify(formation.referentiel_competence.to_dict())
|
||||||
|
@ -1,20 +1,32 @@
|
|||||||
########################################## Formsemestres ##############################################################
|
##############################################################################
|
||||||
from flask import jsonify
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : accès aux formsemestres
|
||||||
|
"""
|
||||||
|
from flask import abort, jsonify, request
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import models
|
from app import models
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import permission_required_api
|
||||||
from app.models import Departement, FormSemestre, FormSemestreEtape
|
from app.comp import res_sem
|
||||||
|
from app.comp.moy_mod import ModuleImplResults
|
||||||
|
from app.comp.res_compat import NotesTableCompat
|
||||||
|
from app.models import Evaluation, FormSemestre, FormSemestreEtape, ModuleImpl
|
||||||
from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json
|
from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json
|
||||||
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.sco_utils import ModuleType
|
from app.scodoc.sco_utils import ModuleType
|
||||||
|
import app.scodoc.sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"])
|
@bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def formsemestre_infos(formsemestre_id: int):
|
||||||
def formsemestre(formsemestre_id: int):
|
|
||||||
"""
|
"""
|
||||||
Information sur le formsemestre indiqué.
|
Information sur le formsemestre indiqué.
|
||||||
|
|
||||||
@ -51,230 +63,67 @@ def formsemestre(formsemestre_id: int):
|
|||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
|
formsemestre: FormSemestre = models.FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
id=formsemestre_id
|
return jsonify(formsemestre.to_dict_api())
|
||||||
).first_or_404()
|
|
||||||
data = formsemestre.to_dict(convert_parcours=True)
|
|
||||||
# Pour le moment on a besoin de fixer le departement
|
|
||||||
# pour accéder aux préferences
|
|
||||||
dept = Departement.query.get(formsemestre.dept_id)
|
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
data["annee_scolaire"] = formsemestre.annee_scolaire_str()
|
|
||||||
data["session_id"] = formsemestre.session_id()
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/apo/<string:etape_apo>", methods=["GET"])
|
@bp.route("/formsemestres/query", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def formsemestres_query():
|
||||||
def formsemestre_apo(etape_apo: str):
|
|
||||||
"""
|
"""
|
||||||
Retourne les informations sur les formsemestres ayant cette étape Apogée
|
Retourne les formsemestres filtrés par
|
||||||
|
étape Apogée ou année scolaire ou département (acronyme ou id)
|
||||||
|
|
||||||
etape_apo : un code étape apogée
|
etape_apo : un code étape apogée
|
||||||
|
annee_scolaire : année de début de l'année scolaire
|
||||||
Exemple de résultat :
|
dept_acronym : acronyme du département (eg "RT")
|
||||||
[
|
dept_id : id du département
|
||||||
{ ...formsemestre...
|
|
||||||
}, ...
|
|
||||||
]
|
|
||||||
"""
|
"""
|
||||||
formsemestres = FormSemestre.query.filter(
|
etape_apo = request.args.get("etape_apo")
|
||||||
FormSemestreEtape.etape_apo == etape_apo,
|
annee_scolaire = request.args.get("annee_scolaire")
|
||||||
FormSemestreEtape.formsemestre_id == FormSemestre.id,
|
dept_acronym = request.args.get("dept_acronym")
|
||||||
)
|
dept_id = request.args.get("dept_id")
|
||||||
|
formsemestres = FormSemestre.query
|
||||||
|
if etape_apo is not None:
|
||||||
|
formsemestres = formsemestres.join(FormSemestreEtape).filter(
|
||||||
|
FormSemestreEtape.etape_apo == etape_apo
|
||||||
|
)
|
||||||
|
if annee_scolaire is not None:
|
||||||
|
try:
|
||||||
|
annee_scolaire_int = int(annee_scolaire)
|
||||||
|
except ValueError:
|
||||||
|
abort(404, "invalid annee_scolaire: not int")
|
||||||
|
debut_annee = scu.date_debut_anne_scolaire(annee_scolaire_int)
|
||||||
|
fin_annee = scu.date_fin_anne_scolaire(annee_scolaire_int)
|
||||||
|
formsemestres = formsemestres.filter(
|
||||||
|
FormSemestre.date_fin >= debut_annee, FormSemestre.date_debut <= fin_annee
|
||||||
|
)
|
||||||
|
if dept_acronym is not None:
|
||||||
|
formsemestres = formsemestres.join(models.Departement).filter_by(
|
||||||
|
acronym=dept_acronym
|
||||||
|
)
|
||||||
|
if dept_id is not None:
|
||||||
|
try:
|
||||||
|
dept_id = int(dept_id)
|
||||||
|
except ValueError:
|
||||||
|
abort(404, "invalid dept_id: not int")
|
||||||
|
formsemestres = formsemestres.filter_by(dept_id=dept_id)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify([formsemestre.to_dict_api() for formsemestre in formsemestres])
|
||||||
[formsemestre.to_dict(convert_parcours=True) for formsemestre in formsemestres]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
|
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def bulletins(formsemestre_id: int):
|
def bulletins(formsemestre_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne les bulletins d'un formsemestre donné
|
Retourne les bulletins d'un formsemestre donné
|
||||||
|
|
||||||
formsemestre_id : l'id d'un formesemestre
|
formsemestre_id : l'id d'un formesemestre
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat : liste, voir https://scodoc.org/ScoDoc9API/#bulletin
|
||||||
[
|
|
||||||
{
|
|
||||||
"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 = models.FormSemestre.query.filter_by(
|
formsemestre = models.FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
id=formsemestre_id
|
app.set_sco_dept(formsemestre.departement.acronym)
|
||||||
).first_or_404()
|
|
||||||
dept = models.Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for etu in formsemestre.etuds:
|
for etu in formsemestre.etuds:
|
||||||
@ -284,50 +133,11 @@ def bulletins(formsemestre_id: int):
|
|||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
# XXX Attendre ScoDoc 9.3
|
|
||||||
# @bp.route("/formsemestre/<int:formsemestre_id>/jury", methods=["GET"])
|
|
||||||
# @token_auth.login_required
|
|
||||||
# @token_permission_required(Permission.APIView)
|
|
||||||
# def jury(formsemestre_id: int):
|
|
||||||
# """
|
|
||||||
# Retourne le récapitulatif des décisions jury
|
|
||||||
|
|
||||||
# formsemestre_id : l'id d'un formsemestre
|
|
||||||
|
|
||||||
# Exemple de résultat :
|
|
||||||
|
|
||||||
# """
|
|
||||||
# # Fonction utilisée : app.scodoc.sco_pvjury.formsemestre_pvjury()
|
|
||||||
|
|
||||||
# formsemestre = models.FormSemestre.query.filter_by(
|
|
||||||
# id=formsemestre_id
|
|
||||||
# ).first_or_404()
|
|
||||||
|
|
||||||
# dept = models.Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
|
||||||
|
|
||||||
# app.set_sco_dept(dept.acronym)
|
|
||||||
|
|
||||||
# data = formsemestre_pvjury(formsemestre_id)
|
|
||||||
|
|
||||||
# # try:
|
|
||||||
# # # Utilisation de la fonction formsemestre_pvjury
|
|
||||||
# # data = formsemestre_pvjury(formsemestre_id)
|
|
||||||
# # except AttributeError:
|
|
||||||
# # return error_response(
|
|
||||||
# # 409,
|
|
||||||
# # message="La requête ne peut être traitée en l’état actuel. \n"
|
|
||||||
# # "Veillez vérifier la conformité du 'formation_id'",
|
|
||||||
# # )
|
|
||||||
|
|
||||||
# return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formsemestre/<int:formsemestre_id>/programme",
|
"/formsemestre/<int:formsemestre_id>/programme",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
)
|
)
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def formsemestre_programme(formsemestre_id: int):
|
def formsemestre_programme(formsemestre_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des Ues, ressources et SAE d'un semestre
|
Retourne la liste des Ues, ressources et SAE d'un semestre
|
||||||
@ -393,10 +203,7 @@ def formsemestre_programme(formsemestre_id: int):
|
|||||||
"modules" : [ ... les modules qui ne sont ni des SAEs ni des ressources ... ]
|
"modules" : [ ... les modules qui ne sont ni des SAEs ni des ressources ... ]
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
|
formsemestre: FormSemestre = models.FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
id=formsemestre_id
|
|
||||||
).first_or_404()
|
|
||||||
|
|
||||||
ues = formsemestre.query_ues()
|
ues = formsemestre.query_ues()
|
||||||
m_list = {
|
m_list = {
|
||||||
ModuleType.RESSOURCE: [],
|
ModuleType.RESSOURCE: [],
|
||||||
@ -404,14 +211,179 @@ def formsemestre_programme(formsemestre_id: int):
|
|||||||
ModuleType.STANDARD: [],
|
ModuleType.STANDARD: [],
|
||||||
}
|
}
|
||||||
for modimpl in formsemestre.modimpls_sorted:
|
for modimpl in formsemestre.modimpls_sorted:
|
||||||
d = modimpl.to_dict()
|
d = modimpl.to_dict(convert_objects=True)
|
||||||
m_list[modimpl.module.module_type].append(d)
|
m_list[modimpl.module.module_type].append(d)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
{
|
{
|
||||||
"ues": [ue.to_dict() for ue in ues],
|
"ues": [ue.to_dict(convert_objects=True) for ue in ues],
|
||||||
"ressources": m_list[ModuleType.RESSOURCE],
|
"ressources": m_list[ModuleType.RESSOURCE],
|
||||||
"saes": m_list[ModuleType.SAE],
|
"saes": m_list[ModuleType.SAE],
|
||||||
"modules": m_list[ModuleType.STANDARD],
|
"modules": m_list[ModuleType.STANDARD],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(
|
||||||
|
"/formsemestre/<int:formsemestre_id>/etudiants",
|
||||||
|
methods=["GET"],
|
||||||
|
defaults={"etat": scu.INSCRIT},
|
||||||
|
)
|
||||||
|
@bp.route(
|
||||||
|
"/formsemestre/<int:formsemestre_id>/etudiants/demissionnaires",
|
||||||
|
methods=["GET"],
|
||||||
|
defaults={"etat": scu.DEMISSION},
|
||||||
|
)
|
||||||
|
@bp.route(
|
||||||
|
"/formsemestre/<int:formsemestre_id>/etudiants/defaillants",
|
||||||
|
methods=["GET"],
|
||||||
|
defaults={"etat": scu.DEF},
|
||||||
|
)
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def formsemestre_etudiants(formsemestre_id: int, etat: str):
|
||||||
|
"""
|
||||||
|
Retourne la liste des étudiants d'un formsemestre
|
||||||
|
|
||||||
|
formsemestre_id : l'id d'un formsemestre
|
||||||
|
"""
|
||||||
|
formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
|
||||||
|
id=formsemestre_id
|
||||||
|
).first_or_404()
|
||||||
|
|
||||||
|
inscriptions = [ins for ins in formsemestre.inscriptions if ins.etat == etat]
|
||||||
|
etuds = [ins.etud.to_dict_short() for ins in inscriptions]
|
||||||
|
# Ajout des groupes de chaque étudiants
|
||||||
|
# XXX A REVOIR: trop inefficace !
|
||||||
|
for etud in etuds:
|
||||||
|
etud["groups"] = sco_groups.get_etud_groups(etud["id"], formsemestre_id)
|
||||||
|
|
||||||
|
return jsonify(etuds)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/formsemestre/<int:formsemestre_id>/etat_evals", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def etat_evals(formsemestre_id: int):
|
||||||
|
"""
|
||||||
|
Informations sur l'état des évaluations d'un formsemestre.
|
||||||
|
|
||||||
|
formsemestre_id : l'id d'un semestre
|
||||||
|
|
||||||
|
Exemple de résultat :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1, // moduleimpl_id
|
||||||
|
"titre": "Initiation aux réseaux informatiques",
|
||||||
|
"evaluations": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"description": null,
|
||||||
|
"datetime_epreuve": null,
|
||||||
|
"heure_fin": "09:00:00",
|
||||||
|
"coefficient": "02.00"
|
||||||
|
"is_complete": true,
|
||||||
|
"nb_inscrits": 16,
|
||||||
|
"nb_manquantes": 0,
|
||||||
|
"ABS": 0,
|
||||||
|
"ATT": 0,
|
||||||
|
"EXC": 0,
|
||||||
|
"saisie_notes": {
|
||||||
|
"datetime_debut": "2021-09-11T00:00:00+02:00",
|
||||||
|
"datetime_fin": "2022-08-25T00:00:00+02:00",
|
||||||
|
"datetime_mediane": "2022-03-19T00:00:00+01:00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
app.set_sco_dept(formsemestre.departement.acronym)
|
||||||
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for modimpl_id in nt.modimpls_results:
|
||||||
|
modimpl_results: ModuleImplResults = nt.modimpls_results[modimpl_id]
|
||||||
|
modimpl = ModuleImpl.query.get_or_404(modimpl_id)
|
||||||
|
modimpl_dict = modimpl.to_dict()
|
||||||
|
|
||||||
|
list_eval = []
|
||||||
|
for evaluation_id in modimpl_results.evaluations_etat:
|
||||||
|
eval_etat = modimpl_results.evaluations_etat[evaluation_id]
|
||||||
|
evaluation = Evaluation.query.get_or_404(evaluation_id)
|
||||||
|
eval_dict = evaluation.to_dict()
|
||||||
|
eval_dict["etat"] = eval_etat.to_dict()
|
||||||
|
|
||||||
|
eval_dict["nb_inscrits"] = modimpl_results.nb_inscrits_module
|
||||||
|
eval_dict["nb_notes_manquantes"] = len(
|
||||||
|
modimpl_results.evals_etudids_sans_note[evaluation.id]
|
||||||
|
)
|
||||||
|
eval_dict["nb_notes_abs"] = sum(
|
||||||
|
modimpl_results.evals_notes[evaluation.id] == scu.NOTES_ABSENCE
|
||||||
|
)
|
||||||
|
eval_dict["nb_notes_att"] = eval_etat.nb_attente
|
||||||
|
eval_dict["nb_notes_exc"] = sum(
|
||||||
|
modimpl_results.evals_notes[evaluation.id] == scu.NOTES_NEUTRALISE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Récupération de toutes les notes de l'évaluation
|
||||||
|
# eval["notes"] = modimpl_results.get_eval_notes_dict(evaluation_id)
|
||||||
|
|
||||||
|
notes = models.NotesNotes.query.filter_by(evaluation_id=evaluation.id).all()
|
||||||
|
|
||||||
|
date_debut = None
|
||||||
|
date_fin = None
|
||||||
|
date_mediane = None
|
||||||
|
|
||||||
|
# Si il y a plus d'une note saisie pour l'évaluation
|
||||||
|
if len(notes) >= 1:
|
||||||
|
# Trie des notes en fonction de leurs dates
|
||||||
|
notes_sorted = sorted(notes, key=lambda note: note.date)
|
||||||
|
|
||||||
|
date_debut = notes_sorted[0].date
|
||||||
|
date_fin = notes_sorted[-1].date
|
||||||
|
|
||||||
|
# Récupération de l'id de la note médiane
|
||||||
|
list_id_notes_sorted = [note.id for note in notes_sorted]
|
||||||
|
id_mediane = list_id_notes_sorted[len(list_id_notes_sorted) // 2]
|
||||||
|
date_mediane = notes_sorted[id_mediane].date
|
||||||
|
|
||||||
|
eval_dict["saisie_notes"] = {
|
||||||
|
"datetime_debut": date_debut.isoformat()
|
||||||
|
if date_debut is not None
|
||||||
|
else None,
|
||||||
|
"datetime_fin": date_fin.isoformat() if date_fin is not None else None,
|
||||||
|
"datetime_mediane": date_mediane.isoformat()
|
||||||
|
if date_mediane is not None
|
||||||
|
else None,
|
||||||
|
}
|
||||||
|
|
||||||
|
list_eval.append(eval)
|
||||||
|
|
||||||
|
modimpl_dict["evaluations"] = list_eval
|
||||||
|
result.append(modimpl_dict)
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/formsemestre/<int:formsemestre_id>/resultats", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def formsemestre_resultat(formsemestre_id: int):
|
||||||
|
"""Tableau récapitulatif des résultats
|
||||||
|
Pour chaque étudiant, son état, ses groupes, ses moyennes d'UE et de modules.
|
||||||
|
"""
|
||||||
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
app.set_sco_dept(formsemestre.departement.acronym)
|
||||||
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
rows, footer_rows, titles, column_ids = res.get_table_recap(
|
||||||
|
convert_values=False,
|
||||||
|
include_evaluations=False,
|
||||||
|
mode_jury=False,
|
||||||
|
allow_html=False,
|
||||||
|
)
|
||||||
|
# Supprime les champs inutiles (mise en forme)
|
||||||
|
table = [{k: row[k] for k in row if not k[0] == "_"} for row in rows]
|
||||||
|
# Ajoute les groupes
|
||||||
|
etud_groups = sco_groups.get_formsemestre_etuds_groups(formsemestre_id)
|
||||||
|
for row in table:
|
||||||
|
row["partitions"] = etud_groups.get(row["etudid"], {})
|
||||||
|
return jsonify(table)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# from app import models
|
# 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 permission_required_api
|
||||||
# from app.scodoc.sco_prepajury import feuille_preparation_jury
|
# from app.scodoc.sco_prepajury import feuille_preparation_jury
|
||||||
# from app.scodoc.sco_pvjury import formsemestre_pvjury
|
# from app.scodoc.sco_pvjury import formsemestre_pvjury
|
||||||
|
|
||||||
|
@ -38,13 +38,12 @@ from app.api.auth import token_auth
|
|||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.models import Departement
|
from app.models import Departement
|
||||||
from app.scodoc.sco_logos import list_logos, find_logo
|
from app.scodoc.sco_logos import list_logos, find_logo
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import permission_required_api
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/logos", methods=["GET"])
|
@bp.route("/logos", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def api_get_glob_logos():
|
def api_get_glob_logos():
|
||||||
if not g.current_user.has_permission(Permission.ScoSuperAdmin, None):
|
if not g.current_user.has_permission(Permission.ScoSuperAdmin, None):
|
||||||
return error_response(401, message="accès interdit")
|
return error_response(401, message="accès interdit")
|
||||||
@ -56,8 +55,7 @@ def api_get_glob_logos():
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/logos/<string:logoname>", methods=["GET"])
|
@bp.route("/logos/<string:logoname>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def api_get_glob_logo(logoname):
|
def api_get_glob_logo(logoname):
|
||||||
if not g.current_user.has_permission(Permission.ScoSuperAdmin, None):
|
if not g.current_user.has_permission(Permission.ScoSuperAdmin, None):
|
||||||
return error_response(401, message="accès interdit")
|
return error_response(401, message="accès interdit")
|
||||||
@ -73,8 +71,7 @@ def api_get_glob_logo(logoname):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/departements/<string:departement>/logos", methods=["GET"])
|
@bp.route("/departements/<string:departement>/logos", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def api_get_local_logos(departement):
|
def api_get_local_logos(departement):
|
||||||
dept_id = Departement.from_acronym(departement).id
|
dept_id = Departement.from_acronym(departement).id
|
||||||
if not g.current_user.has_permission(Permission.ScoChangePreferences, departement):
|
if not g.current_user.has_permission(Permission.ScoChangePreferences, departement):
|
||||||
@ -84,8 +81,7 @@ def api_get_local_logos(departement):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/departements/<string:departement>/logos/<string:logoname>", methods=["GET"])
|
@bp.route("/departements/<string:departement>/logos/<string:logoname>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def api_get_local_logo(departement, logoname):
|
def api_get_local_logo(departement, logoname):
|
||||||
# format = requested_format("jpg", ['png', 'jpg']) XXX ?
|
# format = requested_format("jpg", ['png', 'jpg']) XXX ?
|
||||||
dept_id = Departement.from_acronym(departement).id
|
dept_id = Departement.from_acronym(departement).id
|
||||||
|
@ -1,145 +1,320 @@
|
|||||||
############################################### Partitions ############################################################
|
##############################################################################
|
||||||
from flask import jsonify
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
from app import models
|
"""
|
||||||
|
ScoDoc 9 API : partitions
|
||||||
|
"""
|
||||||
|
from flask import abort, jsonify, request
|
||||||
|
|
||||||
|
import app
|
||||||
|
from app import db, log
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
|
from app.api.auth import permission_required_api
|
||||||
from app.api.errors import error_response
|
from app.models import FormSemestre, FormSemestreInscription, Identite
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.models import GroupDescr, Partition
|
||||||
from app.scodoc.sco_groups import get_group_members, setGroups, get_partitions_list
|
from app.models.groups import group_membership
|
||||||
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/partitions/<int:formsemestre_id>", methods=["GET"])
|
@bp.route("/partition/<int:partition_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_permission_required(Permission.APIView)
|
def partition_info(partition_id: int):
|
||||||
def partition(formsemestre_id: int):
|
"""
|
||||||
|
Exemple de résultat :
|
||||||
|
```
|
||||||
|
{
|
||||||
|
'bul_show_rank': False,
|
||||||
|
'formsemestre_id': 39,
|
||||||
|
'groups': [
|
||||||
|
{'id': 268, 'name': 'A', 'partition_id': 100},
|
||||||
|
{'id': 269, 'name': 'B', 'partition_id': 100}
|
||||||
|
],
|
||||||
|
'groups_editable': True,
|
||||||
|
'id': 100,
|
||||||
|
'numero': 100,
|
||||||
|
'partition_name': 'TD',
|
||||||
|
'show_in_lists': True
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
partition = Partition.query.get_or_404(partition_id)
|
||||||
|
return jsonify(partition.to_dict(with_groups=True))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/formsemestre/<int:formsemestre_id>/partitions", methods=["GET"])
|
||||||
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
|
def formsemestre_partitions(formsemestre_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne la liste de toutes les partitions d'un formsemestre
|
Retourne la liste de toutes les partitions d'un formsemestre
|
||||||
|
|
||||||
formsemestre_id : l'id d'un formsemestre
|
formsemestre_id : l'id d'un formsemestre
|
||||||
|
|
||||||
Exemple de résultat :
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"partition_id": 2,
|
|
||||||
"id": 2,
|
|
||||||
"formsemestre_id": 1,
|
|
||||||
"partition_name": "TD",
|
|
||||||
"numero": 1,
|
|
||||||
"bul_show_rank": false,
|
|
||||||
"show_in_lists": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"partition_id": 1,
|
|
||||||
"id": 1,
|
|
||||||
"formsemestre_id": 1,
|
|
||||||
"partition_name": null,
|
|
||||||
"numero": 0,
|
|
||||||
"bul_show_rank": false,
|
|
||||||
"show_in_lists": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"""
|
"""
|
||||||
# # Récupération de toutes les partitions
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
# partitions = models.Partition.query.filter_by(id=formsemestre_id)
|
return jsonify(
|
||||||
#
|
[partition.to_dict(with_groups=True) for partition in formsemestre.partitions]
|
||||||
# # Mise en forme des données
|
)
|
||||||
# data = [partition.to_dict() for partition in partitions]
|
|
||||||
|
|
||||||
data = get_partitions_list(formsemestre_id)
|
|
||||||
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/partitions/groups/<int:group_id>", methods=["GET"])
|
@bp.route("/group/<int:group_id>/etudiants", methods=["GET"])
|
||||||
@bp.route("/partitions/groups/<int:group_id>/etat/<string:etat>", methods=["GET"])
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
@token_auth.login_required
|
def etud_in_group(group_id: int):
|
||||||
@token_permission_required(Permission.APIView)
|
|
||||||
def etud_in_group(group_id: int, etat=None):
|
|
||||||
"""
|
"""
|
||||||
Retourne la liste des étudiants dans un groupe
|
Retourne la liste des étudiants dans un groupe
|
||||||
|
|
||||||
group_id : l'id d'un groupe
|
group_id : l'id d'un groupe
|
||||||
etat : état de l'inscription
|
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"etudid": 10,
|
'civilite': 'M',
|
||||||
"id": 10,
|
'id': 123456,
|
||||||
"dept_id": 1,
|
'ine': None,
|
||||||
"nom": "BOUTET",
|
'nip': '987654321',
|
||||||
"prenom": "Marguerite",
|
'nom': 'MARTIN',
|
||||||
"nom_usuel": "",
|
'nom_usuel': null,
|
||||||
"civilite": "F",
|
'prenom': 'JEAN'}
|
||||||
"date_naissance": null,
|
},
|
||||||
"lieu_naissance": null,
|
...
|
||||||
"dept_naissance": null,
|
]
|
||||||
"nationalite": null,
|
|
||||||
"statut": null,
|
|
||||||
"boursier": null,
|
|
||||||
"photo_filename": null,
|
|
||||||
"code_nip": "10",
|
|
||||||
"code_ine": "10",
|
|
||||||
"scodoc7_id": null,
|
|
||||||
"email": "MARGUERITE.BOUTET@example.com",
|
|
||||||
"emailperso": null,
|
|
||||||
"domicile": null,
|
|
||||||
"codepostaldomicile": null,
|
|
||||||
"villedomicile": null,
|
|
||||||
"paysdomicile": null,
|
|
||||||
"telephone": null,
|
|
||||||
"telephonemobile": null,
|
|
||||||
"fax": null,
|
|
||||||
"typeadresse": "domicile",
|
|
||||||
"description": null,
|
|
||||||
"group_id": 1,
|
|
||||||
"etat": "I",
|
|
||||||
"civilite_str": "Mme",
|
|
||||||
"nom_disp": "BOUTET",
|
|
||||||
"nomprenom": "Mme Marguerite BOUTET",
|
|
||||||
"ne": "e",
|
|
||||||
"email_default": "MARGUERITE.BOUTET@example.com"
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"""
|
"""
|
||||||
# Fonction utilisée : app.scodoc.sco_groups.get_group_members()
|
group = GroupDescr.query.get_or_404(group_id)
|
||||||
|
return jsonify([etud.to_dict_short() for etud in group.etuds])
|
||||||
if etat is None:
|
|
||||||
data = get_group_members(group_id)
|
|
||||||
else:
|
|
||||||
data = get_group_members(group_id, etat)
|
|
||||||
|
|
||||||
if len(data) == 0:
|
|
||||||
return error_response(404, message="group_id inconnu")
|
|
||||||
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route("/group/<int:group_id>/etudiants/query", methods=["GET"])
|
||||||
"/partitions/set_groups/partition/<int:partition_id>/groups/<string:groups_id>/delete/<string:groups_to_delete>"
|
@permission_required_api(Permission.ScoView, Permission.APIView)
|
||||||
"/create/<string:groups_to_create>",
|
def etud_in_group_query(group_id: int):
|
||||||
methods=["POST"],
|
"""Etudiants du groupe, filtrés par état"""
|
||||||
)
|
etat = request.args.get("etat")
|
||||||
@token_auth.login_required
|
if etat not in {scu.INSCRIT, scu.DEMISSION, scu.DEF}:
|
||||||
@token_permission_required(Permission.APIEtudChangeGroups)
|
abort(404, "etat invalid")
|
||||||
def set_groups(
|
group = GroupDescr.query.get_or_404(group_id)
|
||||||
partition_id: int, groups_lists: str, groups_to_delete: str, groups_to_create: str
|
query = (
|
||||||
):
|
Identite.query.join(FormSemestreInscription)
|
||||||
|
.filter_by(formsemestre_id=group.partition.formsemestre_id, etat=etat)
|
||||||
|
.join(group_membership)
|
||||||
|
.filter_by(group_id=group_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify([etud.to_dict_short() for etud in query])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/group/<int:group_id>/set_etudiant/<int:etudid>", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def set_etud_group(etudid: int, group_id: int):
|
||||||
|
"""Affecte l'étudiant au groupe indiqué"""
|
||||||
|
etud = Identite.query.get_or_404(etudid)
|
||||||
|
group = GroupDescr.query.get_or_404(group_id)
|
||||||
|
if etud.id not in {e.id for e in group.partition.formsemestre.etuds}:
|
||||||
|
abort(404, "etud non inscrit au formsemestre du groupe")
|
||||||
|
groups = (
|
||||||
|
GroupDescr.query.filter_by(partition_id=group.partition.id)
|
||||||
|
.join(group_membership)
|
||||||
|
.filter_by(etudid=etudid)
|
||||||
|
)
|
||||||
|
ok = False
|
||||||
|
for g in groups:
|
||||||
|
if g.id == group_id:
|
||||||
|
ok = True
|
||||||
|
else:
|
||||||
|
g.etuds.remove(etud)
|
||||||
|
if not ok:
|
||||||
|
group.etuds.append(etud)
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify({"group_id": group_id, "etudid": etudid})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/partition/<int:partition_id>/group/create", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def group_create(partition_id: int):
|
||||||
|
"""Création d'un groupe dans une partition
|
||||||
|
|
||||||
|
The request content type should be "application/json":
|
||||||
|
{
|
||||||
|
"group_name" : nom_du_groupe,
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
Set les groups
|
partition: Partition = Partition.query.get_or_404(partition_id)
|
||||||
|
if not partition.groups_editable:
|
||||||
|
abort(404, "partition non editable")
|
||||||
|
data = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
|
group_name = data.get("group_name")
|
||||||
|
if group_name is None:
|
||||||
|
abort(404, "missing group name or invalid data format")
|
||||||
|
if not GroupDescr.check_name(partition, group_name):
|
||||||
|
abort(404, "invalid group_name")
|
||||||
|
group_name = group_name.strip()
|
||||||
|
|
||||||
partition_id : l'id d'une partition
|
group = GroupDescr(group_name=group_name, partition_id=partition_id)
|
||||||
groups_lists : membres de chaque groupe existant
|
db.session.add(group)
|
||||||
groups_ti_delete : les groupes à supprimer
|
db.session.commit()
|
||||||
groups_to_create : les groupes à créer
|
log(f"created group {group}")
|
||||||
|
app.set_sco_dept(partition.formsemestre.departement.acronym)
|
||||||
|
sco_cache.invalidate_formsemestre(partition.formsemestre_id)
|
||||||
|
return jsonify(group.to_dict(with_partition=True))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/group/<int:group_id>/delete", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def group_delete(group_id: int):
|
||||||
|
"""Suppression d'un groupe"""
|
||||||
|
group = GroupDescr.query.get_or_404(group_id)
|
||||||
|
if not group.partition.groups_editable:
|
||||||
|
abort(404, "partition non editable")
|
||||||
|
formsemestre_id = group.partition.formsemestre_id
|
||||||
|
log(f"deleting {group}")
|
||||||
|
db.session.delete(group)
|
||||||
|
db.session.commit()
|
||||||
|
app.set_sco_dept(group.partition.formsemestre.departement.acronym)
|
||||||
|
sco_cache.invalidate_formsemestre(formsemestre_id)
|
||||||
|
return jsonify({"OK": 1})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/group/<int:group_id>/edit", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def group_edit(group_id: int):
|
||||||
|
"""Edit a group"""
|
||||||
|
group: GroupDescr = GroupDescr.query.get_or_404(group_id)
|
||||||
|
if not group.partition.groups_editable:
|
||||||
|
abort(404, "partition non editable")
|
||||||
|
data = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
|
group_name = data.get("group_name")
|
||||||
|
if group_name is not None:
|
||||||
|
if not GroupDescr.check_name(group.partition, group_name, existing=True):
|
||||||
|
abort(404, "invalid group_name")
|
||||||
|
group.group_name = group_name.strip()
|
||||||
|
db.session.add(group)
|
||||||
|
db.session.commit()
|
||||||
|
log(f"modified {group}")
|
||||||
|
app.set_sco_dept(group.partition.formsemestre.departement.acronym)
|
||||||
|
sco_cache.invalidate_formsemestre(group.partition.formsemestre_id)
|
||||||
|
return jsonify(group.to_dict(with_partition=True))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/formsemestre/<int:formsemestre_id>/partition/create", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def partition_create(formsemestre_id: int):
|
||||||
|
"""Création d'une partition dans un semestre
|
||||||
|
|
||||||
|
The request content type should be "application/json":
|
||||||
|
{
|
||||||
|
"partition_name": str,
|
||||||
|
"numero":int,
|
||||||
|
"bul_show_rank":bool,
|
||||||
|
"show_in_lists":bool,
|
||||||
|
"groups_editable":bool
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
# Fonction utilisée : app.scodoc.sco_groups.setGroups()
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
try:
|
data = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
# Utilisation de la fonction setGroups
|
partition_name = data.get("partition_name")
|
||||||
setGroups(partition_id, groups_lists, groups_to_create, groups_to_delete)
|
if partition_name is None:
|
||||||
return error_response(200, message="Groups set")
|
abort(404, "missing partition_name or invalid data format")
|
||||||
except ValueError:
|
if not Partition.check_name(formsemestre, partition_name):
|
||||||
return error_response(404, message="Erreur")
|
abort(404, "invalid partition_name")
|
||||||
|
numero = data.get("numero", 0)
|
||||||
|
if not isinstance(numero, int):
|
||||||
|
abort(404, "invalid type for numero")
|
||||||
|
args = {
|
||||||
|
"formsemestre_id": formsemestre_id,
|
||||||
|
"partition_name": partition_name.strip(),
|
||||||
|
"numero": numero,
|
||||||
|
}
|
||||||
|
for boolean_field in ("bul_show_rank", "show_in_lists", "groups_editable"):
|
||||||
|
value = data.get(
|
||||||
|
boolean_field, False if boolean_field != "groups_editable" else True
|
||||||
|
)
|
||||||
|
if not isinstance(value, bool):
|
||||||
|
abort(404, f"invalid type for {boolean_field}")
|
||||||
|
args[boolean_field] = value
|
||||||
|
|
||||||
|
partition = Partition(**args)
|
||||||
|
db.session.add(partition)
|
||||||
|
db.session.commit()
|
||||||
|
log(f"created partition {partition}")
|
||||||
|
app.set_sco_dept(formsemestre.departement.acronym)
|
||||||
|
sco_cache.invalidate_formsemestre(formsemestre_id)
|
||||||
|
return jsonify(partition.to_dict(with_groups=True))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/partition/<int:partition_id>/edit", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def partition_edit(partition_id: int):
|
||||||
|
"""Modification d'une partition dans un semestre
|
||||||
|
|
||||||
|
The request content type should be "application/json"
|
||||||
|
All fields are optional:
|
||||||
|
{
|
||||||
|
"partition_name": str,
|
||||||
|
"numero":int,
|
||||||
|
"bul_show_rank":bool,
|
||||||
|
"show_in_lists":bool,
|
||||||
|
"groups_editable":bool
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
partition = Partition.query.get_or_404(partition_id)
|
||||||
|
data = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
|
modified = False
|
||||||
|
partition_name = data.get("partition_name")
|
||||||
|
if partition_name is not None and partition_name != partition.partition_name:
|
||||||
|
if not Partition.check_name(
|
||||||
|
partition.formsemestre, partition_name, existing=True
|
||||||
|
):
|
||||||
|
abort(404, "invalid partition_name")
|
||||||
|
partition.partition_name = partition_name.strip()
|
||||||
|
modified = True
|
||||||
|
|
||||||
|
numero = data.get("numero")
|
||||||
|
if numero is not None and numero != partition.numero:
|
||||||
|
if not isinstance(numero, int):
|
||||||
|
abort(404, "invalid type for numero")
|
||||||
|
partition.numero = numero
|
||||||
|
modified = True
|
||||||
|
|
||||||
|
for boolean_field in ("bul_show_rank", "show_in_lists", "groups_editable"):
|
||||||
|
value = data.get(boolean_field)
|
||||||
|
if value is not None and value != getattr(partition, boolean_field):
|
||||||
|
if not isinstance(value, bool):
|
||||||
|
abort(404, f"invalid type for {boolean_field}")
|
||||||
|
setattr(partition, boolean_field, value)
|
||||||
|
modified = True
|
||||||
|
|
||||||
|
if modified:
|
||||||
|
db.session.add(partition)
|
||||||
|
db.session.commit()
|
||||||
|
log(f"modified partition {partition}")
|
||||||
|
app.set_sco_dept(partition.formsemestre.departement.acronym)
|
||||||
|
sco_cache.invalidate_formsemestre(partition.formsemestre_id)
|
||||||
|
|
||||||
|
return jsonify(partition.to_dict(with_groups=True))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/partition/<int:partition_id>/delete", methods=["POST"])
|
||||||
|
@permission_required_api(Permission.ScoEtudChangeGroups, Permission.APIEditGroups)
|
||||||
|
def partition_delete(partition_id: int):
|
||||||
|
"""Suppression d'une partition (et de tous ses groupes).
|
||||||
|
|
||||||
|
Note 1: La partition par défaut (tous les étudiants du sem.) ne peut
|
||||||
|
pas être supprimée.
|
||||||
|
Note 2: Si la partition de parcours est supprimée, les étudiants
|
||||||
|
sont désinscrits des parcours.
|
||||||
|
"""
|
||||||
|
partition = Partition.query.get_or_404(partition_id)
|
||||||
|
if not partition.partition_name:
|
||||||
|
abort(404, "ne peut pas supprimer la partition par défaut")
|
||||||
|
is_parcours = partition.is_parcours()
|
||||||
|
formsemestre: FormSemestre = partition.formsemestre
|
||||||
|
log(f"deleting partition {partition}")
|
||||||
|
db.session.delete(partition)
|
||||||
|
db.session.commit()
|
||||||
|
app.set_sco_dept(partition.formsemestre.departement.acronym)
|
||||||
|
sco_cache.invalidate_formsemestre(formsemestre.id)
|
||||||
|
if is_parcours:
|
||||||
|
formsemestre.update_inscriptions_parcours_from_groups()
|
||||||
|
return jsonify({"OK": 1})
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
"""ScoDoc 9 API : outils
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
from app import models
|
from app import models
|
||||||
|
from app.api.errors import error_response
|
||||||
|
from app.models import Identite, Admission
|
||||||
|
|
||||||
|
|
||||||
def get_etud_from_etudid_or_nip_or_ine(
|
def get_etud(etudid=None, nip=None, ine=None) -> models.Identite:
|
||||||
etudid=None, nip=None, ine=None
|
|
||||||
) -> models.Identite:
|
|
||||||
"""
|
"""
|
||||||
etudiant en fonction de l'etudid, code nip et code ine rentré en paramètres
|
L'instance d'étudiant la plus récente en fonction de l'etudid,
|
||||||
|
ou du code nip ou code ine.
|
||||||
|
|
||||||
etudid : None ou un int etudid
|
etudid : None ou un int etudid
|
||||||
nip : None ou un int code_nip
|
nip : None ou un int code_nip
|
||||||
@ -13,12 +24,16 @@ def get_etud_from_etudid_or_nip_or_ine(
|
|||||||
|
|
||||||
Return None si étudiant inexistant.
|
Return None si étudiant inexistant.
|
||||||
"""
|
"""
|
||||||
if etudid is None:
|
if etudid is not None:
|
||||||
if nip is None: # si ine
|
return Identite.query.get(etudid)
|
||||||
etud = models.Identite.query.filter_by(code_ine=str(ine)).first()
|
|
||||||
else: # si nip
|
|
||||||
etud = models.Identite.query.filter_by(code_nip=str(nip)).first()
|
|
||||||
else: # si etudid
|
|
||||||
etud = models.Identite.query.filter_by(id=etudid).first()
|
|
||||||
|
|
||||||
return etud
|
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",
|
||||||
|
)
|
||||||
|
return query.join(Admission).order_by(desc(Admission.annee)).first()
|
||||||
|
@ -33,6 +33,7 @@ Rappel: pour éviter les confusions, on appelera *poids* les coefficients d'une
|
|||||||
évaluation dans un module, et *coefficients* ceux utilisés pour le calcul de la
|
évaluation dans un module, et *coefficients* ceux utilisés pour le calcul de la
|
||||||
moyenne générale d'une UE.
|
moyenne générale d'une UE.
|
||||||
"""
|
"""
|
||||||
|
import dataclasses
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -54,6 +55,10 @@ class EvaluationEtat:
|
|||||||
nb_attente: int
|
nb_attente: int
|
||||||
is_complete: bool
|
is_complete: bool
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"convert to dict"
|
||||||
|
return dataclasses.asdict(self)
|
||||||
|
|
||||||
|
|
||||||
class ModuleImplResults:
|
class ModuleImplResults:
|
||||||
"""Classe commune à toutes les formations (standard et APC).
|
"""Classe commune à toutes les formations (standard et APC).
|
||||||
@ -236,6 +241,16 @@ class ModuleImplResults:
|
|||||||
self.evals_notes.values > scu.NOTES_ABSENCE, self.evals_notes.values, 0.0
|
self.evals_notes.values > scu.NOTES_ABSENCE, self.evals_notes.values, 0.0
|
||||||
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
||||||
|
|
||||||
|
def get_eval_notes_dict(self, evaluation_id: int) -> dict:
|
||||||
|
"""Notes d'une évaulation, brutes, sous forme d'un dict
|
||||||
|
{ etudid : valeur }
|
||||||
|
avec les valeurs float, ou "ABS" ou EXC
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
etudid: scu.fmt_note(x, keep_numeric=True)
|
||||||
|
for (etudid, x) in self.evals_notes[evaluation_id].items()
|
||||||
|
}
|
||||||
|
|
||||||
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl):
|
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl):
|
||||||
"""L'évaluation de rattrapage de ce module, ou None s'il n'en a pas.
|
"""L'évaluation de rattrapage de ce module, ou None s'il n'en a pas.
|
||||||
Rattrapage: la moyenne du module est la meilleure note entre moyenne
|
Rattrapage: la moyenne du module est la meilleure note entre moyenne
|
||||||
|
@ -426,9 +426,16 @@ class ResultatsSemestre(ResultatsCache):
|
|||||||
# --- TABLEAU RECAP
|
# --- TABLEAU RECAP
|
||||||
|
|
||||||
def get_table_recap(
|
def get_table_recap(
|
||||||
self, convert_values=False, include_evaluations=False, mode_jury=False
|
self,
|
||||||
|
convert_values=False,
|
||||||
|
include_evaluations=False,
|
||||||
|
mode_jury=False,
|
||||||
|
allow_html=True,
|
||||||
):
|
):
|
||||||
"""Result: tuple avec
|
"""Table récap. des résultats.
|
||||||
|
allow_html: si vri, peut-mettre du HTML dans les valeurs
|
||||||
|
|
||||||
|
Result: tuple avec
|
||||||
- rows: liste de dicts { column_id : value }
|
- rows: liste de dicts { column_id : value }
|
||||||
- titles: { column_id : title }
|
- titles: { column_id : title }
|
||||||
- columns_ids: (liste des id de colonnes)
|
- columns_ids: (liste des id de colonnes)
|
||||||
@ -591,7 +598,7 @@ class ResultatsSemestre(ResultatsCache):
|
|||||||
row,
|
row,
|
||||||
f"bonus_ue_{ue.id}",
|
f"bonus_ue_{ue.id}",
|
||||||
f"Bonus {ue.acronyme}",
|
f"Bonus {ue.acronyme}",
|
||||||
val_fmt_html,
|
val_fmt_html if allow_html else val_fmt,
|
||||||
"col_ue_bonus",
|
"col_ue_bonus",
|
||||||
idx,
|
idx,
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
# -*- coding: UTF-8 -*
|
# -*- coding: UTF-8 -*
|
||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
"""ScoDoc models: formsemestre
|
"""ScoDoc models: formsemestre
|
||||||
"""
|
"""
|
||||||
@ -141,8 +146,11 @@ class FormSemestre(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} {self.id} {self.titre_num()}>"
|
return f"<{self.__class__.__name__} {self.id} {self.titre_num()}>"
|
||||||
|
|
||||||
def to_dict(self, convert_parcours=False):
|
def to_dict(self, convert_objects=False) -> dict:
|
||||||
"dict (compatible ScoDoc7)"
|
"""dict (compatible ScoDoc7).
|
||||||
|
If convert_objects, convert all attributes to native types
|
||||||
|
(suitable jor json encoding).
|
||||||
|
"""
|
||||||
d = dict(self.__dict__)
|
d = dict(self.__dict__)
|
||||||
d.pop("_sa_instance_state", None)
|
d.pop("_sa_instance_state", None)
|
||||||
# ScoDoc7 output_formators: (backward compat)
|
# ScoDoc7 output_formators: (backward compat)
|
||||||
@ -160,10 +168,35 @@ class FormSemestre(db.Model):
|
|||||||
d["date_fin"] = d["date_fin_iso"] = ""
|
d["date_fin"] = d["date_fin_iso"] = ""
|
||||||
d["responsables"] = [u.id for u in self.responsables]
|
d["responsables"] = [u.id for u in self.responsables]
|
||||||
d["titre_formation"] = self.titre_formation()
|
d["titre_formation"] = self.titre_formation()
|
||||||
if convert_parcours:
|
if convert_objects:
|
||||||
d["parcours"] = [p.to_dict() for p in self.parcours]
|
d["parcours"] = [p.to_dict() for p in self.parcours]
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def to_dict_api(self):
|
||||||
|
"""
|
||||||
|
Un dict avec les informations sur le semestre destiné à l'api
|
||||||
|
"""
|
||||||
|
d = dict(self.__dict__)
|
||||||
|
d.pop("_sa_instance_state", None)
|
||||||
|
d["annee_scolaire"] = self.annee_scolaire_str()
|
||||||
|
d["formsemestre_id"] = self.id
|
||||||
|
d["titre_num"] = self.titre_num()
|
||||||
|
if self.date_debut:
|
||||||
|
d["date_debut"] = self.date_debut.strftime("%d/%m/%Y")
|
||||||
|
d["date_debut_iso"] = self.date_debut.isoformat()
|
||||||
|
else:
|
||||||
|
d["date_debut"] = d["date_debut_iso"] = ""
|
||||||
|
if self.date_fin:
|
||||||
|
d["date_fin"] = self.date_fin.strftime("%d/%m/%Y")
|
||||||
|
d["date_fin_iso"] = self.date_fin.isoformat()
|
||||||
|
else:
|
||||||
|
d["date_fin"] = d["date_fin_iso"] = ""
|
||||||
|
d["responsables"] = [u.id for u in self.responsables]
|
||||||
|
d["titre_court"] = self.formation.acronyme
|
||||||
|
d["parcours"] = [p.to_dict() for p in self.parcours]
|
||||||
|
d["session_id"] = self.session_id()
|
||||||
|
return d
|
||||||
|
|
||||||
def get_infos_dict(self) -> dict:
|
def get_infos_dict(self) -> dict:
|
||||||
"""Un dict avec des informations sur le semestre
|
"""Un dict avec des informations sur le semestre
|
||||||
pour les bulletins et autres templates
|
pour les bulletins et autres templates
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
# -*- coding: UTF-8 -*
|
# -*- coding: UTF-8 -*
|
||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
"""Groups & partitions
|
"""ScoDoc models: Groups & partitions
|
||||||
"""
|
"""
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.models import SHORT_STR_LEN
|
from app.models import SHORT_STR_LEN
|
||||||
from app.models import GROUPNAME_STR_LEN
|
from app.models import GROUPNAME_STR_LEN
|
||||||
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
class Partition(db.Model):
|
class Partition(db.Model):
|
||||||
@ -41,6 +46,7 @@ class Partition(db.Model):
|
|||||||
"GroupDescr",
|
"GroupDescr",
|
||||||
backref=db.backref("partition", lazy=True),
|
backref=db.backref("partition", lazy=True),
|
||||||
lazy="dynamic",
|
lazy="dynamic",
|
||||||
|
cascade="all, delete-orphan",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@ -56,14 +62,33 @@ class Partition(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"""<{self.__class__.__name__} {self.id} "{self.partition_name or '(default)'}">"""
|
return f"""<{self.__class__.__name__} {self.id} "{self.partition_name or '(default)'}">"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def check_name(
|
||||||
|
cls, formsemestre: "FormSemestre", partition_name: str, existing=False
|
||||||
|
) -> bool:
|
||||||
|
"""check if a partition named 'partition_name' can be created in the given formsemestre.
|
||||||
|
If existing is True, allow a partition_name already existing in the formsemestre.
|
||||||
|
"""
|
||||||
|
if not isinstance(partition_name, str):
|
||||||
|
return False
|
||||||
|
if not len(partition_name.strip()) > 0:
|
||||||
|
return False
|
||||||
|
if (not existing) and (
|
||||||
|
partition_name in [p.partition_name for p in formsemestre.partitions]
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_parcours(self) -> bool:
|
||||||
|
"Vrai s'il s'agit de la partitoon de parcours"
|
||||||
|
return self.partition_name == scu.PARTITION_PARCOURS
|
||||||
|
|
||||||
def to_dict(self, with_groups=False) -> dict:
|
def to_dict(self, with_groups=False) -> dict:
|
||||||
"""as a dict, with or without groups"""
|
"""as a dict, with or without groups"""
|
||||||
d = {
|
d = dict(self.__dict__)
|
||||||
"id": self.id,
|
d.pop("_sa_instance_state", None)
|
||||||
"formsemestre_id": self.partition_id,
|
d.pop("formsemestre", None)
|
||||||
"name": self.partition_name,
|
|
||||||
"numero": self.numero,
|
|
||||||
}
|
|
||||||
if with_groups:
|
if with_groups:
|
||||||
d["groups"] = [group.to_dict(with_partition=False) for group in self.groups]
|
d["groups"] = [group.to_dict(with_partition=False) for group in self.groups]
|
||||||
return d
|
return d
|
||||||
@ -107,6 +132,21 @@ class GroupDescr(db.Model):
|
|||||||
d["partition"] = self.partition.to_dict(with_groups=False)
|
d["partition"] = self.partition.to_dict(with_groups=False)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def check_name(
|
||||||
|
cls, partition: "Partition", group_name: str, existing=False
|
||||||
|
) -> bool:
|
||||||
|
"""check if a group named 'group_name' can be created in the given partition.
|
||||||
|
If existing is True, allow a group_name already existing in the partition.
|
||||||
|
"""
|
||||||
|
if not isinstance(group_name, str):
|
||||||
|
return False
|
||||||
|
if not len(group_name.strip()) > 0:
|
||||||
|
return False
|
||||||
|
if (not existing) and (group_name in [g.group_name for g in partition.groups]):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
group_membership = db.Table(
|
group_membership = db.Table(
|
||||||
"group_membership",
|
"group_membership",
|
||||||
|
@ -79,17 +79,23 @@ class ModuleImpl(db.Model):
|
|||||||
self.module.formation.get_module_coefs(self.module.semestre_id),
|
self.module.formation.get_module_coefs(self.module.semestre_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self, convert_objects=False, with_module=True):
|
||||||
"""as a dict, with the same conversions as in ScoDoc7, including module"""
|
"""as a dict, with the same conversions as in ScoDoc7, including module.
|
||||||
e = dict(self.__dict__)
|
If convert_objects, convert all attributes to native types
|
||||||
e.pop("_sa_instance_state", None)
|
(suitable jor json encoding).
|
||||||
|
"""
|
||||||
|
d = dict(self.__dict__)
|
||||||
|
d.pop("_sa_instance_state", None)
|
||||||
# ScoDoc7 output_formators: (backward compat)
|
# ScoDoc7 output_formators: (backward compat)
|
||||||
e["moduleimpl_id"] = self.id
|
d["moduleimpl_id"] = self.id
|
||||||
e["ens"] = [
|
d["ens"] = [
|
||||||
{"moduleimpl_id": self.id, "ens_id": e.id} for e in self.enseignants
|
{"moduleimpl_id": self.id, "ens_id": e.id} for e in self.enseignants
|
||||||
]
|
]
|
||||||
e["module"] = self.module.to_dict()
|
if with_module:
|
||||||
return e
|
d["module"] = self.module.to_dict(convert_objects=convert_objects)
|
||||||
|
else:
|
||||||
|
d.pop("module", None)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
# Enseignants (chargés de TD ou TP) d'un moduleimpl
|
# Enseignants (chargés de TD ou TP) d'un moduleimpl
|
||||||
|
@ -67,19 +67,33 @@ class Module(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Module{ModuleType(self.module_type or ModuleType.STANDARD).name} id={self.id} code={self.code!r}>"
|
return f"<Module{ModuleType(self.module_type or ModuleType.STANDARD).name} id={self.id} code={self.code!r}>"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self, convert_objects=False, with_matiere=False, with_ue=False) -> dict:
|
||||||
e = dict(self.__dict__)
|
"""If convert_objects, convert all attributes to native types
|
||||||
e.pop("_sa_instance_state", None)
|
(suitable jor json encoding).
|
||||||
|
"""
|
||||||
|
d = dict(self.__dict__)
|
||||||
|
d.pop("_sa_instance_state", None)
|
||||||
|
if convert_objects:
|
||||||
|
d["parcours"] = [p.to_dict() for p in self.parcours]
|
||||||
|
if not with_matiere:
|
||||||
|
d.pop("matiere", None)
|
||||||
|
if not with_ue:
|
||||||
|
d.pop("ue", None)
|
||||||
|
if convert_objects and with_matiere:
|
||||||
|
d["matiere"] = self.matiere.to_dict(convert_objects=True)
|
||||||
|
if convert_objects and with_ue:
|
||||||
|
d["ue"] = self.ue.to_dict(convert_objects=True)
|
||||||
|
|
||||||
# ScoDoc7 output_formators: (backward compat)
|
# ScoDoc7 output_formators: (backward compat)
|
||||||
e["module_id"] = self.id
|
d["module_id"] = self.id
|
||||||
e["heures_cours"] = 0.0 if self.heures_cours is None else self.heures_cours
|
d["heures_cours"] = 0.0 if self.heures_cours is None else self.heures_cours
|
||||||
e["heures_td"] = 0.0 if self.heures_td is None else self.heures_td
|
d["heures_td"] = 0.0 if self.heures_td is None else self.heures_td
|
||||||
e["heures_tp"] = 0.0 if self.heures_tp is None else self.heures_tp
|
d["heures_tp"] = 0.0 if self.heures_tp is None else self.heures_tp
|
||||||
e["numero"] = 0 if self.numero is None else self.numero
|
d["numero"] = 0 if self.numero is None else self.numero
|
||||||
e["coefficient"] = 0.0 if self.coefficient is None else self.coefficient
|
d["coefficient"] = 0.0 if self.coefficient is None else self.coefficient
|
||||||
e["module_type"] = 0 if self.module_type is None else self.module_type
|
d["module_type"] = 0 if self.module_type is None else self.module_type
|
||||||
e["code_apogee"] = e["code_apogee"] or "" # pas de None
|
d["code_apogee"] = d["code_apogee"] or "" # pas de None
|
||||||
return e
|
return d
|
||||||
|
|
||||||
def is_apc(self):
|
def is_apc(self):
|
||||||
"True si module SAÉ ou Ressource"
|
"True si module SAÉ ou Ressource"
|
||||||
@ -220,6 +234,14 @@ class ModuleUECoef(db.Model):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def to_dict(self, convert_objects=False) -> dict:
|
||||||
|
"""If convert_objects, convert all attributes to native types
|
||||||
|
(suitable for json encoding).
|
||||||
|
"""
|
||||||
|
d = dict(self.__dict__)
|
||||||
|
d.pop("_sa_instance_state", None)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
class NotesTag(db.Model):
|
class NotesTag(db.Model):
|
||||||
"""Tag sur un module"""
|
"""Tag sur un module"""
|
||||||
|
@ -47,6 +47,12 @@ class NotesNotes(db.Model):
|
|||||||
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
uid = db.Column(db.Integer, db.ForeignKey("user.id"))
|
uid = db.Column(db.Integer, db.ForeignKey("user.id"))
|
||||||
|
|
||||||
|
def to_dict(self) -> dict:
|
||||||
|
"dict"
|
||||||
|
d = dict(self.__dict__)
|
||||||
|
d.pop("_sa_instance_state", None)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
class NotesNotesLog(db.Model):
|
class NotesNotesLog(db.Model):
|
||||||
"""Historique des modifs sur notes (anciennes entrees de notes_notes)"""
|
"""Historique des modifs sur notes (anciennes entrees de notes_notes)"""
|
||||||
|
@ -59,18 +59,25 @@ class UniteEns(db.Model):
|
|||||||
self.semestre_idx} {
|
self.semestre_idx} {
|
||||||
'EXTERNE' if self.is_external else ''})>"""
|
'EXTERNE' if self.is_external else ''})>"""
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self, convert_objects=False):
|
||||||
"""as a dict, with the same conversions as in ScoDoc7
|
"""as a dict, with the same conversions as in ScoDoc7
|
||||||
(except ECTS: keep None)
|
(except ECTS: keep None)
|
||||||
|
If convert_objects, convert all attributes to native types
|
||||||
|
(suitable jor json encoding).
|
||||||
"""
|
"""
|
||||||
e = dict(self.__dict__)
|
e = dict(self.__dict__)
|
||||||
e.pop("_sa_instance_state", None)
|
e.pop("_sa_instance_state", None)
|
||||||
|
e.pop("evaluation_ue_poids", None)
|
||||||
# ScoDoc7 output_formators
|
# ScoDoc7 output_formators
|
||||||
e["ue_id"] = self.id
|
e["ue_id"] = self.id
|
||||||
e["numero"] = e["numero"] if e["numero"] else 0
|
e["numero"] = e["numero"] if e["numero"] else 0
|
||||||
e["ects"] = e["ects"]
|
e["ects"] = e["ects"]
|
||||||
e["coefficient"] = e["coefficient"] if e["coefficient"] else 0.0
|
e["coefficient"] = e["coefficient"] if e["coefficient"] else 0.0
|
||||||
e["code_apogee"] = e["code_apogee"] or "" # pas de None
|
e["code_apogee"] = e["code_apogee"] or "" # pas de None
|
||||||
|
if convert_objects:
|
||||||
|
e["module_ue_coefs"] = [
|
||||||
|
c.to_dict(convert_objects=True) for c in self.module_ue_coefs
|
||||||
|
]
|
||||||
return e
|
return e
|
||||||
|
|
||||||
def is_locked(self):
|
def is_locked(self):
|
||||||
|
@ -131,12 +131,14 @@ class EvaluationCache(ScoDocCache):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def invalidate_sem(cls, formsemestre_id):
|
def invalidate_sem(cls, formsemestre_id):
|
||||||
"delete evaluations in this formsemestre from cache"
|
"delete evaluations in this formsemestre from cache"
|
||||||
req = """SELECT e.id
|
from app.models.evaluations import Evaluation
|
||||||
FROM notes_formsemestre s, notes_evaluation e, notes_moduleimpl m
|
from app.models.moduleimpls import ModuleImpl
|
||||||
WHERE s.id = %(formsemestre_id)s and s.id=m.formsemestre_id and e.moduleimpl_id=m.id;
|
|
||||||
"""
|
|
||||||
evaluation_ids = [
|
evaluation_ids = [
|
||||||
x[0] for x in ndb.SimpleQuery(req, {"formsemestre_id": formsemestre_id})
|
e.id
|
||||||
|
for e in Evaluation.query.join(ModuleImpl).filter_by(
|
||||||
|
formsemestre_id=formsemestre_id
|
||||||
|
)
|
||||||
]
|
]
|
||||||
cls.delete_many(evaluation_ids)
|
cls.delete_many(evaluation_ids)
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- mode: python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
@ -27,15 +26,15 @@
|
|||||||
|
|
||||||
"""Gestion des cursus (jurys suivant la formation)
|
"""Gestion des cursus (jurys suivant la formation)
|
||||||
"""
|
"""
|
||||||
|
from sqlalchemy.sql import text
|
||||||
|
|
||||||
|
from app import db
|
||||||
from app.but import cursus_but
|
from app.but import cursus_but
|
||||||
from app.scodoc import sco_cursus_dut
|
from app.scodoc import sco_cursus_dut
|
||||||
|
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc import sco_formations
|
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
|
|
||||||
# SituationEtudParcours -> get_situation_etud_cursus
|
# SituationEtudParcours -> get_situation_etud_cursus
|
||||||
@ -111,24 +110,26 @@ def list_formsemestre_utilisateurs_uecap(formsemestre_id):
|
|||||||
"""Liste des formsemestres pouvant utiliser une UE capitalisee de ce semestre
|
"""Liste des formsemestres pouvant utiliser une UE capitalisee de ce semestre
|
||||||
(et qui doivent donc etre sortis du cache si l'on modifie ce
|
(et qui doivent donc etre sortis du cache si l'on modifie ce
|
||||||
semestre): meme code formation, meme semestre_id, date posterieure"""
|
semestre): meme code formation, meme semestre_id, date posterieure"""
|
||||||
cnx = ndb.GetDBConnexion()
|
formsemestre = FormSemestre.query.get(formsemestre_id)
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
cursor = db.session.execute(
|
||||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
text(
|
||||||
cursor.execute(
|
"""
|
||||||
"""SELECT sem.id
|
SELECT sem.id
|
||||||
FROM notes_formsemestre sem, notes_formations F
|
FROM notes_formsemestre sem, notes_formations F
|
||||||
WHERE sem.formation_id = F.id
|
WHERE sem.formation_id = F.id
|
||||||
and F.formation_code = %(formation_code)s
|
and F.formation_code = :formation_code
|
||||||
and sem.semestre_id = %(semestre_id)s
|
and sem.semestre_id = :semestre_id
|
||||||
and sem.date_debut >= %(date_debut)s
|
and sem.date_debut >= :date_debut
|
||||||
and sem.id != %(formsemestre_id)s;
|
and sem.id != :formsemestre_id;
|
||||||
""",
|
"""
|
||||||
|
),
|
||||||
{
|
{
|
||||||
"formation_code": F["formation_code"],
|
"formation_code": formsemestre.formation.formation_code,
|
||||||
"semestre_id": sem["semestre_id"],
|
"semestre_id": formsemestre.semestre_id,
|
||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
"date_debut": formsemestre.date_debut,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return [x[0] for x in cursor.fetchall()]
|
|
||||||
|
return [x[0] for x in cursor]
|
||||||
|
@ -136,7 +136,7 @@ def get_partition(partition_id):
|
|||||||
return r[0]
|
return r[0]
|
||||||
|
|
||||||
|
|
||||||
def get_partitions_list(formsemestre_id, with_default=True):
|
def get_partitions_list(formsemestre_id, with_default=True) -> list[dict]:
|
||||||
"""Liste des partitions pour ce semestre (list of dicts)"""
|
"""Liste des partitions pour ce semestre (list of dicts)"""
|
||||||
partitions = ndb.SimpleDictFetch(
|
partitions = ndb.SimpleDictFetch(
|
||||||
"""SELECT p.id AS partition_id, p.*
|
"""SELECT p.id AS partition_id, p.*
|
||||||
@ -146,9 +146,9 @@ def get_partitions_list(formsemestre_id, with_default=True):
|
|||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
)
|
)
|
||||||
# Move 'all' at end of list (for menus)
|
# Move 'all' at end of list (for menus)
|
||||||
R = [p for p in partitions if p["partition_name"] != None]
|
R = [p for p in partitions if p["partition_name"] is not None]
|
||||||
if with_default:
|
if with_default:
|
||||||
R += [p for p in partitions if p["partition_name"] == None]
|
R += [p for p in partitions if p["partition_name"] is None]
|
||||||
return R
|
return R
|
||||||
|
|
||||||
|
|
||||||
@ -179,6 +179,24 @@ def get_formsemestre_groups(formsemestre_id, with_default=False):
|
|||||||
return partitions, partitions_etud_groups
|
return partitions, partitions_etud_groups
|
||||||
|
|
||||||
|
|
||||||
|
def get_formsemestre_etuds_groups(formsemestre_id: int) -> dict:
|
||||||
|
"""{ etudid : { partition_id : group_id } }"""
|
||||||
|
infos = ndb.SimpleDictFetch(
|
||||||
|
"""SELECT etudid, p.id AS partition_id, gd.id AS group_id
|
||||||
|
FROM group_descr gd, group_membership gm, partition p
|
||||||
|
WHERE gd.partition_id = p.id
|
||||||
|
AND gm.group_id = gd.id
|
||||||
|
AND p.formsemestre_id = %(formsemestre_id)s
|
||||||
|
""",
|
||||||
|
{"formsemestre_id": formsemestre_id},
|
||||||
|
)
|
||||||
|
# -> {'etudid': 16483, 'group_id': 5317, 'partition_id': 2264},
|
||||||
|
d = collections.defaultdict(lambda: {})
|
||||||
|
for i in infos:
|
||||||
|
d[i["etudid"]][i["partition_id"]] = i["group_id"]
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
def get_partition_groups(partition):
|
def get_partition_groups(partition):
|
||||||
"""List of groups in this partition (list of dicts).
|
"""List of groups in this partition (list of dicts).
|
||||||
Some groups may be empty."""
|
Some groups may be empty."""
|
||||||
|
@ -51,7 +51,7 @@ _SCO_PERMISSIONS = (
|
|||||||
# 27 à 39 ... réservé pour "entreprises"
|
# 27 à 39 ... réservé pour "entreprises"
|
||||||
# Api scodoc9
|
# Api scodoc9
|
||||||
(1 << 40, "APIView", "API: Lecture"),
|
(1 << 40, "APIView", "API: Lecture"),
|
||||||
(1 << 41, "APIEtudChangeGroups", "API: Modifier les groupes"),
|
(1 << 41, "APIEditGroups", "API: Modifier les groupes"),
|
||||||
(1 << 42, "APIEditAllNotes", "API: Modifier toutes les notes"),
|
(1 << 42, "APIEditAllNotes", "API: Modifier toutes les notes"),
|
||||||
(1 << 43, "APIAbsChange", "API: Saisir des absences"),
|
(1 << 43, "APIAbsChange", "API: Saisir des absences"),
|
||||||
)
|
)
|
||||||
|
@ -1893,6 +1893,8 @@ class BasePreferences(object):
|
|||||||
# log(f"loading preferences for dept_id={self.dept_id}")
|
# log(f"loading preferences for dept_id={self.dept_id}")
|
||||||
|
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
|
if self.dept_id:
|
||||||
|
g.scodoc_dept_id = self.dept_id
|
||||||
preflist = self._editor.list(cnx, {"dept_id": self.dept_id})
|
preflist = self._editor.list(cnx, {"dept_id": self.dept_id})
|
||||||
self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } }
|
self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } }
|
||||||
self.default = {} # { name : default_value }
|
self.default = {} # { name : default_value }
|
||||||
|
@ -65,6 +65,8 @@ class DevConfig(Config):
|
|||||||
os.environ.get("SCODOC_DATABASE_URI") or "postgresql:///SCODOC_DEV"
|
os.environ.get("SCODOC_DATABASE_URI") or "postgresql:///SCODOC_DEV"
|
||||||
)
|
)
|
||||||
SECRET_KEY = os.environ.get("DEV_SECRET_KEY") or "bb3faec7d9a34eb68a8e3e710087d87a"
|
SECRET_KEY = os.environ.get("DEV_SECRET_KEY") or "bb3faec7d9a34eb68a8e3e710087d87a"
|
||||||
|
# pour le avoir url_for dans le shell:
|
||||||
|
# SERVER_NAME = os.environ.get("SCODOC_TEST_SERVER_NAME") or "localhost"
|
||||||
|
|
||||||
|
|
||||||
class TestConfig(DevConfig):
|
class TestConfig(DevConfig):
|
||||||
|
@ -20,6 +20,7 @@ Travail en cours.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
import urllib3
|
import urllib3
|
||||||
@ -35,8 +36,13 @@ 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.get("SCODOC_URL") or "http://localhost:5000"
|
SCODOC_URL = os.environ.get("SCODOC_URL") or "http://localhost:5000"
|
||||||
API_URL = SCODOC_URL + "/ScoDoc/api"
|
API_URL = SCODOC_URL + "/ScoDoc/api"
|
||||||
|
# Admin:
|
||||||
SCODOC_USER = os.environ["SCODOC_USER"]
|
SCODOC_USER = os.environ["SCODOC_USER"]
|
||||||
SCODOC_PASSWORD = os.environ["SCODOC_PASSWORD"]
|
SCODOC_PASSWORD = os.environ["SCODOC_PASSWORD"]
|
||||||
|
# Lecteur
|
||||||
|
SCODOC_USER_API_LECTEUR = os.environ["SCODOC_USER_API_LECTEUR"]
|
||||||
|
SCODOC_PASSWORD_API_LECTEUR = os.environ["SCODOC_PASSWORD_API_LECTEUR"]
|
||||||
|
|
||||||
print(f"SCODOC_URL={SCODOC_URL}")
|
print(f"SCODOC_URL={SCODOC_URL}")
|
||||||
print(f"API URL={API_URL}")
|
print(f"API URL={API_URL}")
|
||||||
|
|
||||||
@ -51,25 +57,48 @@ class ScoError(Exception):
|
|||||||
|
|
||||||
def GET(path: str, headers={}, errmsg=None):
|
def GET(path: str, headers={}, errmsg=None):
|
||||||
"""Get and returns as JSON"""
|
"""Get and returns as JSON"""
|
||||||
r = requests.get(API_URL + "/" + path, headers=headers or HEADERS, verify=CHK_CERT)
|
r = requests.get(API_URL + path, headers=headers or HEADERS, verify=CHK_CERT)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
raise ScoError(errmsg or "erreur !")
|
raise ScoError(errmsg or f"erreur status={r.status_code} !")
|
||||||
return r.json() # decode la reponse JSON
|
return r.json() # decode la reponse JSON
|
||||||
|
|
||||||
|
|
||||||
def POST(s, path: str, data: dict, errmsg=None):
|
def POST(path: str, data: dict = {}, headers={}, errmsg=None):
|
||||||
"""Post"""
|
"""Post"""
|
||||||
r = s.post(API_URL + "/" + path, data=data, verify=CHK_CERT)
|
r = requests.post(
|
||||||
|
API_URL + path,
|
||||||
|
data=data,
|
||||||
|
headers=headers or HEADERS,
|
||||||
|
verify=CHK_CERT,
|
||||||
|
)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
raise ScoError(errmsg or "erreur !")
|
raise ScoError(errmsg or f"erreur status={r.status_code} !")
|
||||||
return r.text
|
return r.json() # decode la reponse JSON
|
||||||
|
|
||||||
|
|
||||||
# --- Obtention du jeton (token)
|
def POST_JSON(path: str, data: dict = {}, headers={}, errmsg=None):
|
||||||
r = requests.post(API_URL + "/tokens", auth=(SCODOC_USER, SCODOC_PASSWORD))
|
"""Post"""
|
||||||
assert r.status_code == 200
|
r = requests.post(
|
||||||
token = r.json()["token"]
|
API_URL + path,
|
||||||
HEADERS = {"Authorization": f"Bearer {token}"}
|
json=data,
|
||||||
|
headers=headers or HEADERS,
|
||||||
|
verify=CHK_CERT,
|
||||||
|
)
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise ScoError(errmsg or f"erreur status={r.status_code} !")
|
||||||
|
return r.json() # decode la reponse JSON
|
||||||
|
|
||||||
|
|
||||||
|
def GET_TOKEN(user, password):
|
||||||
|
"Obtention du jeton (token)"
|
||||||
|
r = requests.post(API_URL + "/tokens", auth=(user, password))
|
||||||
|
assert r.status_code == 200
|
||||||
|
token = r.json()["token"]
|
||||||
|
return {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
|
||||||
|
HEADERS = GET_TOKEN(SCODOC_USER, SCODOC_PASSWORD)
|
||||||
|
HEADERS_USER = GET_TOKEN(SCODOC_USER_API_LECTEUR, SCODOC_PASSWORD_API_LECTEUR)
|
||||||
|
|
||||||
r = requests.get(API_URL + "/departements", headers=HEADERS, verify=CHK_CERT)
|
r = requests.get(API_URL + "/departements", headers=HEADERS, verify=CHK_CERT)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
@ -113,8 +142,52 @@ print("\n".join([s["titre_num"] for s in sems]))
|
|||||||
# Evaluation
|
# Evaluation
|
||||||
evals = GET("/evaluations/1")
|
evals = GET("/evaluations/1")
|
||||||
|
|
||||||
# # --- Recupere la liste de tous les semestres:
|
# Partitions d'un BUT
|
||||||
# sems = GET(s, "Notes/formsemestre_list?format=json", "Aucun semestre !")
|
formsemestre_id = 1063 # A adapter
|
||||||
|
partitions = GET(f"/formsemestre/{formsemestre_id}/partitions")
|
||||||
|
print(partitions)
|
||||||
|
pid = partitions[1]["id"]
|
||||||
|
partition = GET(f"/partition/{pid}")
|
||||||
|
print(partition)
|
||||||
|
group_id = partition["groups"][0]["id"]
|
||||||
|
etuds = GET(f"/group/{group_id}/etudiants")
|
||||||
|
print(f"{len(etuds)} étudiants")
|
||||||
|
pp(etuds[1])
|
||||||
|
|
||||||
|
etuds_dem = GET(f"/group/{group_id}/etudiants/query?etat=D")
|
||||||
|
print(f"{len(etuds_dem)} étudiants")
|
||||||
|
|
||||||
|
etudid = 16650
|
||||||
|
group_id = 5315
|
||||||
|
POST(f"/group/{group_id}/set_etudiant/{etudid}")
|
||||||
|
|
||||||
|
|
||||||
|
POST_JSON(f"/partition/{pid}/group/create", data={"group_name": "Omega10"})
|
||||||
|
partitions = GET(f"/formsemestre/{formsemestre_id}/partitions")
|
||||||
|
pp(partitions)
|
||||||
|
|
||||||
|
POST_JSON(f"/group/5559/delete")
|
||||||
|
POST_JSON(f"/group/5327/edit", data={"group_name": "TDXXX"})
|
||||||
|
|
||||||
|
POST_JSON(
|
||||||
|
f"/formsemestre/{formsemestre_id}/partition/create",
|
||||||
|
data={"partition_name": "PXXXXYY"},
|
||||||
|
)
|
||||||
|
|
||||||
|
POST_JSON(
|
||||||
|
f"/partition/{2379}/edit",
|
||||||
|
data={"partition_name": "---PPPP", "show_in_lists": True},
|
||||||
|
)
|
||||||
|
|
||||||
|
POST_JSON(f"/partition/{2379}/delete")
|
||||||
|
|
||||||
|
# Recherche de formsemestres
|
||||||
|
sems = GET(f"/formsemestres/query?etape_apo=V1RT&annee_scolaire=2021")
|
||||||
|
|
||||||
|
# Table récap:
|
||||||
|
pp(GET(f"/formsemestre/1063/resultats")[0])
|
||||||
|
|
||||||
|
pp(GET(f"/formsemestre/880/resultats")[0])
|
||||||
|
|
||||||
# # sems est une liste de semestres (dictionnaires)
|
# # sems est une liste de semestres (dictionnaires)
|
||||||
# for sem in sems:
|
# for sem in sems:
|
||||||
|
@ -21,13 +21,22 @@ import requests
|
|||||||
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
||||||
|
|
||||||
# Etudiant pour les tests
|
# Etudiant pour les tests
|
||||||
|
from tests.api.tools_test_api import (
|
||||||
|
verify_fields,
|
||||||
|
ABSENCES_FIELDS,
|
||||||
|
ABSENCES_GROUP_ETAT_FIELDS,
|
||||||
|
)
|
||||||
|
|
||||||
ETUDID = 1
|
ETUDID = 1
|
||||||
|
|
||||||
|
|
||||||
# absences
|
# absences
|
||||||
def test_absences(api_headers):
|
def test_absences(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /absences/etudid/<int:etudid>
|
Test 'absences'
|
||||||
|
|
||||||
|
Route :
|
||||||
|
- /absences/etudid/<int:etudid>
|
||||||
"""
|
"""
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/absences/etudid/{ETUDID}",
|
f"{API_URL}/absences/etudid/{ETUDID}",
|
||||||
@ -35,29 +44,165 @@ def test_absences(api_headers):
|
|||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
absences = r.json()
|
||||||
|
|
||||||
|
assert isinstance(absences, list)
|
||||||
|
for abs in absences:
|
||||||
|
assert verify_fields(abs, ABSENCES_FIELDS) is True
|
||||||
|
assert isinstance(abs["jour"], str)
|
||||||
|
assert isinstance(abs["matin"], bool)
|
||||||
|
assert isinstance(abs["estabs"], bool)
|
||||||
|
assert isinstance(abs["estjust"], bool)
|
||||||
|
assert isinstance(abs["description"], str)
|
||||||
|
assert isinstance(abs["begin"], str)
|
||||||
|
assert isinstance(abs["end"], str)
|
||||||
|
|
||||||
|
assert abs["begin"] < abs["end"]
|
||||||
|
|
||||||
|
|
||||||
# absences_justify
|
# absences_justify
|
||||||
def test_absences_justify(api_headers):
|
def test_absences_justify(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /absences/etudid/<etudid:int>/just
|
Test 'absences_just'
|
||||||
|
|
||||||
|
Route :
|
||||||
|
- /absences/etudid/<int:etudid>/just
|
||||||
"""
|
"""
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + f"/absences/etudid/{ETUDID}/just",
|
f"{API_URL}/absences/etudid/{ETUDID}/just",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
# TODO vérifier résultat
|
absences = r.json()
|
||||||
|
|
||||||
|
assert isinstance(absences, list)
|
||||||
|
for abs in absences:
|
||||||
|
assert verify_fields(abs, ABSENCES_FIELDS) is True
|
||||||
|
assert isinstance(abs["jour"], str)
|
||||||
|
assert isinstance(abs["matin"], bool)
|
||||||
|
assert isinstance(abs["estabs"], bool)
|
||||||
|
assert isinstance(abs["estjust"], bool)
|
||||||
|
assert isinstance(abs["description"], str)
|
||||||
|
assert isinstance(abs["begin"], str)
|
||||||
|
assert isinstance(abs["end"], str)
|
||||||
|
|
||||||
|
assert abs["begin"] < abs["end"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_abs_groupe_etat(api_headers):
|
||||||
|
"""
|
||||||
|
Test 'abs_groupe_etat'
|
||||||
|
|
||||||
|
Routes :
|
||||||
|
- /absences/abs_group_etat/<int:group_id>
|
||||||
|
- /absences/abs_group_etat/group_id/<int:group_id>/date_debut/<string:date_debut>/date_fin/<string:date_fin>
|
||||||
|
"""
|
||||||
|
group_id = 1
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/absences/abs_group_etat/{group_id}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
list_absences = r.json()
|
||||||
|
|
||||||
|
assert isinstance(list_absences, list)
|
||||||
|
list_id_etu = []
|
||||||
|
for etu in list_absences:
|
||||||
|
list_id_etu.append(etu["etudid"])
|
||||||
|
assert verify_fields(etu, ABSENCES_GROUP_ETAT_FIELDS) is True
|
||||||
|
assert isinstance(etu["etudid"], int)
|
||||||
|
assert isinstance(etu["list_abs"], list)
|
||||||
|
|
||||||
|
list_abs = etu["list_abs"]
|
||||||
|
for abs in list_abs:
|
||||||
|
assert verify_fields(abs, ABSENCES_FIELDS) is True
|
||||||
|
assert isinstance(abs["jour"], str)
|
||||||
|
assert isinstance(abs["matin"], bool)
|
||||||
|
assert isinstance(abs["estabs"], bool)
|
||||||
|
assert isinstance(abs["estjust"], bool)
|
||||||
|
assert isinstance(abs["description"], str)
|
||||||
|
assert isinstance(abs["begin"], str)
|
||||||
|
assert isinstance(abs["end"], str)
|
||||||
|
|
||||||
|
assert abs["begin"] < abs["end"]
|
||||||
|
|
||||||
|
all_unique = True
|
||||||
|
for id in list_id_etu:
|
||||||
|
if list_id_etu.count(id) > 1:
|
||||||
|
all_unique = False
|
||||||
|
assert all_unique is True
|
||||||
|
|
||||||
|
date_debut = "Fri, 15 Apr 2021 00:00:00 GMT"
|
||||||
|
date_fin = "Fri, 18 Apr 2022 00:00:00 GMT"
|
||||||
|
|
||||||
|
r1 = requests.get(
|
||||||
|
f"{API_URL}/absences/abs_group_etat/group_id/{group_id}/date_debut/{date_debut}/date_fin/{date_fin}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r1.status_code == 200
|
||||||
|
|
||||||
|
list_absences1 = r.json()
|
||||||
|
|
||||||
|
assert isinstance(list_absences1, list)
|
||||||
|
list_id_etu1 = []
|
||||||
|
for etu in list_absences1:
|
||||||
|
list_id_etu1.append(etu["etudid"])
|
||||||
|
assert verify_fields(etu, ABSENCES_GROUP_ETAT_FIELDS) is True
|
||||||
|
assert isinstance(etu["etudid"], int)
|
||||||
|
assert isinstance(etu["list_abs"], list)
|
||||||
|
|
||||||
|
list_abs1 = etu["list_abs"]
|
||||||
|
for abs in list_abs1:
|
||||||
|
assert verify_fields(abs, ABSENCES_FIELDS) is True
|
||||||
|
assert isinstance(abs["jour"], str)
|
||||||
|
assert isinstance(abs["matin"], bool)
|
||||||
|
assert isinstance(abs["estabs"], bool)
|
||||||
|
assert isinstance(abs["estjust"], bool)
|
||||||
|
assert isinstance(abs["description"], str)
|
||||||
|
assert isinstance(abs["begin"], str)
|
||||||
|
assert isinstance(abs["end"], str)
|
||||||
|
|
||||||
|
assert abs["begin"] < abs["end"]
|
||||||
|
|
||||||
|
all_unique1 = True
|
||||||
|
for id in list_id_etu1:
|
||||||
|
if list_id_etu1.count(id) > 1:
|
||||||
|
all_unique1 = False
|
||||||
|
assert all_unique1 is True
|
||||||
|
|
||||||
|
|
||||||
# XXX TODO
|
# XXX TODO
|
||||||
# def test_abs_groupe_etat(api_headers):
|
# def reset_etud_abs(api_headers):
|
||||||
# """
|
# """
|
||||||
# Route:
|
# Test 'reset_etud_abs'
|
||||||
|
#
|
||||||
|
# Routes :
|
||||||
|
# - /absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs
|
||||||
|
# - /absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_not_just
|
||||||
|
# - /absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_just
|
||||||
# """
|
# """
|
||||||
|
# list_abs = []
|
||||||
# r = requests.get(
|
# r = requests.get(
|
||||||
# API_URL + "/absences/abs_group_etat/?group_id=<int:group_id>&date_debut=date_debut&date_fin=date_fin",
|
# f"{API_URL}/absences/etudid/{ETUDID}/list_abs/{list_abs}/reset_etud_abs",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
#
|
||||||
|
# r_only_not_just = requests.get(
|
||||||
|
# f"{API_URL}/absences/etudid/{ETUDID}/list_abs/{list_abs}/reset_etud_abs/only_not_just",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# r_only_just = requests.get(
|
||||||
|
# f"{API_URL}/absences/etudid/{ETUDID}/list_abs/{list_abs}/reset_etud_abs/only_just",
|
||||||
# headers=api_headers,
|
# headers=api_headers,
|
||||||
# verify=CHECK_CERTIFICATE,
|
# verify=CHECK_CERTIFICATE,
|
||||||
# )
|
# )
|
||||||
|
@ -19,29 +19,20 @@ Utilisation :
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.api.setup_test_api import (
|
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
||||||
API_URL,
|
from tests.api.tools_test_api import (
|
||||||
CHECK_CERTIFICATE,
|
verify_fields,
|
||||||
DEPT_ACRONYM,
|
DEPARTEMENT_FIELDS,
|
||||||
api_headers,
|
FORMSEMESTRE_FIELDS,
|
||||||
|
verify_occurences_ids_etus,
|
||||||
)
|
)
|
||||||
from tests.api.tools_test_api import verify_fields
|
|
||||||
|
|
||||||
DEPARTEMENT_FIELDS = [
|
|
||||||
"id",
|
|
||||||
"acronym",
|
|
||||||
"description",
|
|
||||||
"visible",
|
|
||||||
"date_creation",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def test_departements(api_headers):
|
def test_departements(api_headers):
|
||||||
""" "
|
|
||||||
Routes: /departements_ids, /departement, /departement/<string:dept>/formsemestres_ids
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# --- Liste des ids
|
Routes: /departements_ids, /departement, /departement/<string:dept>/formsemestres_ids
|
||||||
|
"""
|
||||||
|
# --- departement_ids : liste des ids
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/departements_ids",
|
API_URL + "/departements_ids",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
@ -53,8 +44,17 @@ def test_departements(api_headers):
|
|||||||
assert len(departements_ids) > 0
|
assert len(departements_ids) > 0
|
||||||
assert all(isinstance(x, int) for x in departements_ids)
|
assert all(isinstance(x, int) for x in departements_ids)
|
||||||
|
|
||||||
|
all_unique = True
|
||||||
|
for id in departements_ids:
|
||||||
|
if departements_ids.count(id) > 1:
|
||||||
|
all_unique = False
|
||||||
|
|
||||||
|
assert all_unique is True
|
||||||
|
|
||||||
dept_id = departements_ids[0]
|
dept_id = departements_ids[0]
|
||||||
# --- Infos sur un département, accès par id
|
|
||||||
|
# --- departement
|
||||||
|
# Infos sur un département, accès par id
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/departement/{dept_id}",
|
f"{API_URL}/departement/{dept_id}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
@ -62,8 +62,7 @@ def test_departements(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
dept_a = r.json()
|
dept_a = r.json()
|
||||||
assert verify_fields(dept_a, DEPARTEMENT_FIELDS) is True
|
# Infos sur un département, accès par acronyme4
|
||||||
# --- Infos sur un département, accès par acronyme4
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/departement/{dept_a['acronym']}",
|
f"{API_URL}/departement/{dept_a['acronym']}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
@ -71,65 +70,131 @@ def test_departements(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
dept_b = r.json()
|
dept_b = r.json()
|
||||||
assert dept_a == dept_b
|
|
||||||
|
|
||||||
# Liste des formsemestres
|
assert dept_a == dept_b
|
||||||
|
assert verify_fields(dept_a, DEPARTEMENT_FIELDS) is True
|
||||||
|
assert isinstance(dept_a["id"], int)
|
||||||
|
assert isinstance(dept_a["acronym"], str)
|
||||||
|
assert dept_a["description"] is None or isinstance(dept_a["description"], str)
|
||||||
|
assert isinstance(dept_a["visible"], bool)
|
||||||
|
assert dept_a["date_creation"] is None or isinstance(dept_a["date_creation"], str)
|
||||||
|
|
||||||
|
# --- departements : Liste des départements
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/departements",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
# --- formsemestre_ids : listes des ids de formsemestres du département
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/departement/{dept_a['acronym']}/formsemestres_ids",
|
f"{API_URL}/departement/{dept_a['acronym']}/formsemestres_ids",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
dept_ids = r.json()
|
dept_ids_a = r.json()
|
||||||
assert isinstance(dept_ids, list)
|
|
||||||
assert all(isinstance(x, int) for x in dept_ids)
|
r = requests.get(
|
||||||
assert len(dept_ids) > 0
|
f"{API_URL}/departement/{dept_a['id']}/formsemestres_ids",
|
||||||
assert dept_id in dept_ids
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
dept_ids_b = r.json()
|
||||||
|
|
||||||
|
assert dept_ids_a == dept_ids_b
|
||||||
|
assert isinstance(dept_ids_a, list)
|
||||||
|
assert all(isinstance(id, int) for id in dept_ids_a)
|
||||||
|
assert len(dept_ids_a) > 0
|
||||||
|
assert dept_id in dept_ids_a
|
||||||
|
|
||||||
|
# Les erreurs
|
||||||
|
id_inexistant = 50000
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/departement/{id_inexistant}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/departement/{id_inexistant}/formsemestres_ids",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
acronym_inexistant = "AAAAAAAAAAAAAAAAAAA"
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/departement/{acronym_inexistant}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/departement/{acronym_inexistant}/formsemestres_ids",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_list_etudiants(api_headers):
|
def test_list_etudiants(api_headers):
|
||||||
fields = {"id", "nip", "ine", "nom", "nom_usuel", "prenom", "civilite"}
|
fields = {"id", "nip", "ine", "nom", "nom_usuel", "prenom", "civilite"}
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/departement/{DEPT_ACRONYM}/etudiants",
|
API_URL + "/departement/TAPI/etudiants",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud = r.json()[0]
|
etud_a = r.json()[0]
|
||||||
assert verify_fields(etud, fields) is True
|
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/departement/1/etudiants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
etud_b = r.json()[0]
|
||||||
|
|
||||||
|
assert etud_a == etud_b
|
||||||
|
assert verify_fields(etud_a, fields) is True
|
||||||
|
assert isinstance(etud_a["id"], int)
|
||||||
|
assert etud_a["nip"] is None or isinstance(etud_a["nip"], str)
|
||||||
|
assert etud_a["ine"] is None or isinstance(etud_a["ine"], str)
|
||||||
|
assert etud_a["nom"] is None or isinstance(etud_a["nom"], str)
|
||||||
|
assert etud_a["nom_usuel"] is None or isinstance(etud_a["nom_usuel"], str)
|
||||||
|
assert etud_a["prenom"] is None or isinstance(etud_a["prenom"], str)
|
||||||
|
assert isinstance(etud_a["civilite"], str)
|
||||||
|
assert len(etud_a["civilite"]) == 1
|
||||||
|
|
||||||
|
all_unique = verify_occurences_ids_etus(r.text)
|
||||||
|
assert all_unique is True
|
||||||
|
|
||||||
|
# Les erreurs
|
||||||
|
id_inexistant = 50000
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/departement/{id_inexistant}/etudiants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
acronym_inexistant = "AAAAAAAAAAAAAAAAAAA"
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/departement/{acronym_inexistant}/etudiants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
# liste_semestres_courant
|
# liste_semestres_courant
|
||||||
def test_semestres_courant(api_headers):
|
def test_semestres_courant(api_headers):
|
||||||
fields = [
|
|
||||||
"titre",
|
|
||||||
"gestion_semestrielle",
|
|
||||||
"scodoc7_id",
|
|
||||||
"date_debut",
|
|
||||||
"bul_bgcolor",
|
|
||||||
"date_fin",
|
|
||||||
"resp_can_edit",
|
|
||||||
"dept_id",
|
|
||||||
"etat",
|
|
||||||
"resp_can_change_ens",
|
|
||||||
"id",
|
|
||||||
"modalite",
|
|
||||||
"ens_can_edit_eval",
|
|
||||||
"formation_id",
|
|
||||||
"gestion_compensation",
|
|
||||||
"elt_sem_apo",
|
|
||||||
"semestre_id",
|
|
||||||
"bul_hide_xml",
|
|
||||||
"elt_annee_apo",
|
|
||||||
"block_moyennes",
|
|
||||||
"formsemestre_id",
|
|
||||||
"titre_num",
|
|
||||||
"titre_formation",
|
|
||||||
"date_debut_iso",
|
|
||||||
"date_fin_iso",
|
|
||||||
"responsables",
|
|
||||||
]
|
|
||||||
dept_id = 1
|
dept_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/departement/{dept_id}",
|
f"{API_URL}/departement/{dept_id}",
|
||||||
@ -139,6 +204,7 @@ def test_semestres_courant(api_headers):
|
|||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
dept = r.json()
|
dept = r.json()
|
||||||
assert dept["id"] == dept_id
|
assert dept["id"] == dept_id
|
||||||
|
|
||||||
# Accès via acronyme
|
# Accès via acronyme
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/departement/{dept['acronym']}/formsemestres_courants",
|
f"{API_URL}/departement/{dept['acronym']}/formsemestres_courants",
|
||||||
@ -147,10 +213,6 @@ def test_semestres_courant(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
result_a = r.json()
|
result_a = r.json()
|
||||||
assert isinstance(result_a, list) # liste de formsemestres
|
|
||||||
assert len(result_a) > 0
|
|
||||||
sem = result_a[0]
|
|
||||||
assert verify_fields(sem, fields) is True
|
|
||||||
|
|
||||||
# accès via dept_id
|
# accès via dept_id
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
@ -161,3 +223,7 @@ def test_semestres_courant(api_headers):
|
|||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
result_b = r.json()
|
result_b = r.json()
|
||||||
assert result_a == result_b
|
assert result_a == result_b
|
||||||
|
assert isinstance(result_a, list) # liste de formsemestres
|
||||||
|
assert len(result_a) > 0
|
||||||
|
sem = result_a[0]
|
||||||
|
assert verify_fields(sem, FORMSEMESTRE_FIELDS) is True
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""Test API: accès aux étudiants
|
"""Test Logos
|
||||||
|
|
||||||
Utilisation :
|
Utilisation :
|
||||||
créer les variables d'environnement: (indiquer les valeurs
|
créer les variables d'environnement: (indiquer les valeurs
|
||||||
@ -19,24 +19,54 @@ Utilisation :
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.api.setup_test_api import (
|
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
||||||
API_URL,
|
from tests.api.tools_test_api import (
|
||||||
CHECK_CERTIFICATE,
|
verify_fields,
|
||||||
DEPT_ACRONYM,
|
verify_occurences_ids_etus,
|
||||||
api_headers,
|
BULLETIN_FIELDS,
|
||||||
|
BULLETIN_ETUDIANT_FIELDS,
|
||||||
|
BULLETIN_FORMATION_FIELDS,
|
||||||
|
BULLETIN_OPTIONS_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_FIELDS,
|
||||||
|
BULLETIN_SAES_FIELDS,
|
||||||
|
BULLETIN_UES_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_FIELDS,
|
||||||
|
BULLETIN_UES_RT11_RESSOURCES_FIELDS,
|
||||||
|
BULLETIN_UES_RT11_SAES_FIELDS,
|
||||||
|
BULLETIN_UES_RT21_RESSOURCES_FIELDS,
|
||||||
|
BULLETIN_UES_RT31_RESSOURCES_FIELDS,
|
||||||
|
BULLETIN_UES_RT21_SAES_FIELDS,
|
||||||
|
BULLETIN_UES_RT31_SAES_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_ABSENCES_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_ECTS_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_NOTES_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_RANG_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_MOYENNE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_RESSOURCES_RESSOURCE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_SAES_SAE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_ECTS_FIELDS,
|
||||||
)
|
)
|
||||||
from tests.api.tools_test_api import verify_fields
|
|
||||||
from tests.api.tools_test_api import ETUD_FIELDS, FSEM_FIELDS
|
from tests.api.tools_test_api import ETUD_FIELDS, FSEM_FIELDS
|
||||||
|
|
||||||
|
|
||||||
|
ETUDID = 1
|
||||||
|
NIP = "1"
|
||||||
|
INE = "1"
|
||||||
|
|
||||||
|
|
||||||
def test_etudiants_courant(api_headers):
|
def test_etudiants_courant(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /etudiants/courant
|
Route: /etudiants/courant
|
||||||
"""
|
"""
|
||||||
fields = {"id", "nip", "ine", "nom", "nom_usuel", "prenom", "civilite"}
|
fields = {"id", "nip", "nom", "prenom", "civilite"}
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiants/courant",
|
API_URL + "/etudiants/courants",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -46,10 +76,18 @@ def test_etudiants_courant(api_headers):
|
|||||||
|
|
||||||
etud = etudiants[-1]
|
etud = etudiants[-1]
|
||||||
assert verify_fields(etud, fields) is True
|
assert verify_fields(etud, fields) is True
|
||||||
|
assert isinstance(etud["id"], int)
|
||||||
|
assert isinstance(etud["nip"], str)
|
||||||
|
assert isinstance(etud["nom"], str)
|
||||||
|
assert isinstance(etud["prenom"], str)
|
||||||
|
assert isinstance(etud["civilite"], str)
|
||||||
|
|
||||||
|
all_unique = verify_occurences_ids_etus(r.text)
|
||||||
|
assert all_unique is True
|
||||||
|
|
||||||
########## Version long ################
|
########## Version long ################
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiants/courant/long",
|
API_URL + "/etudiants/courants/long",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -63,77 +101,119 @@ def test_etudiants_courant(api_headers):
|
|||||||
|
|
||||||
def test_etudiant(api_headers):
|
def test_etudiant(api_headers):
|
||||||
"""
|
"""
|
||||||
Routes: /etudiant/etudid, /etudiant/nip, /etudiant/ine
|
Routes : /etudiant/etudid/<int:etudid>, /etudiant/nip/<string:nip>, /etudiant/ine/<string:ine>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
######### Test etudid #########
|
######### Test etudid #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/etudid/1",
|
API_URL + "/etudiant/etudid/" + str(ETUDID),
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud = r.json()
|
etud = r.json()
|
||||||
|
|
||||||
assert verify_fields(etud, ETUD_FIELDS) is True
|
assert verify_fields(etud, ETUD_FIELDS) is True
|
||||||
|
|
||||||
|
code_nip = r.json()["code_nip"]
|
||||||
|
code_ine = r.json()["code_ine"]
|
||||||
|
|
||||||
######### Test code nip #########
|
######### Test code nip #########
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/nip/1",
|
API_URL + "/etudiant/nip/" + code_nip,
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud = r.json()
|
etud_nip = r.json()
|
||||||
fields_ok = verify_fields(etud, ETUD_FIELDS)
|
fields_ok = verify_fields(etud, ETUD_FIELDS)
|
||||||
assert fields_ok is True
|
assert fields_ok is True
|
||||||
assert etud["dept_acronym"] == DEPT_ACRONYM
|
|
||||||
######### Test code ine #########
|
######### Test code ine #########
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/ine/INE1",
|
API_URL + "/etudiant/ine/" + code_ine,
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
etud_ine = r.json()
|
||||||
|
assert len(etud) == 26
|
||||||
|
fields_ok = verify_fields(etud, ETUD_FIELDS)
|
||||||
|
assert fields_ok is True
|
||||||
|
|
||||||
|
assert etud == etud_nip == etud_ine
|
||||||
|
|
||||||
|
|
||||||
|
def test_etudiants(api_headers):
|
||||||
|
"""
|
||||||
|
Route : /etudiants/etudid/<int:etudid>, /etudiants/nip/<string:nip>, /etudiants/ine/<string:ine>
|
||||||
|
"""
|
||||||
|
######### Test etudid #########
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/etudiants/etudid/" + str(ETUDID),
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud = r.json()
|
etud = r.json()
|
||||||
assert len(etud) == 25
|
code_nip = etud[0]["code_nip"]
|
||||||
fields_ok = verify_fields(etud, ETUD_FIELDS)
|
code_ine = etud[0]["code_ine"]
|
||||||
|
|
||||||
|
assert isinstance(etud, list)
|
||||||
|
assert len(etud) == 1
|
||||||
|
fields_ok = verify_fields(etud[0], ETUD_FIELDS)
|
||||||
assert fields_ok is True
|
assert fields_ok is True
|
||||||
|
|
||||||
# Vérifie le requetage des 3 1er étudiants
|
######### Test code nip #########
|
||||||
for etudid in (1, 2, 3):
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL }/etudiant/etudid/{etudid}",
|
API_URL + "/etudiants/nip/" + code_nip,
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud = r.json()
|
etud_nip = r.json()
|
||||||
nip = etud["code_nip"]
|
|
||||||
ine = etud["code_ine"]
|
assert isinstance(etud_nip, list)
|
||||||
assert isinstance(etud["id"], int)
|
fields_ok = verify_fields(etud_nip[0], ETUD_FIELDS)
|
||||||
assert isinstance(nip, str)
|
assert fields_ok is True
|
||||||
assert isinstance(ine, str)
|
|
||||||
r = requests.get(
|
all_unique = True
|
||||||
f"{API_URL }/etudiant/nip/{nip}",
|
list_ids = [etud["id"] for etud in etud_nip]
|
||||||
headers=api_headers,
|
for id in list_ids:
|
||||||
verify=CHECK_CERTIFICATE,
|
if list_ids.count(id) > 1:
|
||||||
)
|
all_unique = False
|
||||||
assert r.status_code == 200
|
assert all_unique is True
|
||||||
etud_nip = r.json()
|
|
||||||
# On doit avoir obtenue le même étudiant
|
######### Test code ine #########
|
||||||
assert etud_nip == etud
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL }/etudiant/ine/{ine}",
|
API_URL + "/etudiants/ine/" + code_ine,
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
etud_ine = r.json()
|
etud_ine = r.json()
|
||||||
# On doit avoir obtenue le même étudiant
|
|
||||||
assert etud_ine == etud
|
assert isinstance(etud_ine, list)
|
||||||
|
fields_ok = verify_fields(etud_ine[0], ETUD_FIELDS)
|
||||||
|
assert fields_ok is True
|
||||||
|
|
||||||
|
all_unique = True
|
||||||
|
list_ids = [etud["id"] for etud in etud_ine]
|
||||||
|
for id in list_ids:
|
||||||
|
if list_ids.count(id) > 1:
|
||||||
|
all_unique = False
|
||||||
|
assert all_unique is True
|
||||||
|
|
||||||
|
####### Erreurs #######
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/etudiants/etudid/",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_etudiant_formsemestres(api_headers):
|
def test_etudiant_formsemestres(api_headers):
|
||||||
@ -144,20 +224,52 @@ def test_etudiant_formsemestres(api_headers):
|
|||||||
######### Test etudid #########
|
######### Test etudid #########
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/etudid/1/formsemestres",
|
API_URL + "/etudiant/etudid/" + str(ETUDID) + "/formsemestres",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
formsemestres = r.json()
|
list_formsemestres = r.json()
|
||||||
assert len(formsemestres) == 1
|
assert len(list_formsemestres) == 1
|
||||||
|
formsemestre = list_formsemestres[0]
|
||||||
|
assert isinstance(formsemestre["id"], int)
|
||||||
|
assert isinstance(formsemestre["bul_bgcolor"], str)
|
||||||
|
assert isinstance(formsemestre["date_debut"], str)
|
||||||
|
assert isinstance(formsemestre["date_fin"], str)
|
||||||
|
assert isinstance(formsemestre["resp_can_edit"], bool)
|
||||||
|
assert isinstance(formsemestre["dept_id"], int)
|
||||||
|
assert isinstance(formsemestre["etat"], bool)
|
||||||
|
assert isinstance(formsemestre["resp_can_change_ens"], bool)
|
||||||
|
assert isinstance(formsemestre["modalite"], str)
|
||||||
|
assert isinstance(formsemestre["ens_can_edit_eval"], bool)
|
||||||
|
assert isinstance(formsemestre["formation_id"], int)
|
||||||
|
assert isinstance(formsemestre["gestion_compensation"], bool)
|
||||||
|
assert formsemestre["elt_sem_apo"] is None or isinstance(
|
||||||
|
formsemestre["elt_sem_apo"], str
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["semestre_id"], int)
|
||||||
|
assert isinstance(formsemestre["bul_hide_xml"], bool)
|
||||||
|
assert formsemestre["elt_annee_apo"] is None or isinstance(
|
||||||
|
formsemestre["elt_annee_apo"], str
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["titre"], str)
|
||||||
|
assert isinstance(formsemestre["block_moyennes"], bool)
|
||||||
|
assert formsemestre["scodoc7_id"] is None or isinstance(
|
||||||
|
formsemestre["scodoc7_id"], int
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["gestion_semestrielle"], bool)
|
||||||
|
assert isinstance(formsemestre["formsemestre_id"], int)
|
||||||
|
assert isinstance(formsemestre["titre_num"], str)
|
||||||
|
assert isinstance(formsemestre["date_debut_iso"], str)
|
||||||
|
assert isinstance(formsemestre["date_fin_iso"], str)
|
||||||
|
assert isinstance(formsemestre["responsables"], list)
|
||||||
|
assert isinstance(formsemestre["titre_formation"], str)
|
||||||
|
|
||||||
formsemestre = formsemestres[0]
|
|
||||||
assert verify_fields(formsemestre, FSEM_FIELDS) is True
|
assert verify_fields(formsemestre, FSEM_FIELDS) is True
|
||||||
|
|
||||||
######### Test code nip #########
|
######### Test code nip #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/nip/1/formsemestres",
|
API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestres",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -170,7 +282,7 @@ def test_etudiant_formsemestres(api_headers):
|
|||||||
|
|
||||||
######### Test code ine #########
|
######### Test code ine #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/ine/INE1/formsemestres",
|
API_URL + "/etudiant/ine/" + str(INE) + "/formsemestres",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -186,10 +298,391 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
"""
|
"""
|
||||||
Route: /etudiant/etudid/<etudid>/formsemestre/<formsemestre_id>/bulletin
|
Route: /etudiant/etudid/<etudid>/formsemestre/<formsemestre_id>/bulletin
|
||||||
"""
|
"""
|
||||||
|
##################### LONG ########################
|
||||||
|
|
||||||
######### Test etudid #########
|
######### Test etudid #########
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/etudid/1/formsemestre/1/bulletin",
|
API_URL + "/etudiant/etudid/" + str(ETUDID) + "/formsemestre/1/bulletin",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
bulletin = r.json()
|
||||||
|
assert len(bulletin) == 13 # HARDCODED
|
||||||
|
|
||||||
|
assert verify_fields(bulletin, BULLETIN_FIELDS) is True
|
||||||
|
assert isinstance(bulletin["version"], str)
|
||||||
|
assert isinstance(bulletin["type"], str)
|
||||||
|
assert isinstance(bulletin["date"], str)
|
||||||
|
assert isinstance(bulletin["publie"], bool)
|
||||||
|
assert isinstance(bulletin["etudiant"], dict)
|
||||||
|
assert isinstance(bulletin["formation"], dict)
|
||||||
|
assert isinstance(bulletin["formsemestre_id"], int)
|
||||||
|
assert isinstance(bulletin["etat_inscription"], str)
|
||||||
|
assert isinstance(bulletin["options"], dict)
|
||||||
|
assert isinstance(bulletin["ressources"], dict)
|
||||||
|
assert isinstance(bulletin["saes"], dict)
|
||||||
|
assert isinstance(bulletin["ues"], dict)
|
||||||
|
assert isinstance(bulletin["semestre"], dict)
|
||||||
|
|
||||||
|
bulletin_etud = bulletin["etudiant"]
|
||||||
|
assert verify_fields(bulletin_etud, BULLETIN_ETUDIANT_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_etud["civilite"], str)
|
||||||
|
assert isinstance(bulletin_etud["code_ine"], str)
|
||||||
|
assert isinstance(bulletin_etud["code_nip"], str)
|
||||||
|
assert isinstance(bulletin_etud["date_naissance"], str)
|
||||||
|
assert isinstance(bulletin_etud["dept_id"], int)
|
||||||
|
assert isinstance(bulletin_etud["dept_acronym"], str)
|
||||||
|
assert isinstance(bulletin_etud["email"], str)
|
||||||
|
assert isinstance(bulletin_etud["emailperso"], str)
|
||||||
|
assert isinstance(bulletin_etud["etudid"], int)
|
||||||
|
assert isinstance(bulletin_etud["nom"], str)
|
||||||
|
assert isinstance(bulletin_etud["prenom"], str)
|
||||||
|
assert isinstance(bulletin_etud["nomprenom"], str)
|
||||||
|
assert isinstance(bulletin_etud["lieu_naissance"], str)
|
||||||
|
assert isinstance(bulletin_etud["dept_naissance"], str)
|
||||||
|
assert isinstance(bulletin_etud["nationalite"], str)
|
||||||
|
assert isinstance(bulletin_etud["fiche_url"], str)
|
||||||
|
assert isinstance(bulletin_etud["photo_url"], str)
|
||||||
|
assert isinstance(bulletin_etud["id"], int)
|
||||||
|
assert isinstance(bulletin_etud["domicile"], str)
|
||||||
|
assert isinstance(bulletin_etud["villedomicile"], str)
|
||||||
|
assert isinstance(bulletin_etud["telephone"], str)
|
||||||
|
assert isinstance(bulletin_etud["fax"], str)
|
||||||
|
assert isinstance(bulletin_etud["description"], str)
|
||||||
|
assert isinstance(bulletin_etud["codepostaldomicile"], str)
|
||||||
|
assert isinstance(bulletin_etud["paysdomicile"], str)
|
||||||
|
assert isinstance(bulletin_etud["telephonemobile"], str)
|
||||||
|
assert isinstance(bulletin_etud["typeadresse"], str)
|
||||||
|
|
||||||
|
bulletin_formation = bulletin["formation"]
|
||||||
|
assert verify_fields(bulletin_formation, BULLETIN_FORMATION_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_formation["id"], int)
|
||||||
|
assert isinstance(bulletin_formation["acronyme"], str)
|
||||||
|
assert isinstance(bulletin_formation["titre_officiel"], str)
|
||||||
|
assert isinstance(bulletin_formation["titre"], str)
|
||||||
|
|
||||||
|
bulletin_options = bulletin["options"]
|
||||||
|
assert verify_fields(bulletin_options, BULLETIN_OPTIONS_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_options["show_abs"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_abs_modules"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_ects"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_codemodules"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_matieres"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_rangs"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_ue_rangs"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_mod_rangs"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_moypromo"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_minmax"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_minmax_mod"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_minmax_eval"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_coef"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_ue_cap_details"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_ue_cap_current"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_temporary"], bool)
|
||||||
|
assert isinstance(bulletin_options["temporary_txt"], str)
|
||||||
|
assert isinstance(bulletin_options["show_uevalid"], bool)
|
||||||
|
assert isinstance(bulletin_options["show_date_inscr"], bool)
|
||||||
|
|
||||||
|
bulletin_ressources = bulletin["ressources"]
|
||||||
|
assert verify_fields(bulletin_ressources, BULLETIN_RESSOURCES_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_ressources, dict)
|
||||||
|
|
||||||
|
for ressource in bulletin_ressources.values():
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
ressource, BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(ressource, dict)
|
||||||
|
assert isinstance(ressource["evaluations"], list)
|
||||||
|
for evaluation in ressource["evaluations"]:
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["id"], int)
|
||||||
|
assert evaluation["description"] is None or isinstance(
|
||||||
|
evaluation["description"], str
|
||||||
|
)
|
||||||
|
assert evaluation["date"] is None or isinstance(evaluation["date"], str)
|
||||||
|
assert isinstance(evaluation["heure_debut"], str)
|
||||||
|
assert isinstance(evaluation["heure_fin"], str)
|
||||||
|
assert isinstance(evaluation["coef"], str)
|
||||||
|
assert isinstance(evaluation["poids"], dict)
|
||||||
|
assert isinstance(evaluation["note"], dict)
|
||||||
|
assert isinstance(evaluation["url"], str)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["poids"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["poids"]["RT1.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT2.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT3.1"], float)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["note"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["note"]["value"], str)
|
||||||
|
assert isinstance(evaluation["note"]["min"], str)
|
||||||
|
assert isinstance(evaluation["note"]["max"], str)
|
||||||
|
assert isinstance(evaluation["note"]["moy"], str)
|
||||||
|
|
||||||
|
bulletin_saes = bulletin["saes"]
|
||||||
|
assert verify_fields(bulletin_saes, BULLETIN_SAES_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_saes, dict)
|
||||||
|
|
||||||
|
for sae in bulletin_saes.values():
|
||||||
|
assert (
|
||||||
|
verify_fields(sae, BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(sae, dict)
|
||||||
|
assert isinstance(sae["evaluations"], list)
|
||||||
|
for evaluation in sae["evaluations"]:
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["id"], int)
|
||||||
|
assert evaluation["description"] is None or isinstance(
|
||||||
|
evaluation["description"], str
|
||||||
|
)
|
||||||
|
assert evaluation["date"] is None or isinstance(evaluation["date"], str)
|
||||||
|
assert isinstance(evaluation["heure_debut"], str)
|
||||||
|
assert isinstance(evaluation["heure_fin"], str)
|
||||||
|
assert isinstance(evaluation["coef"], str)
|
||||||
|
assert isinstance(evaluation["poids"], dict)
|
||||||
|
assert isinstance(evaluation["note"], dict)
|
||||||
|
assert isinstance(evaluation["url"], str)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["poids"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["poids"]["RT1.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT2.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT3.1"], float)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["note"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["note"]["value"], str)
|
||||||
|
assert isinstance(evaluation["note"]["min"], str)
|
||||||
|
assert isinstance(evaluation["note"]["max"], str)
|
||||||
|
assert isinstance(evaluation["note"]["moy"], str)
|
||||||
|
|
||||||
|
bulletin_ues = bulletin["ues"]
|
||||||
|
assert verify_fields(bulletin_ues, BULLETIN_UES_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_ues, dict)
|
||||||
|
|
||||||
|
for (key_ue, value_ue) in bulletin_ues.items():
|
||||||
|
assert verify_fields(value_ue, BULLETIN_UES_UE_FIELDS) is True
|
||||||
|
assert isinstance(value_ue["id"], int)
|
||||||
|
assert isinstance(value_ue["titre"], str)
|
||||||
|
assert isinstance(value_ue["numero"], int)
|
||||||
|
assert isinstance(value_ue["type"], int)
|
||||||
|
assert isinstance(value_ue["color"], str)
|
||||||
|
assert value_ue["competence"] is None or isinstance(value_ue["competence"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"], dict)
|
||||||
|
assert isinstance(value_ue["bonus"], str)
|
||||||
|
assert isinstance(value_ue["malus"], str)
|
||||||
|
assert value_ue["capitalise"] is None or isinstance(value_ue["capitalise"], str)
|
||||||
|
assert isinstance(value_ue["ressources"], dict)
|
||||||
|
assert isinstance(value_ue["saes"], dict)
|
||||||
|
assert isinstance(value_ue["ECTS"], dict)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(value_ue["moyenne"], BULLETIN_UES_UE_MOYENNE_FIELDS) is True
|
||||||
|
)
|
||||||
|
assert isinstance(value_ue["moyenne"]["value"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["min"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["max"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["moy"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["rang"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["total"], int)
|
||||||
|
|
||||||
|
if key_ue == "RT1.1":
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_ues[key_ue]["ressources"],
|
||||||
|
BULLETIN_UES_RT11_RESSOURCES_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_ues[key_ue]["saes"], BULLETIN_UES_RT11_SAES_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
elif key_ue == "RT2.1":
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_ues[key_ue]["ressources"],
|
||||||
|
BULLETIN_UES_RT21_RESSOURCES_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_ues[key_ue]["saes"], BULLETIN_UES_RT21_SAES_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
elif key_ue == "RT3.1":
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_ues[key_ue]["ressources"],
|
||||||
|
BULLETIN_UES_RT31_RESSOURCES_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_ues[key_ue]["saes"], BULLETIN_UES_RT31_SAES_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
|
||||||
|
for ressource in value_ue["ressources"].values():
|
||||||
|
assert (
|
||||||
|
verify_fields(ressource, BULLETIN_UES_UE_RESSOURCES_RESSOURCE_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(ressource["id"], int)
|
||||||
|
assert isinstance(ressource["coef"], float)
|
||||||
|
assert isinstance(ressource["moyenne"], str)
|
||||||
|
|
||||||
|
for sae in value_ue["saes"].values():
|
||||||
|
assert verify_fields(sae, BULLETIN_UES_UE_SAES_SAE_FIELDS) is True
|
||||||
|
assert isinstance(sae["id"], int)
|
||||||
|
assert isinstance(sae["coef"], float)
|
||||||
|
assert isinstance(sae["moyenne"], str)
|
||||||
|
|
||||||
|
assert verify_fields(value_ue["ECTS"], BULLETIN_UES_UE_ECTS_FIELDS) is True
|
||||||
|
assert isinstance(value_ue["ECTS"]["acquis"], float)
|
||||||
|
assert isinstance(value_ue["ECTS"]["total"], float)
|
||||||
|
|
||||||
|
bulletin_semestre = bulletin["semestre"]
|
||||||
|
assert verify_fields(bulletin_semestre, BULLETIN_SEMESTRE_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_semestre["etapes"], list)
|
||||||
|
assert isinstance(bulletin_semestre["date_debut"], str)
|
||||||
|
assert isinstance(bulletin_semestre["date_fin"], str)
|
||||||
|
assert isinstance(bulletin_semestre["annee_universitaire"], str)
|
||||||
|
assert isinstance(bulletin_semestre["numero"], int)
|
||||||
|
assert isinstance(bulletin_semestre["inscription"], str)
|
||||||
|
assert isinstance(bulletin_semestre["groupes"], list)
|
||||||
|
assert isinstance(bulletin_semestre["absences"], dict)
|
||||||
|
assert isinstance(bulletin_semestre["ECTS"], dict)
|
||||||
|
assert isinstance(bulletin_semestre["notes"], dict)
|
||||||
|
assert isinstance(bulletin_semestre["rang"], dict)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["absences"], BULLETIN_SEMESTRE_ABSENCES_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["absences"]["injustifie"], int)
|
||||||
|
assert isinstance(bulletin_semestre["absences"]["total"], int)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["ECTS"], BULLETIN_SEMESTRE_ECTS_FIELDS) is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["ECTS"]["acquis"], int)
|
||||||
|
assert isinstance(bulletin_semestre["ECTS"]["total"], float)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["notes"], BULLETIN_SEMESTRE_NOTES_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["value"], str)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["min"], str)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["max"], str)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["moy"], str)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["rang"], BULLETIN_SEMESTRE_RANG_FIELDS) is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["rang"]["value"], str)
|
||||||
|
assert isinstance(bulletin_semestre["rang"]["total"], int)
|
||||||
|
|
||||||
|
######### Test code nip #########
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestre/1/bulletin",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
bul = r.json()
|
||||||
|
assert len(bul) == 13 # HARDCODED
|
||||||
|
|
||||||
|
######### Test code ine #########
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/etudiant/ine/" + str(INE) + "/formsemestre/1/bulletin",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
bul = r.json()
|
||||||
|
assert len(bul) == 13 # HARDCODED
|
||||||
|
|
||||||
|
################### LONG + PDF #####################
|
||||||
|
|
||||||
|
# ######### Test etudid #########
|
||||||
|
#
|
||||||
|
# r = requests.get(
|
||||||
|
# API_URL + "/etudiant/etudid/" + str(ETUDID) + "/formsemestre/1/bulletin/pdf",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
#
|
||||||
|
# ######### Test code nip #########
|
||||||
|
#
|
||||||
|
# r = requests.get(
|
||||||
|
# API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestre/1/bulletin/pdf",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
#
|
||||||
|
# ######### Test code ine #########
|
||||||
|
# r = requests.get(
|
||||||
|
# API_URL + "/etudiant/ine/" + str(INE) + "/formsemestre/1/bulletin/pdf",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
|
||||||
|
################### SHORT #####################
|
||||||
|
|
||||||
|
######### Test etudid #########
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/etudiant/etudid/" + str(ETUDID) + "/formsemestre/1/bulletin/short",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -200,7 +693,7 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
######### Test code nip #########
|
######### Test code nip #########
|
||||||
|
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/nip/1/formsemestre/1/bulletin",
|
API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestre/1/bulletin/short",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -210,7 +703,7 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
|
|
||||||
######### Test code ine #########
|
######### Test code ine #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/ine/INE1/formsemestre/1/bulletin",
|
API_URL + "/etudiant/ine/" + str(INE) + "/formsemestre/1/bulletin/short",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -218,6 +711,33 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
bul = r.json()
|
bul = r.json()
|
||||||
assert len(bul) == 13 # HARDCODED
|
assert len(bul) == 13 # HARDCODED
|
||||||
|
|
||||||
|
################### SHORT + PDF #####################
|
||||||
|
|
||||||
|
# ######### Test etudid #########
|
||||||
|
# r = requests.get(
|
||||||
|
# API_URL + "/etudiant/etudid/" + str(ETUDID) + "/formsemestre/1/bulletin/short/pdf",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
#
|
||||||
|
# ######### Test code nip #########
|
||||||
|
#
|
||||||
|
# r = requests.get(
|
||||||
|
# API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestre/1/bulletin/short/pdf",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
#
|
||||||
|
# ######### Test code ine #########
|
||||||
|
# r = requests.get(
|
||||||
|
# API_URL + "/etudiant/ine/" + str(INE) + "/formsemestre/1/bulletin/short/pdf",
|
||||||
|
# headers=api_headers,
|
||||||
|
# verify=CHECK_CERTIFICATE,
|
||||||
|
# )
|
||||||
|
# assert r.status_code == 200
|
||||||
|
|
||||||
### --- Test étudiant inexistant
|
### --- Test étudiant inexistant
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/ine/189919919119191/formsemestre/1/bulletin",
|
API_URL + "/etudiant/ine/189919919119191/formsemestre/1/bulletin",
|
||||||
@ -260,7 +780,7 @@ def test_etudiant_groups(api_headers):
|
|||||||
|
|
||||||
######### Test code nip #########
|
######### Test code nip #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/nip/1/formsemestre/1/groups",
|
API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestre/1/groups",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
@ -273,7 +793,7 @@ def test_etudiant_groups(api_headers):
|
|||||||
|
|
||||||
######### Test code ine #########
|
######### Test code ine #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/etudiant/ine/INE1/formsemestre/1/groups",
|
API_URL + "/etudiant/ine/" + str(INE) + "/formsemestre/1/groups",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
|
@ -20,30 +20,79 @@ Utilisation :
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
||||||
|
from tests.api.tools_test_api import (
|
||||||
|
verify_fields,
|
||||||
|
EVALUATIONS_FIELDS,
|
||||||
|
EVALUATION_FIELDS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_evaluations(api_headers):
|
def test_evaluations(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /evaluation/<int:moduleimpl_id>
|
Test 'evaluations'
|
||||||
|
|
||||||
|
Route :
|
||||||
|
- /evaluations/<int:moduleimpl_id>
|
||||||
"""
|
"""
|
||||||
|
moduleimpl_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/evaluations/1",
|
f"{API_URL}/evaluations/{moduleimpl_id}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
# TODO
|
list_eval = r.json()
|
||||||
|
assert isinstance(list_eval, list)
|
||||||
|
for eval in list_eval:
|
||||||
|
assert verify_fields(eval, EVALUATIONS_FIELDS) is True
|
||||||
|
assert isinstance(eval["id"], int)
|
||||||
|
assert isinstance(eval["jour"], str)
|
||||||
|
assert isinstance(eval["heure_fin"], str)
|
||||||
|
assert isinstance(eval["note_max"], float)
|
||||||
|
assert isinstance(eval["visibulletin"], bool)
|
||||||
|
assert isinstance(eval["evaluation_type"], int)
|
||||||
|
assert isinstance(eval["moduleimpl_id"], int)
|
||||||
|
assert isinstance(eval["heure_debut"], str)
|
||||||
|
assert eval["description"] is None or isinstance(eval["description"], str)
|
||||||
|
assert isinstance(eval["coefficient"], float)
|
||||||
|
assert isinstance(eval["publish_incomplete"], bool)
|
||||||
|
assert isinstance(eval["numero"], int)
|
||||||
|
assert isinstance(eval["evaluation_id"], int)
|
||||||
|
assert eval["date_debut"] is None or isinstance(eval["date_debut"], str)
|
||||||
|
assert eval["date_fin"] is None or isinstance(eval["date_fin"], str)
|
||||||
|
assert isinstance(eval["poids"], dict)
|
||||||
|
assert eval["jouriso"] is None or isinstance(eval["jouriso"], str)
|
||||||
|
assert isinstance(eval["duree"], str)
|
||||||
|
assert isinstance(eval["descrheure"], str)
|
||||||
|
assert isinstance(eval["matin"], int)
|
||||||
|
assert isinstance(eval["apresmidi"], int)
|
||||||
|
|
||||||
|
assert eval["moduleimpl_id"] == moduleimpl_id
|
||||||
|
|
||||||
|
|
||||||
# TODO car pas d'évaluations créées à ce stade
|
def test_evaluation_notes(api_headers): # XXX TODO changer la boucle pour parcourir le dict sans les indices
|
||||||
# def test_evaluation_notes(api_headers):
|
"""
|
||||||
# """
|
Test 'evaluation_notes'
|
||||||
# Route: /evaluation/eval_notes/<int:evaluation_id>
|
|
||||||
# """
|
Route :
|
||||||
# r = requests.get(
|
- /evaluation/eval_notes/<int:evaluation_id>
|
||||||
# API_URL + "/evaluation/eval_notes/1",
|
"""
|
||||||
# headers=api_headers,
|
eval_id = 1
|
||||||
# verify=CHECK_CERTIFICATE,
|
r = requests.get(
|
||||||
# )
|
f"{API_URL}/evaluation/eval_notes/{eval_id}",
|
||||||
# assert r.status_code == 200
|
headers=api_headers,
|
||||||
# # TODO
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
eval_notes = r.json()
|
||||||
|
for i in range(1, len(eval_notes)):
|
||||||
|
assert verify_fields(eval_notes[f"{i}"], EVALUATION_FIELDS)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["id"], int)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["etudid"], int)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["evaluation_id"], int)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["value"], float)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["comment"], str)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["date"], str)
|
||||||
|
assert isinstance(eval_notes[f"{i}"]["uid"], int)
|
||||||
|
|
||||||
|
assert eval_id == eval_notes[f"{i}"]["evaluation_id"]
|
||||||
|
@ -20,7 +20,16 @@ Utilisation :
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
||||||
from tests.api.tools_test_api import verify_fields
|
from tests.api.tools_test_api import (
|
||||||
|
verify_fields,
|
||||||
|
FORMATION_EXPORT_FIELDS,
|
||||||
|
FORMATION_EXPORT_UE_FIELDS,
|
||||||
|
FORMATION_EXPORT_UE_MATIERE_FIELDS,
|
||||||
|
FORMATION_EXPORT_UE_MATIERE_MODULE_FIELDS,
|
||||||
|
FORMATION_EXPORT_UE_MATIERE_MODULE_COEF_FIELDS,
|
||||||
|
MODULE_FIELDS,
|
||||||
|
REF_COMP_FIELDS,
|
||||||
|
)
|
||||||
from tests.api.tools_test_api import FORMATION_FIELDS, MODIMPL_FIELDS
|
from tests.api.tools_test_api import FORMATION_FIELDS, MODIMPL_FIELDS
|
||||||
|
|
||||||
|
|
||||||
@ -45,15 +54,52 @@ def test_formations_by_id(api_headers):
|
|||||||
"""
|
"""
|
||||||
Route: /formation/<int:formation_id>
|
Route: /formation/<int:formation_id>
|
||||||
"""
|
"""
|
||||||
|
id_formation = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/formation/1",
|
f"{API_URL}/formation/{id_formation}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
formation = r.json()
|
formation = r.json()
|
||||||
assert verify_fields(formation, FORMATION_FIELDS) is True
|
assert verify_fields(formation, FORMATION_FIELDS) is True
|
||||||
# TODO tester le contenu de certains champs
|
assert isinstance(formation["dept_id"], int)
|
||||||
|
assert isinstance(formation["acronyme"], str)
|
||||||
|
assert isinstance(formation["titre_officiel"], str)
|
||||||
|
assert isinstance(formation["formation_code"], str)
|
||||||
|
assert formation["code_specialite"] is None or isinstance(
|
||||||
|
formation["code_specialite"], str
|
||||||
|
)
|
||||||
|
assert isinstance(formation["id"], int)
|
||||||
|
assert isinstance(formation["titre"], str)
|
||||||
|
assert isinstance(formation["version"], int)
|
||||||
|
assert isinstance(formation["type_parcours"], int)
|
||||||
|
assert formation["referentiel_competence_id"] is None or isinstance(
|
||||||
|
formation["referentiel_competence_id"], int
|
||||||
|
)
|
||||||
|
assert isinstance(formation["formation_id"], int)
|
||||||
|
|
||||||
|
assert id_formation == formation["formation_id"]
|
||||||
|
assert id_formation == formation["id"]
|
||||||
|
|
||||||
|
r1 = requests.get(
|
||||||
|
f"{API_URL}/formation/{formation['formation_id']}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r1.status_code == 200
|
||||||
|
formation1 = r1.json()
|
||||||
|
|
||||||
|
assert formation == formation1
|
||||||
|
|
||||||
|
# ERROR
|
||||||
|
id_formation_inexistant = 1516476846861656351
|
||||||
|
r_error = requests.get(
|
||||||
|
f"{API_URL}/formation/{id_formation_inexistant}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_formation_export(api_headers):
|
def test_formation_export(api_headers):
|
||||||
@ -67,33 +113,150 @@ def test_formation_export(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
export_formation = r.json()
|
export_formation = r.json()
|
||||||
assert verify_fields(export_formation, FORMATION_FIELDS) is True
|
assert verify_fields(export_formation, FORMATION_EXPORT_FIELDS) is True
|
||||||
# TODO tester le contenu de certains champs
|
assert isinstance(export_formation["dept_id"], int)
|
||||||
|
assert isinstance(export_formation["acronyme"], str)
|
||||||
|
assert isinstance(export_formation["titre_officiel"], str)
|
||||||
|
assert isinstance(export_formation["formation_code"], str)
|
||||||
|
assert export_formation["code_specialite"] is None or isinstance(
|
||||||
|
export_formation["code_specialite"], str
|
||||||
|
)
|
||||||
|
assert isinstance(export_formation["id"], int)
|
||||||
|
assert isinstance(export_formation["titre"], str)
|
||||||
|
assert isinstance(export_formation["version"], int)
|
||||||
|
assert isinstance(export_formation["type_parcours"], int)
|
||||||
|
assert export_formation["referentiel_competence_id"] is None or isinstance(
|
||||||
|
export_formation["referentiel_competence_id"], int
|
||||||
|
)
|
||||||
|
assert isinstance(export_formation["formation_id"], int)
|
||||||
|
assert isinstance(export_formation["ue"], list)
|
||||||
|
|
||||||
|
ues = export_formation["ue"]
|
||||||
|
|
||||||
# TODO
|
for ue in ues:
|
||||||
# def test_formsemestre_apo(api_headers):
|
assert verify_fields(ue, FORMATION_EXPORT_UE_FIELDS) is True
|
||||||
# r = requests.get(
|
assert isinstance(ue["acronyme"], str)
|
||||||
# API_URL + "/formation/apo/<string:etape_apo>",
|
assert isinstance(ue["numero"], int)
|
||||||
# headers=api_headers,
|
assert isinstance(ue["titre"], str)
|
||||||
# verify=CHECK_CERTIFICATE,
|
assert isinstance(ue["type"], int)
|
||||||
# )
|
assert isinstance(ue["ue_code"], str)
|
||||||
# assert r.status_code == 200
|
assert isinstance(ue["ects"], float)
|
||||||
|
assert isinstance(ue["is_external"], bool)
|
||||||
|
assert isinstance(ue["code_apogee"], str)
|
||||||
|
assert isinstance(ue["coefficient"], float)
|
||||||
|
assert isinstance(ue["semestre_idx"], int)
|
||||||
|
assert isinstance(ue["color"], str)
|
||||||
|
assert isinstance(ue["reference"], int)
|
||||||
|
assert isinstance(ue["matiere"], list)
|
||||||
|
|
||||||
|
matieres = ue["matiere"]
|
||||||
|
|
||||||
|
for matiere in matieres:
|
||||||
|
assert verify_fields(matiere, FORMATION_EXPORT_UE_MATIERE_FIELDS)
|
||||||
|
assert isinstance(matiere["titre"], str)
|
||||||
|
assert isinstance(matiere["numero"], int)
|
||||||
|
assert isinstance(matiere["module"], list)
|
||||||
|
|
||||||
|
modules = matiere["module"]
|
||||||
|
for module in modules:
|
||||||
|
assert verify_fields(module, FORMATION_EXPORT_UE_MATIERE_MODULE_FIELDS)
|
||||||
|
assert isinstance(module["titre"], str)
|
||||||
|
assert isinstance(module["abbrev"], str)
|
||||||
|
assert isinstance(module["code"], str)
|
||||||
|
assert isinstance(module["heures_cours"], float)
|
||||||
|
assert isinstance(module["heures_td"], float)
|
||||||
|
assert isinstance(module["heures_tp"], float)
|
||||||
|
assert isinstance(module["coefficient"], float)
|
||||||
|
assert isinstance(module["ects"], str)
|
||||||
|
assert isinstance(module["semestre_id"], int)
|
||||||
|
assert isinstance(module["numero"], int)
|
||||||
|
assert isinstance(module["code_apogee"], str)
|
||||||
|
assert isinstance(module["module_type"], int)
|
||||||
|
assert isinstance(module["coefficients"], list)
|
||||||
|
|
||||||
|
coefficients = module["coefficients"]
|
||||||
|
for coef in coefficients:
|
||||||
|
assert verify_fields(
|
||||||
|
coef, FORMATION_EXPORT_UE_MATIERE_MODULE_COEF_FIELDS
|
||||||
|
)
|
||||||
|
assert isinstance(coef["ue_reference"], str)
|
||||||
|
assert isinstance(coef["coef"], str)
|
||||||
|
|
||||||
|
# ERROR
|
||||||
|
id_formation_inexistant = 1516476846861656351
|
||||||
|
r_error = requests.get(
|
||||||
|
f"{API_URL}/formation/formation_export/{id_formation_inexistant}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_moduleimpl(api_headers):
|
def test_moduleimpl(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /formation/moduleimpl/<int:moduleimpl_id>
|
Route: /formation/moduleimpl/<int:moduleimpl_id>
|
||||||
"""
|
"""
|
||||||
|
moduleimpl_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/formation/moduleimpl/1",
|
f"{API_URL}/formation/moduleimpl/{moduleimpl_id}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
moduleimpl = r.json()
|
moduleimpl = r.json()
|
||||||
assert verify_fields(moduleimpl, MODIMPL_FIELDS) is True
|
assert verify_fields(moduleimpl, MODIMPL_FIELDS) is True
|
||||||
# TODO tester le contenu de certains champs
|
assert isinstance(moduleimpl["id"], int)
|
||||||
|
assert isinstance(moduleimpl["responsable_id"], int)
|
||||||
|
assert isinstance(moduleimpl["module_id"], int)
|
||||||
|
assert isinstance(moduleimpl["formsemestre_id"], int)
|
||||||
|
assert moduleimpl["computation_expr"] is None or isinstance(
|
||||||
|
moduleimpl["computation_expr"], str
|
||||||
|
)
|
||||||
|
assert isinstance(moduleimpl["moduleimpl_id"], int)
|
||||||
|
assert isinstance(moduleimpl["ens"], list)
|
||||||
|
assert isinstance(moduleimpl["module"], dict)
|
||||||
|
|
||||||
|
module = moduleimpl["module"]
|
||||||
|
assert verify_fields(module, MODULE_FIELDS)
|
||||||
|
assert isinstance(module["heures_cours"], float)
|
||||||
|
assert isinstance(module["semestre_id"], int)
|
||||||
|
assert isinstance(module["heures_td"], float)
|
||||||
|
assert isinstance(module["numero"], int)
|
||||||
|
assert isinstance(module["heures_tp"], float)
|
||||||
|
assert isinstance(module["code_apogee"], str)
|
||||||
|
assert isinstance(module["titre"], str)
|
||||||
|
assert isinstance(module["coefficient"], float)
|
||||||
|
assert isinstance(module["module_type"], int)
|
||||||
|
assert isinstance(module["id"], int)
|
||||||
|
assert module["ects"] is None or isinstance(module["ects"], str)
|
||||||
|
assert isinstance(module["abbrev"], str)
|
||||||
|
assert isinstance(module["ue_id"], int)
|
||||||
|
assert isinstance(module["code"], str)
|
||||||
|
assert isinstance(module["formation_id"], int)
|
||||||
|
assert isinstance(module["matiere_id"], int)
|
||||||
|
assert isinstance(module["module_id"], int)
|
||||||
|
|
||||||
|
assert moduleimpl_id == moduleimpl["id"]
|
||||||
|
assert moduleimpl_id == moduleimpl["moduleimpl_id"]
|
||||||
|
|
||||||
|
r1 = requests.get(
|
||||||
|
f"{API_URL}/formation/moduleimpl/{moduleimpl['moduleimpl_id']}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r1.status_code == 200
|
||||||
|
moduleimpl1 = r1.json()
|
||||||
|
|
||||||
|
assert moduleimpl == moduleimpl1
|
||||||
|
|
||||||
|
# ERROR
|
||||||
|
id_formation_inexistant = 1516476846861656351
|
||||||
|
r_error = requests.get(
|
||||||
|
f"{API_URL}/formation/moduleimpl/{id_formation_inexistant}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_referentiel_competences(api_headers):
|
def test_referentiel_competences(api_headers):
|
||||||
@ -101,9 +264,32 @@ def test_referentiel_competences(api_headers):
|
|||||||
Route: "/formation/<int:formation_id>/referentiel_competences",
|
Route: "/formation/<int:formation_id>/referentiel_competences",
|
||||||
"""
|
"""
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/formation/1/referentiel_competences",
|
f"{API_URL}/formation/1/referentiel_competences",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
# XXX A compléter
|
|
||||||
|
ref_comp = r.json()
|
||||||
|
assert verify_fields(ref_comp, REF_COMP_FIELDS) is True
|
||||||
|
assert isinstance(ref_comp["dept_id"], int)
|
||||||
|
assert isinstance(ref_comp["annexe"], str)
|
||||||
|
assert isinstance(ref_comp["specialite"], str)
|
||||||
|
assert isinstance(ref_comp["specialite_long"], str)
|
||||||
|
assert isinstance(ref_comp["type_structure"], str)
|
||||||
|
assert isinstance(ref_comp["type_departement"], str)
|
||||||
|
assert isinstance(ref_comp["type_titre"], str)
|
||||||
|
assert isinstance(ref_comp["version_orebut"], str)
|
||||||
|
assert isinstance(ref_comp["scodoc_date_loaded"], str)
|
||||||
|
assert isinstance(ref_comp["scodoc_orig_filename"], str)
|
||||||
|
assert isinstance(ref_comp["competences"], dict)
|
||||||
|
assert isinstance(ref_comp["parcours"], dict)
|
||||||
|
|
||||||
|
# ERROR
|
||||||
|
id_formation_inexistant = 1516476846861656351
|
||||||
|
r_error = requests.get(
|
||||||
|
f"{API_URL}/formation/{id_formation_inexistant}/referentiel_competences",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error.status_code == 404
|
||||||
|
@ -21,8 +21,36 @@ import requests
|
|||||||
from app.api.formsemestres import formsemestre
|
from app.api.formsemestres import formsemestre
|
||||||
|
|
||||||
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
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 FSEM_FIELDS, UE_FIELDS, MODULE_FIELDS
|
from tests.api.tools_test_api import (
|
||||||
|
verify_fields,
|
||||||
|
MODIMPL_FIELDS,
|
||||||
|
EVAL_FIELDS,
|
||||||
|
SAISIE_NOTES_FIELDS,
|
||||||
|
FORMSEMESTRE_ETUS_FIELDS,
|
||||||
|
FSEM_FIELDS,
|
||||||
|
FSEM_FIELDS,
|
||||||
|
UE_FIELDS,
|
||||||
|
MODULE_FIELDS,
|
||||||
|
FORMSEMESTRE_BULLETINS_FIELDS,
|
||||||
|
FORMSEMESTRE_BULLETINS_ETU_FIELDS,
|
||||||
|
FORMSEMESTRE_BULLETINS_FORMATION_FIELDS,
|
||||||
|
FORMSEMESTRE_BULLETINS_OPT_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_MOYENNE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_RESSOURCES_RESSOURCE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_SAES_SAE_FIELDS,
|
||||||
|
BULLETIN_UES_UE_ECTS_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_ABSENCES_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_ECTS_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_NOTES_FIELDS,
|
||||||
|
BULLETIN_SEMESTRE_RANG_FIELDS,
|
||||||
|
)
|
||||||
|
|
||||||
# Etudiant pour les tests
|
# Etudiant pour les tests
|
||||||
ETUDID = 1
|
ETUDID = 1
|
||||||
@ -34,62 +62,421 @@ def test_formsemestre(api_headers):
|
|||||||
"""
|
"""
|
||||||
Route: /formsemestre/<id>
|
Route: /formsemestre/<id>
|
||||||
"""
|
"""
|
||||||
|
formsemestre_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/formsemestre/1",
|
f"{API_URL}/formsemestre/{formsemestre_id}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
formsemestre = r.json()
|
formsemestre = r.json()
|
||||||
assert verify_fields(formsemestre, FSEM_FIELDS)
|
assert verify_fields(formsemestre, FSEM_FIELDS)
|
||||||
|
assert isinstance(formsemestre["block_moyennes"], bool)
|
||||||
|
assert isinstance(formsemestre["bul_bgcolor"], str)
|
||||||
|
assert isinstance(formsemestre["bul_hide_xml"], bool)
|
||||||
|
assert isinstance(formsemestre["date_debut_iso"], str)
|
||||||
|
assert isinstance(formsemestre["date_debut"], str)
|
||||||
|
assert isinstance(formsemestre["date_fin_iso"], str)
|
||||||
|
assert isinstance(formsemestre["date_fin"], str)
|
||||||
|
assert isinstance(formsemestre["dept_id"], int)
|
||||||
|
assert formsemestre["elt_annee_apo"] is None or isinstance(
|
||||||
|
formsemestre["elt_annee_apo"], str
|
||||||
|
)
|
||||||
|
assert formsemestre["elt_sem_apo"] is None or isinstance(
|
||||||
|
formsemestre["elt_sem_apo"], str
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["ens_can_edit_eval"], bool)
|
||||||
|
assert isinstance(formsemestre["etat"], bool)
|
||||||
|
assert isinstance(formsemestre["formation_id"], int)
|
||||||
|
assert isinstance(formsemestre["formsemestre_id"], int)
|
||||||
|
assert isinstance(formsemestre["gestion_compensation"], bool)
|
||||||
|
assert isinstance(formsemestre["gestion_semestrielle"], bool)
|
||||||
|
assert isinstance(formsemestre["id"], int)
|
||||||
|
assert isinstance(formsemestre["modalite"], str)
|
||||||
|
assert isinstance(formsemestre["resp_can_change_ens"], bool)
|
||||||
|
assert isinstance(formsemestre["resp_can_edit"], bool)
|
||||||
|
assert isinstance(formsemestre["responsables"], list)
|
||||||
|
assert formsemestre["scodoc7_id"] is None or isinstance(
|
||||||
|
formsemestre["scodoc7_id"], int
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["semestre_id"], int)
|
||||||
|
assert isinstance(formsemestre["titre_formation"], str)
|
||||||
|
assert isinstance(formsemestre["titre_num"], str)
|
||||||
|
assert isinstance(formsemestre["titre"], str)
|
||||||
|
|
||||||
|
### ERROR ###
|
||||||
|
formsemestre_id_inexistant = 165456165165136513510351
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{formsemestre_id_inexistant}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_etudiant_bulletin(api_headers):
|
def test_formsemestre_apo(api_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Route: /formsemestre/apo/<string:etape_apo>
|
||||||
"""
|
"""
|
||||||
formsemestre_id = 1
|
etape_apo = "A1"
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
f"{API_URL}/etudiant/etudid/1/formsemestre/{formsemestre_id}/bulletin",
|
f"{API_URL}/formsemestre/apo/{etape_apo}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
bull_a = r.json()
|
list_formsemestre = r.json()
|
||||||
|
assert isinstance(list_formsemestre, list)
|
||||||
|
|
||||||
r = requests.get(
|
for formsemestre in list_formsemestre:
|
||||||
f"{API_URL}/etudiant/nip/{NIP}/formsemestre/{formsemestre_id}/bulletin",
|
assert isinstance(formsemestre, dict)
|
||||||
headers=api_headers,
|
assert verify_fields(formsemestre, FSEM_FIELDS)
|
||||||
verify=CHECK_CERTIFICATE,
|
assert isinstance(formsemestre["block_moyennes"], bool)
|
||||||
)
|
assert isinstance(formsemestre["bul_bgcolor"], str)
|
||||||
assert r.status_code == 200
|
assert isinstance(formsemestre["bul_hide_xml"], bool)
|
||||||
bull_b = r.json()
|
assert isinstance(formsemestre["date_debut_iso"], str)
|
||||||
|
assert isinstance(formsemestre["date_debut"], str)
|
||||||
|
assert isinstance(formsemestre["date_fin_iso"], str)
|
||||||
|
assert isinstance(formsemestre["date_fin"], str)
|
||||||
|
assert isinstance(formsemestre["dept_id"], int)
|
||||||
|
assert formsemestre["elt_annee_apo"] is None or isinstance(
|
||||||
|
formsemestre["elt_annee_apo"], str
|
||||||
|
)
|
||||||
|
assert formsemestre["elt_sem_apo"] is None or isinstance(
|
||||||
|
formsemestre["elt_sem_apo"], str
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["ens_can_edit_eval"], bool)
|
||||||
|
assert isinstance(formsemestre["etat"], bool)
|
||||||
|
assert isinstance(formsemestre["formation_id"], int)
|
||||||
|
assert isinstance(formsemestre["formsemestre_id"], int)
|
||||||
|
assert isinstance(formsemestre["gestion_compensation"], bool)
|
||||||
|
assert isinstance(formsemestre["gestion_semestrielle"], bool)
|
||||||
|
assert isinstance(formsemestre["id"], int)
|
||||||
|
assert isinstance(formsemestre["modalite"], str)
|
||||||
|
assert isinstance(formsemestre["resp_can_change_ens"], bool)
|
||||||
|
assert isinstance(formsemestre["resp_can_edit"], bool)
|
||||||
|
assert isinstance(formsemestre["responsables"], list)
|
||||||
|
assert formsemestre["scodoc7_id"] is None or isinstance(
|
||||||
|
formsemestre["scodoc7_id"], int
|
||||||
|
)
|
||||||
|
assert isinstance(formsemestre["semestre_id"], int)
|
||||||
|
assert isinstance(formsemestre["titre_formation"], str)
|
||||||
|
assert isinstance(formsemestre["titre_num"], str)
|
||||||
|
assert isinstance(formsemestre["titre"], str)
|
||||||
|
|
||||||
r = requests.get(
|
### ERROR ###
|
||||||
f"{API_URL}/etudiant/ine/{INE}/formsemestre/{formsemestre_id}/bulletin",
|
# etape_apo_inexistante = "aoefiaozidaoẑidjnoaiznjd"
|
||||||
headers=api_headers,
|
# r_error = requests.get(
|
||||||
verify=CHECK_CERTIFICATE,
|
# f"{API_URL}/formsemestre/apo/{etape_apo_inexistante}",
|
||||||
)
|
# headers=api_headers,
|
||||||
assert r.status_code == 200
|
# verify=CHECK_CERTIFICATE,
|
||||||
bull_c = r.json()
|
# )
|
||||||
# elimine les dates de publication pour comparer les autres champs
|
# assert r_error.status_code == 404
|
||||||
del bull_a["date"]
|
|
||||||
del bull_b["date"]
|
|
||||||
del bull_c["date"]
|
|
||||||
assert bull_a == bull_b == bull_c
|
|
||||||
|
|
||||||
|
|
||||||
def test_bulletins(api_headers):
|
def test_bulletins(api_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Route: /formsemestre/<int:formsemestre_id>/bulletins
|
||||||
"""
|
"""
|
||||||
|
formsemestre_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/formsemestre/1/bulletins",
|
f"{API_URL}/formsemestre/{formsemestre_id}/bulletins",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
bulletins = r.json()
|
||||||
|
|
||||||
|
assert isinstance(bulletins, list)
|
||||||
|
for bul in bulletins:
|
||||||
|
assert verify_fields(bul, FORMSEMESTRE_BULLETINS_FIELDS) is True
|
||||||
|
assert isinstance(bul["version"], str)
|
||||||
|
assert isinstance(bul["type"], str)
|
||||||
|
assert isinstance(bul["date"], str)
|
||||||
|
assert isinstance(bul["publie"], bool)
|
||||||
|
assert isinstance(bul["etudiant"], dict)
|
||||||
|
assert isinstance(bul["formation"], dict)
|
||||||
|
assert isinstance(bul["formsemestre_id"], int)
|
||||||
|
assert isinstance(bul["etat_inscription"], str)
|
||||||
|
assert isinstance(bul["options"], dict)
|
||||||
|
assert isinstance(bul["ressources"], dict)
|
||||||
|
assert isinstance(bul["saes"], dict)
|
||||||
|
assert isinstance(bul["ues"], dict)
|
||||||
|
assert isinstance(bul["semestre"], dict)
|
||||||
|
|
||||||
|
formsemestre_id_bul = bul["formsemestre_id"]
|
||||||
|
assert formsemestre_id == formsemestre_id_bul
|
||||||
|
|
||||||
|
etudiant = bul["etudiant"]
|
||||||
|
assert verify_fields(etudiant, FORMSEMESTRE_BULLETINS_ETU_FIELDS) is True
|
||||||
|
assert isinstance(etudiant["civilite"], str)
|
||||||
|
assert isinstance(etudiant["code_ine"], str)
|
||||||
|
assert isinstance(etudiant["code_nip"], str)
|
||||||
|
assert isinstance(etudiant["date_naissance"], str)
|
||||||
|
assert isinstance(etudiant["dept_id"], int)
|
||||||
|
assert isinstance(etudiant["dept_acronym"], str)
|
||||||
|
assert isinstance(etudiant["email"], str)
|
||||||
|
assert isinstance(etudiant["emailperso"], str)
|
||||||
|
assert isinstance(etudiant["etudid"], int)
|
||||||
|
assert isinstance(etudiant["nom"], str)
|
||||||
|
assert isinstance(etudiant["prenom"], str)
|
||||||
|
assert isinstance(etudiant["nomprenom"], str)
|
||||||
|
assert isinstance(etudiant["lieu_naissance"], str)
|
||||||
|
assert isinstance(etudiant["dept_naissance"], str)
|
||||||
|
assert isinstance(etudiant["nationalite"], str)
|
||||||
|
assert isinstance(etudiant["boursier"], str)
|
||||||
|
assert isinstance(etudiant["fiche_url"], str)
|
||||||
|
assert isinstance(etudiant["photo_url"], str)
|
||||||
|
assert isinstance(etudiant["id"], int)
|
||||||
|
assert isinstance(etudiant["codepostaldomicile"], str)
|
||||||
|
assert isinstance(etudiant["paysdomicile"], str)
|
||||||
|
assert isinstance(etudiant["telephonemobile"], str)
|
||||||
|
assert isinstance(etudiant["typeadresse"], str)
|
||||||
|
assert isinstance(etudiant["domicile"], str)
|
||||||
|
assert isinstance(etudiant["villedomicile"], str)
|
||||||
|
assert isinstance(etudiant["telephone"], str)
|
||||||
|
assert isinstance(etudiant["fax"], str)
|
||||||
|
assert isinstance(etudiant["description"], str)
|
||||||
|
|
||||||
|
formation = bul["formation"]
|
||||||
|
assert verify_fields(formation, FORMSEMESTRE_BULLETINS_FORMATION_FIELDS) is True
|
||||||
|
assert isinstance(formation["id"], int)
|
||||||
|
assert isinstance(formation["acronyme"], str)
|
||||||
|
assert isinstance(formation["titre_officiel"], str)
|
||||||
|
assert isinstance(formation["titre"], str)
|
||||||
|
|
||||||
|
options = bul["options"]
|
||||||
|
assert verify_fields(options, FORMSEMESTRE_BULLETINS_OPT_FIELDS) is True
|
||||||
|
assert isinstance(options["show_abs"], bool)
|
||||||
|
assert isinstance(options["show_abs_modules"], bool)
|
||||||
|
assert isinstance(options["show_ects"], bool)
|
||||||
|
assert isinstance(options["show_codemodules"], bool)
|
||||||
|
assert isinstance(options["show_matieres"], bool)
|
||||||
|
assert isinstance(options["show_rangs"], bool)
|
||||||
|
assert isinstance(options["show_ue_rangs"], bool)
|
||||||
|
assert isinstance(options["show_mod_rangs"], bool)
|
||||||
|
assert isinstance(options["show_moypromo"], bool)
|
||||||
|
assert isinstance(options["show_minmax"], bool)
|
||||||
|
assert isinstance(options["show_minmax_mod"], bool)
|
||||||
|
assert isinstance(options["show_minmax_eval"], bool)
|
||||||
|
assert isinstance(options["show_coef"], bool)
|
||||||
|
assert isinstance(options["show_ue_cap_details"], bool)
|
||||||
|
assert isinstance(options["show_ue_cap_current"], bool)
|
||||||
|
assert isinstance(options["show_temporary"], bool)
|
||||||
|
assert isinstance(options["temporary_txt"], str)
|
||||||
|
assert isinstance(options["show_uevalid"], bool)
|
||||||
|
assert isinstance(options["show_date_inscr"], bool)
|
||||||
|
|
||||||
|
bulletin_ressources = bul["ressources"]
|
||||||
|
assert isinstance(bulletin_ressources, dict)
|
||||||
|
|
||||||
|
for ressource in bulletin_ressources.values():
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
ressource, BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(ressource, dict)
|
||||||
|
assert isinstance(ressource["evaluations"], list)
|
||||||
|
for evaluation in ressource["evaluations"]:
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["id"], int)
|
||||||
|
assert evaluation["description"] is None or isinstance(
|
||||||
|
evaluation["description"], str
|
||||||
|
)
|
||||||
|
assert evaluation["date"] is None or isinstance(evaluation["date"], str)
|
||||||
|
assert isinstance(evaluation["heure_debut"], str)
|
||||||
|
assert isinstance(evaluation["heure_fin"], str)
|
||||||
|
assert isinstance(evaluation["coef"], str)
|
||||||
|
assert isinstance(evaluation["poids"], dict)
|
||||||
|
assert isinstance(evaluation["note"], dict)
|
||||||
|
assert isinstance(evaluation["url"], str)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["poids"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["poids"]["RT1.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT2.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT3.1"], float)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["note"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["note"]["value"], str)
|
||||||
|
assert isinstance(evaluation["note"]["min"], str)
|
||||||
|
assert isinstance(evaluation["note"]["max"], str)
|
||||||
|
assert isinstance(evaluation["note"]["moy"], str)
|
||||||
|
|
||||||
|
bulletin_saes = bul["saes"]
|
||||||
|
assert isinstance(bulletin_saes, dict)
|
||||||
|
|
||||||
|
for sae in bulletin_saes.values():
|
||||||
|
assert (
|
||||||
|
verify_fields(sae, BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(sae, dict)
|
||||||
|
assert isinstance(sae["evaluations"], list)
|
||||||
|
for evaluation in sae["evaluations"]:
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation,
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["id"], int)
|
||||||
|
assert evaluation["description"] is None or isinstance(
|
||||||
|
evaluation["description"], str
|
||||||
|
)
|
||||||
|
assert evaluation["date"] is None or isinstance(evaluation["date"], str)
|
||||||
|
assert isinstance(evaluation["heure_debut"], str)
|
||||||
|
assert isinstance(evaluation["heure_fin"], str)
|
||||||
|
assert isinstance(evaluation["coef"], str)
|
||||||
|
assert isinstance(evaluation["poids"], dict)
|
||||||
|
assert isinstance(evaluation["note"], dict)
|
||||||
|
assert isinstance(evaluation["url"], str)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["poids"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["poids"]["RT1.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT2.1"], float)
|
||||||
|
assert isinstance(evaluation["poids"]["RT3.1"], float)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
evaluation["note"],
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS,
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(evaluation["note"]["value"], str)
|
||||||
|
assert isinstance(evaluation["note"]["min"], str)
|
||||||
|
assert isinstance(evaluation["note"]["max"], str)
|
||||||
|
assert isinstance(evaluation["note"]["moy"], str)
|
||||||
|
|
||||||
|
bulletin_ues = bul["ues"]
|
||||||
|
assert isinstance(bulletin_ues, dict)
|
||||||
|
|
||||||
|
for (key_ue, value_ue) in bulletin_ues.items():
|
||||||
|
assert verify_fields(value_ue, BULLETIN_UES_UE_FIELDS) is True
|
||||||
|
assert isinstance(value_ue["id"], int)
|
||||||
|
assert isinstance(value_ue["titre"], str)
|
||||||
|
assert isinstance(value_ue["numero"], int)
|
||||||
|
assert isinstance(value_ue["type"], int)
|
||||||
|
assert isinstance(value_ue["color"], str)
|
||||||
|
assert value_ue["competence"] is None or isinstance(
|
||||||
|
value_ue["competence"], str
|
||||||
|
)
|
||||||
|
assert isinstance(value_ue["moyenne"], dict)
|
||||||
|
assert isinstance(value_ue["bonus"], str)
|
||||||
|
assert isinstance(value_ue["malus"], str)
|
||||||
|
assert value_ue["capitalise"] is None or isinstance(
|
||||||
|
value_ue["capitalise"], str
|
||||||
|
)
|
||||||
|
assert isinstance(value_ue["ressources"], dict)
|
||||||
|
assert isinstance(value_ue["saes"], dict)
|
||||||
|
assert isinstance(value_ue["ECTS"], dict)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(value_ue["moyenne"], BULLETIN_UES_UE_MOYENNE_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(value_ue["moyenne"]["value"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["min"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["max"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["moy"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["rang"], str)
|
||||||
|
assert isinstance(value_ue["moyenne"]["total"], int)
|
||||||
|
|
||||||
|
for ressource in value_ue["ressources"].values():
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
ressource, BULLETIN_UES_UE_RESSOURCES_RESSOURCE_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(ressource["id"], int)
|
||||||
|
assert isinstance(ressource["coef"], float)
|
||||||
|
assert isinstance(ressource["moyenne"], str)
|
||||||
|
|
||||||
|
for sae in value_ue["saes"].values():
|
||||||
|
assert verify_fields(sae, BULLETIN_UES_UE_SAES_SAE_FIELDS) is True
|
||||||
|
assert isinstance(sae["id"], int)
|
||||||
|
assert isinstance(sae["coef"], float)
|
||||||
|
assert isinstance(sae["moyenne"], str)
|
||||||
|
|
||||||
|
assert verify_fields(value_ue["ECTS"], BULLETIN_UES_UE_ECTS_FIELDS) is True
|
||||||
|
assert isinstance(value_ue["ECTS"]["acquis"], float)
|
||||||
|
assert isinstance(value_ue["ECTS"]["total"], float)
|
||||||
|
|
||||||
|
bulletin_semestre = bul["semestre"]
|
||||||
|
assert verify_fields(bulletin_semestre, BULLETIN_SEMESTRE_FIELDS) is True
|
||||||
|
assert isinstance(bulletin_semestre["etapes"], list)
|
||||||
|
assert isinstance(bulletin_semestre["date_debut"], str)
|
||||||
|
assert isinstance(bulletin_semestre["date_fin"], str)
|
||||||
|
assert isinstance(bulletin_semestre["annee_universitaire"], str)
|
||||||
|
assert isinstance(bulletin_semestre["numero"], int)
|
||||||
|
assert isinstance(bulletin_semestre["inscription"], str)
|
||||||
|
assert isinstance(bulletin_semestre["groupes"], list)
|
||||||
|
assert isinstance(bulletin_semestre["absences"], dict)
|
||||||
|
assert isinstance(bulletin_semestre["ECTS"], dict)
|
||||||
|
assert isinstance(bulletin_semestre["notes"], dict)
|
||||||
|
assert isinstance(bulletin_semestre["rang"], dict)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(
|
||||||
|
bulletin_semestre["absences"], BULLETIN_SEMESTRE_ABSENCES_FIELDS
|
||||||
|
)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["absences"]["injustifie"], int)
|
||||||
|
assert isinstance(bulletin_semestre["absences"]["total"], int)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["ECTS"], BULLETIN_SEMESTRE_ECTS_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["ECTS"]["acquis"], int)
|
||||||
|
assert isinstance(bulletin_semestre["ECTS"]["total"], float)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["notes"], BULLETIN_SEMESTRE_NOTES_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["value"], str)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["min"], str)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["max"], str)
|
||||||
|
assert isinstance(bulletin_semestre["notes"]["moy"], str)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
verify_fields(bulletin_semestre["rang"], BULLETIN_SEMESTRE_RANG_FIELDS)
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
assert isinstance(bulletin_semestre["rang"]["value"], str)
|
||||||
|
assert isinstance(bulletin_semestre["rang"]["total"], int)
|
||||||
|
|
||||||
|
|
||||||
# # jury
|
# # jury
|
||||||
# def test_jury():
|
# def test_jury():
|
||||||
@ -101,6 +488,141 @@ def test_bulletins(api_headers):
|
|||||||
# assert r.status_code == 200
|
# assert r.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_formsemestre_etudiants(api_headers):
|
||||||
|
"""
|
||||||
|
Route: /formsemestre/<int:formsemestre_id>/etudiants,
|
||||||
|
/formsemestre/<int:formsemestre_id>/etudiants/demissionnaires,
|
||||||
|
/formsemestre/<int:formsemestre_id>/etudiants/defaillants
|
||||||
|
"""
|
||||||
|
formsemestre_id = 1
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{formsemestre_id}/etudiants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
formsemestre_etus = r.json()
|
||||||
|
assert isinstance(formsemestre_etus, list)
|
||||||
|
for etu in formsemestre_etus:
|
||||||
|
assert verify_fields(etu, FORMSEMESTRE_ETUS_FIELDS) is True
|
||||||
|
assert isinstance(etu["id"], int)
|
||||||
|
assert isinstance(etu["nip"], str)
|
||||||
|
assert isinstance(etu["ine"], str)
|
||||||
|
assert isinstance(etu["nom"], str)
|
||||||
|
assert etu["nom_usuel"] is None or isinstance(etu["nom_usuel"], str)
|
||||||
|
assert isinstance(etu["prenom"], str)
|
||||||
|
assert isinstance(etu["civilite"], str)
|
||||||
|
assert isinstance(etu["groups"], list)
|
||||||
|
etu_groups = etu["groups"]
|
||||||
|
for group in etu_groups:
|
||||||
|
assert isinstance(group["partition_id"], int)
|
||||||
|
assert isinstance(group["id"], int)
|
||||||
|
assert isinstance(group["formsemestre_id"], int)
|
||||||
|
assert group["partition_name"] is None or isinstance(
|
||||||
|
group["partition_name"], str
|
||||||
|
)
|
||||||
|
assert isinstance(group["numero"], int)
|
||||||
|
assert isinstance(group["bul_show_rank"], bool)
|
||||||
|
assert isinstance(group["show_in_lists"], bool)
|
||||||
|
assert isinstance(group["group_id"], int)
|
||||||
|
assert group["group_name"] is None or isinstance(group["group_name"], int)
|
||||||
|
|
||||||
|
### demissionnaires ###
|
||||||
|
r_demissionnaires = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{formsemestre_id}/etudiants/demissionnaires",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_demissionnaires.status_code == 200
|
||||||
|
formsemestre_etus = r_demissionnaires.json()
|
||||||
|
assert isinstance(formsemestre_etus, list)
|
||||||
|
|
||||||
|
for etu in formsemestre_etus:
|
||||||
|
assert verify_fields(etu, FORMSEMESTRE_ETUS_FIELDS) is True
|
||||||
|
assert isinstance(etu["id"], int)
|
||||||
|
assert isinstance(etu["nip"], str)
|
||||||
|
assert isinstance(etu["ine"], str)
|
||||||
|
assert isinstance(etu["nom"], str)
|
||||||
|
assert etu["nom_usuel"] is None or isinstance(etu["nom_usuel"], str)
|
||||||
|
assert isinstance(etu["prenom"], str)
|
||||||
|
assert isinstance(etu["civilite"], str)
|
||||||
|
assert isinstance(etu["groups"], list)
|
||||||
|
etu_groups = etu["groups"]
|
||||||
|
for group in etu_groups:
|
||||||
|
assert isinstance(group["partition_id"], int)
|
||||||
|
assert isinstance(group["id"], int)
|
||||||
|
assert isinstance(group["formsemestre_id"], int)
|
||||||
|
assert group["partition_name"] is None or isinstance(
|
||||||
|
group["partition_name"], str
|
||||||
|
)
|
||||||
|
assert isinstance(group["numero"], int)
|
||||||
|
assert isinstance(group["bul_show_rank"], bool)
|
||||||
|
assert isinstance(group["show_in_lists"], bool)
|
||||||
|
assert isinstance(group["group_id"], int)
|
||||||
|
assert group["group_name"] is None or isinstance(group["group_name"], int)
|
||||||
|
|
||||||
|
### defaillants ###
|
||||||
|
r_defaillants = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{formsemestre_id}/etudiants/defaillants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_defaillants.status_code == 200
|
||||||
|
|
||||||
|
formsemestre_etus = r_defaillants.json()
|
||||||
|
assert isinstance(formsemestre_etus, list)
|
||||||
|
for etu in formsemestre_etus:
|
||||||
|
assert verify_fields(etu, FORMSEMESTRE_ETUS_FIELDS) is True
|
||||||
|
assert isinstance(etu["id"], int)
|
||||||
|
assert isinstance(etu["nip"], str)
|
||||||
|
assert isinstance(etu["ine"], str)
|
||||||
|
assert isinstance(etu["nom"], str)
|
||||||
|
assert etu["nom_usuel"] is None or isinstance(etu["nom_usuel"], str)
|
||||||
|
assert isinstance(etu["prenom"], str)
|
||||||
|
assert isinstance(etu["civilite"], str)
|
||||||
|
assert isinstance(etu["groups"], list)
|
||||||
|
etu_groups = etu["groups"]
|
||||||
|
for group in etu_groups:
|
||||||
|
assert isinstance(group["partition_id"], int)
|
||||||
|
assert isinstance(group["id"], int)
|
||||||
|
assert isinstance(group["formsemestre_id"], int)
|
||||||
|
assert group["partition_name"] is None or isinstance(
|
||||||
|
group["partition_name"], str
|
||||||
|
)
|
||||||
|
assert isinstance(group["numero"], int)
|
||||||
|
assert isinstance(group["bul_show_rank"], bool)
|
||||||
|
assert isinstance(group["show_in_lists"], bool)
|
||||||
|
assert isinstance(group["group_id"], int)
|
||||||
|
assert group["group_name"] is None or isinstance(group["group_name"], int)
|
||||||
|
|
||||||
|
assert r.json() != r_demissionnaires.json()
|
||||||
|
assert r.json() != r_defaillants.json()
|
||||||
|
assert r_demissionnaires.json() != r_defaillants.json()
|
||||||
|
|
||||||
|
### ERROR ###
|
||||||
|
id_formsemestre_inexistant = 265165689619851621685
|
||||||
|
r_error = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{id_formsemestre_inexistant}/etudiants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error.status_code == 404
|
||||||
|
|
||||||
|
r_error_demissionnaires = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{id_formsemestre_inexistant}/etudiants/demissionnaires",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error_demissionnaires.status_code == 404
|
||||||
|
|
||||||
|
r_error_defaillants = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{id_formsemestre_inexistant}/etudiants/defaillants",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_error_defaillants.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_formsemestre_programme(api_headers):
|
def test_formsemestre_programme(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /formsemestre/1/programme
|
Route: /formsemestre/1/programme
|
||||||
@ -131,3 +653,122 @@ def test_formsemestre_programme(api_headers):
|
|||||||
assert verify_fields(modules[0], MODIMPL_FIELDS)
|
assert verify_fields(modules[0], MODIMPL_FIELDS)
|
||||||
assert verify_fields(ressource, MODIMPL_FIELDS)
|
assert verify_fields(ressource, MODIMPL_FIELDS)
|
||||||
assert verify_fields(sae, MODIMPL_FIELDS)
|
assert verify_fields(sae, MODIMPL_FIELDS)
|
||||||
|
|
||||||
|
|
||||||
|
def test_etat_evals(
|
||||||
|
api_headers,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Route : /formsemestre/<int:formsemestre_id>/etat_evals
|
||||||
|
"""
|
||||||
|
r = requests.get(
|
||||||
|
API_URL + "/formsemestre/1/etat_evals",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
etat_evals = r.json()
|
||||||
|
|
||||||
|
assert len(etat_evals) == 3
|
||||||
|
|
||||||
|
for ue in etat_evals.values():
|
||||||
|
for module in ue:
|
||||||
|
assert isinstance(module["id"], int)
|
||||||
|
assert isinstance(module["titre"], str)
|
||||||
|
assert isinstance(module["evaluations"], list)
|
||||||
|
|
||||||
|
for eval in module["evaluations"]:
|
||||||
|
assert verify_fields(eval, EVAL_FIELDS)
|
||||||
|
assert isinstance(eval["id"], int)
|
||||||
|
assert eval["description"] is None or isinstance(
|
||||||
|
eval["description"], str
|
||||||
|
)
|
||||||
|
assert eval["datetime_epreuve"] is None or isinstance(
|
||||||
|
eval["datetime_epreuve"], str
|
||||||
|
)
|
||||||
|
assert isinstance(eval["heure_fin"], str)
|
||||||
|
assert isinstance(eval["coefficient"], float)
|
||||||
|
assert isinstance(eval["comptee"], str)
|
||||||
|
assert isinstance(eval["inscrits"], int)
|
||||||
|
assert isinstance(eval["manquantes"], int)
|
||||||
|
assert isinstance(eval["ABS"], int)
|
||||||
|
assert isinstance(eval["ATT"], int)
|
||||||
|
assert isinstance(eval["EXC"], int)
|
||||||
|
assert isinstance(eval["saisie_notes"], dict)
|
||||||
|
|
||||||
|
list_eval_id = [e["id"] for e in module["evaluations"]]
|
||||||
|
all_unique = True
|
||||||
|
for id in list_eval_id:
|
||||||
|
if list_eval_id.count(id) > 1:
|
||||||
|
all_unique = False
|
||||||
|
assert all_unique is True
|
||||||
|
|
||||||
|
saisie_notes = eval["saisie_notes"]
|
||||||
|
assert verify_fields(saisie_notes, SAISIE_NOTES_FIELDS)
|
||||||
|
assert eval["saisie_notes"]["datetime_debut"] is None or isinstance(
|
||||||
|
eval["saisie_notes"]["datetime_debut"], str
|
||||||
|
)
|
||||||
|
assert eval["saisie_notes"]["datetime_debut"] is None or isinstance(
|
||||||
|
eval["saisie_notes"]["datetime_fin"], str
|
||||||
|
)
|
||||||
|
assert eval["saisie_notes"]["datetime_debut"] is None or isinstance(
|
||||||
|
eval["saisie_notes"]["datetime_mediane"], str
|
||||||
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
eval["saisie_notes"]["datetime_fin"] is not None
|
||||||
|
and eval["saisie_notes"]["datetime_mediane"] is not None
|
||||||
|
and eval["saisie_notes"]["datetime_debut"] is not None
|
||||||
|
):
|
||||||
|
assert (
|
||||||
|
eval["saisie_notes"]["datetime_fin"]
|
||||||
|
> eval["saisie_notes"]["datetime_mediane"]
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
eval["saisie_notes"]["datetime_fin"]
|
||||||
|
> eval["saisie_notes"]["datetime_debut"]
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
eval["saisie_notes"]["datetime_mediane"]
|
||||||
|
> eval["saisie_notes"]["datetime_debut"]
|
||||||
|
)
|
||||||
|
|
||||||
|
list_id_ue1 = []
|
||||||
|
list_titre_ue1 = []
|
||||||
|
|
||||||
|
list_id_ue2 = []
|
||||||
|
list_titre_ue2 = []
|
||||||
|
|
||||||
|
list_id_ue3 = []
|
||||||
|
list_titre_ue3 = []
|
||||||
|
i = 0
|
||||||
|
for ue in etat_evals.values():
|
||||||
|
i += 1
|
||||||
|
for module in ue:
|
||||||
|
if i == 1:
|
||||||
|
list_id_ue1.append(module["id"])
|
||||||
|
list_titre_ue1.append(module["id"])
|
||||||
|
elif i == 2:
|
||||||
|
list_id_ue2.append(module["id"])
|
||||||
|
list_titre_ue2.append(module["id"])
|
||||||
|
elif i == 3:
|
||||||
|
list_id_ue3.append(module["id"])
|
||||||
|
list_titre_ue3.append(module["id"])
|
||||||
|
|
||||||
|
assert list_id_ue1 != list_id_ue2
|
||||||
|
assert list_id_ue1 != list_titre_ue3
|
||||||
|
assert list_id_ue2 != list_titre_ue3
|
||||||
|
|
||||||
|
assert list_titre_ue1 != list_titre_ue2
|
||||||
|
assert list_titre_ue1 != list_titre_ue3
|
||||||
|
assert list_titre_ue2 != list_titre_ue3
|
||||||
|
|
||||||
|
##### ERROR #####
|
||||||
|
fake_eval_id = 153165161656849846516511321651651
|
||||||
|
r = requests.get(
|
||||||
|
f"{API_URL}/formsemestre/{fake_eval_id}/etat_evals",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r.status_code == 404
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""Test API Jurys XXX TODO A ECRIRE
|
"""Test Logos
|
||||||
|
|
||||||
Utilisation :
|
Utilisation :
|
||||||
créer les variables d'environnement: (indiquer les valeurs
|
créer les variables d'environnement: (indiquer les valeurs
|
||||||
@ -24,10 +24,13 @@ from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
|||||||
|
|
||||||
def test_jury_preparation(api_headers):
|
def test_jury_preparation(api_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Test 'jury_preparation'
|
||||||
|
|
||||||
|
Route :
|
||||||
|
- /jury/formsemestre/<int:formsemestre_id>/preparation_jury
|
||||||
"""
|
"""
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
SCODOC_URL
|
API_URL
|
||||||
+ "/ScoDoc/api/jury/formsemestre/<int:formsemestre_id>/preparation_jury",
|
+ "/ScoDoc/api/jury/formsemestre/<int:formsemestre_id>/preparation_jury",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
@ -37,7 +40,10 @@ def test_jury_preparation(api_headers):
|
|||||||
|
|
||||||
def test_jury_decisions(api_headers):
|
def test_jury_decisions(api_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Test 'jury_decisions'
|
||||||
|
|
||||||
|
Route :
|
||||||
|
- /jury/formsemestre/<int:formsemestre_id>/decisions_jury
|
||||||
"""
|
"""
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/jury/formsemestre/<int:formsemestre_id>/decisions_jury",
|
API_URL + "/jury/formsemestre/<int:formsemestre_id>/decisions_jury",
|
||||||
@ -45,62 +51,3 @@ def test_jury_decisions(api_headers):
|
|||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
# set_decision_jury
|
|
||||||
def test_set_decision_jury(api_headers):
|
|
||||||
r = requests.get(
|
|
||||||
SCODOC_URL
|
|
||||||
+ "/ScoDoc/api/jury/set_decision/etudid?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
|
|
||||||
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
|
|
||||||
r = requests.get(
|
|
||||||
SCODOC_URL
|
|
||||||
+ "/ScoDoc/api/jury/set_decision/nip?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
|
|
||||||
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
|
|
||||||
r = requests.get(
|
|
||||||
SCODOC_URL
|
|
||||||
+ "/ScoDoc/api/jury/set_decision/ine?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
|
|
||||||
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>",
|
|
||||||
headers=api_headers,
|
|
||||||
verify=CHECK_CERTIFICATE,
|
|
||||||
)
|
|
||||||
assert r.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
# def test_annule_decision_jury(api_headers):
|
|
||||||
# """
|
|
||||||
# Route:
|
|
||||||
# """
|
|
||||||
# r = requests.get(
|
|
||||||
# SCODOC_URL
|
|
||||||
# + "/ScoDoc/api/jury/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/annule_decision",
|
|
||||||
# headers=api_headers,
|
|
||||||
# verify=CHECK_CERTIFICATE,
|
|
||||||
# )
|
|
||||||
# assert r.status_code == 200
|
|
||||||
|
|
||||||
# r = requests.get(
|
|
||||||
# SCODOC_URL
|
|
||||||
# + "/ScoDoc/api/jury/nip/<int:nip>/formsemestre/<int:formsemestre_id>/annule_decision",
|
|
||||||
# headers=api_headers,
|
|
||||||
# verify=CHECK_CERTIFICATE,
|
|
||||||
# )
|
|
||||||
# assert r.status_code == 200
|
|
||||||
|
|
||||||
# r = requests.get(
|
|
||||||
# SCODOC_URL
|
|
||||||
# + "/ScoDoc/api/jury/ine/<int:ine>/formsemestre/<int:formsemestre_id>/annule_decision",
|
|
||||||
# headers=api_headers,
|
|
||||||
# verify=CHECK_CERTIFICATE,
|
|
||||||
# )
|
|
||||||
# assert r.status_code == 200
|
|
||||||
|
@ -20,103 +20,164 @@ Utilisation :
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
|
||||||
from tests.api.tools_test_api import verify_fields
|
from tests.api.tools_test_api import (
|
||||||
|
verify_fields,
|
||||||
|
PARTITIONS_FIELDS,
|
||||||
|
PARTITIONS_GROUPS_ETU_FIELDS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_partition(api_headers):
|
def test_partition(api_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Test 'partition'
|
||||||
"""
|
|
||||||
fields = [
|
|
||||||
"partition_id",
|
|
||||||
"id",
|
|
||||||
"formsemestre_id",
|
|
||||||
"partition_name",
|
|
||||||
"numero",
|
|
||||||
"bul_show_rank",
|
|
||||||
"show_in_lists",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
Route :
|
||||||
|
- /partitions/<int:formsemestre_id>
|
||||||
|
"""
|
||||||
|
partition_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/partitions/1",
|
f"{API_URL}/partitions/{partition_id}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
partitions = r.json()
|
partitions = r.json()
|
||||||
assert len(partitions) == 1
|
assert len(partitions) == 1
|
||||||
|
assert isinstance(partitions, list)
|
||||||
partition = partitions[0]
|
partition = partitions[0]
|
||||||
fields_ok = verify_fields(partition, fields)
|
assert isinstance(partition, dict)
|
||||||
assert fields_ok is True
|
assert verify_fields(partition, PARTITIONS_FIELDS) is True
|
||||||
|
assert partition_id == partition["partition_id"]
|
||||||
|
|
||||||
|
assert isinstance(partition["partition_id"], int)
|
||||||
|
assert isinstance(partition["id"], int)
|
||||||
|
assert isinstance(partition["formsemestre_id"], int)
|
||||||
|
assert partition["partition_name"] is None or isinstance(
|
||||||
|
partition["partition_name"], str
|
||||||
|
)
|
||||||
|
assert isinstance(partition["numero"], int)
|
||||||
|
assert isinstance(partition["bul_show_rank"], bool)
|
||||||
|
assert isinstance(partition["show_in_lists"], bool)
|
||||||
|
|
||||||
|
|
||||||
def test_etud_in_group(api_headers):
|
def test_etud_in_group(api_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Test 'etud_in_group'
|
||||||
"""
|
|
||||||
fields = [
|
|
||||||
"etudid",
|
|
||||||
"id",
|
|
||||||
"dept_id",
|
|
||||||
"nom",
|
|
||||||
"prenom",
|
|
||||||
"nom_usuel",
|
|
||||||
"civilite",
|
|
||||||
"date_naissance",
|
|
||||||
"lieu_naissance",
|
|
||||||
"dept_naissance",
|
|
||||||
"nationalite",
|
|
||||||
"statut",
|
|
||||||
"boursier",
|
|
||||||
"photo_filename",
|
|
||||||
"code_nip",
|
|
||||||
"code_ine",
|
|
||||||
"scodoc7_id",
|
|
||||||
"email",
|
|
||||||
"emailperso",
|
|
||||||
"domicile",
|
|
||||||
"codepostaldomicile",
|
|
||||||
"villedomicile",
|
|
||||||
"paysdomicile",
|
|
||||||
"telephone",
|
|
||||||
"telephonemobile",
|
|
||||||
"fax",
|
|
||||||
"typeadresse",
|
|
||||||
"description",
|
|
||||||
"group_id",
|
|
||||||
"etat",
|
|
||||||
"civilite_str",
|
|
||||||
"nom_disp",
|
|
||||||
"nomprenom",
|
|
||||||
"ne",
|
|
||||||
"email_default",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
Routes :
|
||||||
|
- /partition/group/<int:group_id>
|
||||||
|
- /partition/group/<int:group_id>/etat/<string:etat>
|
||||||
|
"""
|
||||||
|
group_id = 1
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
API_URL + "/partitions/groups/1",
|
f"{API_URL}/partition/group/{group_id}",
|
||||||
headers=api_headers,
|
headers=api_headers,
|
||||||
verify=CHECK_CERTIFICATE,
|
verify=CHECK_CERTIFICATE,
|
||||||
)
|
)
|
||||||
|
|
||||||
etu = r.json()[0]
|
|
||||||
|
|
||||||
fields_ok = verify_fields(etu, fields)
|
|
||||||
|
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert len(r.json()) == 16
|
assert isinstance(r.json(), list)
|
||||||
assert fields_ok is True
|
|
||||||
# r = requests.get(
|
for etu in r.json():
|
||||||
# API_URL + "/partitions/groups/1/etat/<string:etat>",
|
assert verify_fields(etu, PARTITIONS_GROUPS_ETU_FIELDS)
|
||||||
# headers=api_headers,
|
assert isinstance(etu["etudid"], int)
|
||||||
# verify=CHECK_CERTIFICATE,
|
assert isinstance(etu["id"], int)
|
||||||
# )
|
assert isinstance(etu["dept_id"], int)
|
||||||
# assert r.status_code == 200
|
assert isinstance(etu["nom"], str)
|
||||||
|
assert isinstance(etu["prenom"], str)
|
||||||
|
assert isinstance(etu["nom_usuel"], str)
|
||||||
|
assert isinstance(etu["civilite"], str)
|
||||||
|
assert etu["date_naissance"] is None or isinstance(etu["date_naissance"], str)
|
||||||
|
assert etu["lieu_naissance"] is None or isinstance(etu["lieu_naissance"], str)
|
||||||
|
assert etu["dept_naissance"] is None or isinstance(etu["dept_naissance"], str)
|
||||||
|
assert etu["nationalite"] is None or isinstance(etu["nationalite"], str)
|
||||||
|
assert etu["statut"] is None or isinstance(etu["statut"], str)
|
||||||
|
assert etu["boursier"] is None or isinstance(etu["boursier"], bool)
|
||||||
|
assert etu["photo_filename"] is None or isinstance(etu["photo_filename"], str)
|
||||||
|
assert isinstance(etu["code_nip"], str)
|
||||||
|
assert isinstance(etu["code_ine"], str)
|
||||||
|
assert etu["scodoc7_id"] is None or isinstance(etu["scodoc7_id"], int)
|
||||||
|
assert isinstance(etu["email"], str)
|
||||||
|
assert etu["emailperso"] is None or isinstance(etu["emailperso"], str)
|
||||||
|
assert etu["domicile"] is None or isinstance(etu["domicile"], str)
|
||||||
|
assert etu["codepostaldomicile"] is None or isinstance(
|
||||||
|
etu["codepostaldomicile"], str
|
||||||
|
)
|
||||||
|
assert etu["villedomicile"] is None or isinstance(etu["villedomicile"], str)
|
||||||
|
assert etu["paysdomicile"] is None or isinstance(etu["paysdomicile"], str)
|
||||||
|
assert etu["telephone"] is None or isinstance(etu["telephone"], str)
|
||||||
|
assert etu["telephonemobile"] is None or isinstance(etu["telephonemobile"], str)
|
||||||
|
assert etu["fax"] is None or isinstance(etu["fax"], str)
|
||||||
|
assert isinstance(etu["typeadresse"], str)
|
||||||
|
assert etu["description"] is None or isinstance(etu["description"], int)
|
||||||
|
assert isinstance(etu["group_id"], int)
|
||||||
|
assert isinstance(etu["etat"], str)
|
||||||
|
assert isinstance(etu["civilite_str"], str)
|
||||||
|
assert isinstance(etu["nom_disp"], str)
|
||||||
|
assert isinstance(etu["nomprenom"], str)
|
||||||
|
assert isinstance(etu["ne"], str)
|
||||||
|
assert isinstance(etu["email_default"], str)
|
||||||
|
|
||||||
|
etat = "I"
|
||||||
|
r_etat = requests.get(
|
||||||
|
f"{API_URL}/partition/group/{group_id}/etat/{etat}",
|
||||||
|
headers=api_headers,
|
||||||
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert r_etat.status_code == 200
|
||||||
|
|
||||||
|
assert isinstance(r_etat.json(), list)
|
||||||
|
|
||||||
|
for etu in r_etat.json():
|
||||||
|
assert verify_fields(etu, PARTITIONS_GROUPS_ETU_FIELDS)
|
||||||
|
assert isinstance(etu["etudid"], int)
|
||||||
|
assert isinstance(etu["id"], int)
|
||||||
|
assert isinstance(etu["dept_id"], int)
|
||||||
|
assert isinstance(etu["nom"], str)
|
||||||
|
assert isinstance(etu["prenom"], str)
|
||||||
|
assert isinstance(etu["nom_usuel"], str)
|
||||||
|
assert isinstance(etu["civilite"], str)
|
||||||
|
assert etu["date_naissance"] is None or isinstance(etu["date_naissance"], str)
|
||||||
|
assert etu["lieu_naissance"] is None or isinstance(etu["lieu_naissance"], str)
|
||||||
|
assert etu["dept_naissance"] is None or isinstance(etu["dept_naissance"], str)
|
||||||
|
assert etu["nationalite"] is None or isinstance(etu["nationalite"], str)
|
||||||
|
assert etu["statut"] is None or isinstance(etu["statut"], str)
|
||||||
|
assert etu["boursier"] is None or isinstance(etu["boursier"], bool)
|
||||||
|
assert etu["photo_filename"] is None or isinstance(etu["photo_filename"], str)
|
||||||
|
assert isinstance(etu["code_nip"], str)
|
||||||
|
assert isinstance(etu["code_ine"], str)
|
||||||
|
assert etu["scodoc7_id"] is None or isinstance(etu["scodoc7_id"], int)
|
||||||
|
assert isinstance(etu["email"], str)
|
||||||
|
assert etu["emailperso"] is None or isinstance(etu["emailperso"], str)
|
||||||
|
assert etu["domicile"] is None or isinstance(etu["domicile"], str)
|
||||||
|
assert etu["codepostaldomicile"] is None or isinstance(
|
||||||
|
etu["codepostaldomicile"], str
|
||||||
|
)
|
||||||
|
assert etu["villedomicile"] is None or isinstance(etu["villedomicile"], str)
|
||||||
|
assert etu["paysdomicile"] is None or isinstance(etu["paysdomicile"], str)
|
||||||
|
assert etu["telephone"] is None or isinstance(etu["telephone"], str)
|
||||||
|
assert etu["telephonemobile"] is None or isinstance(etu["telephonemobile"], str)
|
||||||
|
assert etu["fax"] is None or isinstance(etu["fax"], str)
|
||||||
|
assert isinstance(etu["typeadresse"], str)
|
||||||
|
assert etu["description"] is None or isinstance(etu["description"], int)
|
||||||
|
assert isinstance(etu["group_id"], int)
|
||||||
|
assert isinstance(etu["etat"], str)
|
||||||
|
assert isinstance(etu["civilite_str"], str)
|
||||||
|
assert isinstance(etu["nom_disp"], str)
|
||||||
|
assert isinstance(etu["nomprenom"], str)
|
||||||
|
assert isinstance(etu["ne"], str)
|
||||||
|
assert isinstance(etu["email_default"], str)
|
||||||
|
|
||||||
|
assert etat == etu["etat"]
|
||||||
|
|
||||||
|
|
||||||
# # set_groups
|
# # set_groups
|
||||||
# def test_set_groups(api_headers):
|
# def test_set_groups(api_headers):
|
||||||
# """
|
# """
|
||||||
# Route:
|
# Test 'set_groups'
|
||||||
|
#
|
||||||
|
# Routes :
|
||||||
|
# - /partitions/set_groups/partition/<int:partition_id>/groups/<string:groups_id>/delete/<string:groups_to_delete>"
|
||||||
|
# "/create/<string:groups_to_create>
|
||||||
# """
|
# """
|
||||||
# r = requests.get(
|
# r = requests.get(
|
||||||
# SCODOC_URL
|
# SCODOC_URL
|
||||||
|
@ -29,7 +29,7 @@ def test_permissions(api_headers):
|
|||||||
# Ce test va récupérer toutes les routes de l'API
|
# Ce test va récupérer toutes les routes de l'API
|
||||||
app = create_app(RunningConfig)
|
app = create_app(RunningConfig)
|
||||||
assert app
|
assert app
|
||||||
# Les routes de l'API avec GET, excluant les logos pour le momeent XXX
|
# Les routes de l'API avec GET, excluant les logos pour le moment XXX
|
||||||
api_rules = [
|
api_rules = [
|
||||||
r
|
r
|
||||||
for r in app.url_map.iter_rules()
|
for r in app.url_map.iter_rules()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Utilitaires pour les tests de l'API
|
"""Utilitaires pour les tests de l'API
|
||||||
"""
|
"""
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
def verify_fields(json_response: dict, expected_fields: set) -> bool:
|
def verify_fields(json_response: dict, expected_fields: set) -> bool:
|
||||||
@ -14,6 +15,40 @@ def verify_fields(json_response: dict, expected_fields: set) -> bool:
|
|||||||
return all(field in json_response for field in expected_fields)
|
return all(field in json_response for field in expected_fields)
|
||||||
|
|
||||||
|
|
||||||
|
def verify_occurences_ids_etus(json_response) -> bool:
|
||||||
|
"""
|
||||||
|
Vérifie si il n'y a pas deux fois le même id dans la liste d'étudiant donnée en paramètres
|
||||||
|
|
||||||
|
json_response : la réponse de la requête
|
||||||
|
|
||||||
|
Retourne True ou False
|
||||||
|
"""
|
||||||
|
list_etu = json.loads(json_response)
|
||||||
|
|
||||||
|
list_ids = [etu["id"] for etu in list_etu]
|
||||||
|
list_nip = [etu["nip"] for etu in list_etu]
|
||||||
|
list_ine = [etu["ine"] for etu in list_etu]
|
||||||
|
|
||||||
|
for id in list_ids:
|
||||||
|
if list_ids.count(id) > 1:
|
||||||
|
return False
|
||||||
|
for nip in list_nip:
|
||||||
|
if list_nip.count(nip) > 1:
|
||||||
|
return False
|
||||||
|
for ine in list_ine:
|
||||||
|
if list_ine.count(ine) > 1:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
DEPARTEMENT_FIELDS = [
|
||||||
|
"id",
|
||||||
|
"acronym",
|
||||||
|
"description",
|
||||||
|
"visible",
|
||||||
|
"date_creation",
|
||||||
|
]
|
||||||
|
|
||||||
ETUD_FIELDS = {
|
ETUD_FIELDS = {
|
||||||
"boursier",
|
"boursier",
|
||||||
"civilite",
|
"civilite",
|
||||||
@ -43,12 +78,12 @@ ETUD_FIELDS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FORMATION_FIELDS = {
|
FORMATION_FIELDS = {
|
||||||
"id",
|
"dept_id",
|
||||||
"acronyme",
|
"acronyme",
|
||||||
"titre_officiel",
|
"titre_officiel",
|
||||||
"formation_code",
|
"formation_code",
|
||||||
"code_specialite",
|
"code_specialite",
|
||||||
"dept_id",
|
"id",
|
||||||
"titre",
|
"titre",
|
||||||
"version",
|
"version",
|
||||||
"type_parcours",
|
"type_parcours",
|
||||||
@ -56,6 +91,92 @@ FORMATION_FIELDS = {
|
|||||||
"formation_id",
|
"formation_id",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORMATION_EXPORT_FIELDS = {
|
||||||
|
"dept_id",
|
||||||
|
"acronyme",
|
||||||
|
"titre_officiel",
|
||||||
|
"formation_code",
|
||||||
|
"code_specialite",
|
||||||
|
"id",
|
||||||
|
"titre",
|
||||||
|
"version",
|
||||||
|
"type_parcours",
|
||||||
|
"referentiel_competence_id",
|
||||||
|
"formation_id",
|
||||||
|
"ue",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMATION_EXPORT_UE_FIELDS = {
|
||||||
|
"acronyme",
|
||||||
|
"numero",
|
||||||
|
"titre",
|
||||||
|
"type",
|
||||||
|
"ue_code",
|
||||||
|
"ects",
|
||||||
|
"is_external",
|
||||||
|
"code_apogee",
|
||||||
|
"coefficient",
|
||||||
|
"semestre_idx",
|
||||||
|
"color",
|
||||||
|
"reference",
|
||||||
|
"matiere",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMATION_EXPORT_UE_MATIERE_FIELDS = {
|
||||||
|
"titre",
|
||||||
|
"numero",
|
||||||
|
"module",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMATION_EXPORT_UE_MATIERE_MODULE_FIELDS = {
|
||||||
|
"titre",
|
||||||
|
"abbrev",
|
||||||
|
"code",
|
||||||
|
"heures_cours",
|
||||||
|
"heures_td",
|
||||||
|
"coefficient",
|
||||||
|
"ects",
|
||||||
|
"semestre_id",
|
||||||
|
"numero",
|
||||||
|
"code_apogee",
|
||||||
|
"module_type",
|
||||||
|
"coefficients",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMATION_EXPORT_UE_MATIERE_MODULE_COEF_FIELDS = {
|
||||||
|
"ue_reference",
|
||||||
|
"coef",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMSEMESTRE_FIELDS = [
|
||||||
|
"titre",
|
||||||
|
"gestion_semestrielle",
|
||||||
|
"scodoc7_id",
|
||||||
|
"date_debut",
|
||||||
|
"bul_bgcolor",
|
||||||
|
"date_fin",
|
||||||
|
"resp_can_edit",
|
||||||
|
"dept_id",
|
||||||
|
"etat",
|
||||||
|
"resp_can_change_ens",
|
||||||
|
"id",
|
||||||
|
"modalite",
|
||||||
|
"ens_can_edit_eval",
|
||||||
|
"formation_id",
|
||||||
|
"gestion_compensation",
|
||||||
|
"elt_sem_apo",
|
||||||
|
"semestre_id",
|
||||||
|
"bul_hide_xml",
|
||||||
|
"elt_annee_apo",
|
||||||
|
"block_moyennes",
|
||||||
|
"formsemestre_id",
|
||||||
|
"titre_num",
|
||||||
|
"titre_formation",
|
||||||
|
"date_debut_iso",
|
||||||
|
"date_fin_iso",
|
||||||
|
"responsables",
|
||||||
|
]
|
||||||
|
|
||||||
FSEM_FIELDS = {
|
FSEM_FIELDS = {
|
||||||
"block_moyennes",
|
"block_moyennes",
|
||||||
"bul_bgcolor",
|
"bul_bgcolor",
|
||||||
@ -131,3 +252,468 @@ UE_FIELDS = {
|
|||||||
"color",
|
"color",
|
||||||
"ue_id",
|
"ue_id",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BULLETIN_FIELDS = {
|
||||||
|
"version",
|
||||||
|
"type",
|
||||||
|
"date",
|
||||||
|
"publie",
|
||||||
|
"etudiant",
|
||||||
|
"formation",
|
||||||
|
"formsemestre_id",
|
||||||
|
"etat_inscription",
|
||||||
|
"options",
|
||||||
|
"ressources",
|
||||||
|
"saes",
|
||||||
|
"ues",
|
||||||
|
"semestre",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BULLETIN_ETUDIANT_FIELDS = {
|
||||||
|
"civilite",
|
||||||
|
"code_ine",
|
||||||
|
"code_nip",
|
||||||
|
"date_naissance",
|
||||||
|
"dept_id",
|
||||||
|
"dept_acronym",
|
||||||
|
"email",
|
||||||
|
"emailperso",
|
||||||
|
"etudid",
|
||||||
|
"nom",
|
||||||
|
"prenom",
|
||||||
|
"nomprenom",
|
||||||
|
"lieu_naissance",
|
||||||
|
"dept_naissance",
|
||||||
|
"nationalite",
|
||||||
|
"boursier",
|
||||||
|
"fiche_url",
|
||||||
|
"photo_url",
|
||||||
|
"id",
|
||||||
|
"domicile",
|
||||||
|
"villedomicile",
|
||||||
|
"telephone",
|
||||||
|
"fax",
|
||||||
|
"description",
|
||||||
|
"codepostaldomicile",
|
||||||
|
"paysdomicile",
|
||||||
|
"telephonemobile",
|
||||||
|
"typeadresse",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_FORMATION_FIELDS = {"id", "acronyme", "titre_officiel", "titre"}
|
||||||
|
|
||||||
|
BULLETIN_OPTIONS_FIELDS = {
|
||||||
|
"show_abs",
|
||||||
|
"show_abs_modules",
|
||||||
|
"show_ects",
|
||||||
|
"show_codemodules",
|
||||||
|
"show_matieres",
|
||||||
|
"show_rangs",
|
||||||
|
"show_ue_rangs",
|
||||||
|
"show_mod_rangs",
|
||||||
|
"show_moypromo",
|
||||||
|
"show_minmax",
|
||||||
|
"show_minmax_mod",
|
||||||
|
"show_minmax_eval",
|
||||||
|
"show_coef",
|
||||||
|
"show_ue_cap_details",
|
||||||
|
"show_ue_cap_current",
|
||||||
|
"show_temporary",
|
||||||
|
"temporary_txt",
|
||||||
|
"show_uevalid",
|
||||||
|
"show_date_inscr",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_RESSOURCES_FIELDS = {
|
||||||
|
"R101",
|
||||||
|
"R102",
|
||||||
|
"R103",
|
||||||
|
"R104",
|
||||||
|
"R105",
|
||||||
|
"R106",
|
||||||
|
"R107",
|
||||||
|
"R108",
|
||||||
|
"R109",
|
||||||
|
"R110",
|
||||||
|
"R111",
|
||||||
|
"R112",
|
||||||
|
"R113",
|
||||||
|
"R114",
|
||||||
|
"R115",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_SAES_FIELDS = {
|
||||||
|
"SAE11",
|
||||||
|
"SAE12",
|
||||||
|
"SAE13",
|
||||||
|
"SAE14",
|
||||||
|
"SAE15",
|
||||||
|
"SAE16",
|
||||||
|
}
|
||||||
|
|
||||||
|
########### RESSOURCES ET SAES ###########
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"titre",
|
||||||
|
"code_apogee",
|
||||||
|
"url",
|
||||||
|
"moyenne",
|
||||||
|
"evaluations",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"description",
|
||||||
|
"date",
|
||||||
|
"heure_debut",
|
||||||
|
"heure_fin",
|
||||||
|
"coef",
|
||||||
|
"poids",
|
||||||
|
"note",
|
||||||
|
"url",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_POIDS_FIELDS = {
|
||||||
|
"RT1.1",
|
||||||
|
"RT2.1",
|
||||||
|
"RT3.1",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_RESSOURCES_ET_SAES_RESSOURCE_ET_SAE_EVALUATION_NOTE_FIELDS = {
|
||||||
|
"value",
|
||||||
|
"min",
|
||||||
|
"max",
|
||||||
|
"moy",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
########### UES ###########
|
||||||
|
BULLETIN_UES_FIELDS = {"RT1.1", "RT2.1", "RT3.1"}
|
||||||
|
|
||||||
|
BULLETIN_UES_UE_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"titre",
|
||||||
|
"numero",
|
||||||
|
"type",
|
||||||
|
"color",
|
||||||
|
"competence",
|
||||||
|
"moyenne",
|
||||||
|
"bonus",
|
||||||
|
"malus",
|
||||||
|
"capitalise",
|
||||||
|
"ressources",
|
||||||
|
"saes",
|
||||||
|
"ECTS",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_UES_UE_MOYENNE_FIELDS = {"value", "min", "max", "moy", "rang", "total"}
|
||||||
|
|
||||||
|
BULLETIN_UES_RT11_RESSOURCES_FIELDS = {
|
||||||
|
"R101",
|
||||||
|
"R102",
|
||||||
|
"R103",
|
||||||
|
"R104",
|
||||||
|
"R106",
|
||||||
|
"R108",
|
||||||
|
"R110",
|
||||||
|
"R111",
|
||||||
|
"R112",
|
||||||
|
"R113",
|
||||||
|
"R114",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_UES_RT21_RESSOURCES_FIELDS = {
|
||||||
|
"R101",
|
||||||
|
"R103",
|
||||||
|
"R104",
|
||||||
|
"R105",
|
||||||
|
"R110",
|
||||||
|
"R111",
|
||||||
|
"R112",
|
||||||
|
"R113",
|
||||||
|
"R114",
|
||||||
|
"R115",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_UES_RT31_RESSOURCES_FIELDS = {
|
||||||
|
"R101",
|
||||||
|
"R107",
|
||||||
|
"R108",
|
||||||
|
"R109",
|
||||||
|
"R110",
|
||||||
|
"R111",
|
||||||
|
"R112",
|
||||||
|
"R115",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_UES_UE_RESSOURCES_RESSOURCE_FIELDS = {"id", "coef", "moyenne"}
|
||||||
|
|
||||||
|
BULLETIN_UES_RT11_SAES_FIELDS = {
|
||||||
|
"SAE11",
|
||||||
|
"SAE12",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_UES_RT21_SAES_FIELDS = {"SAE13"}
|
||||||
|
|
||||||
|
BULLETIN_UES_RT31_SAES_FIELDS = {
|
||||||
|
"SAE14",
|
||||||
|
"SAE15",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_UES_UE_SAES_SAE_FIELDS = {"id", "coef", "moyenne"}
|
||||||
|
|
||||||
|
|
||||||
|
BULLETIN_UES_UE_ECTS_FIELDS = {"acquis", "total"}
|
||||||
|
|
||||||
|
|
||||||
|
########### SEMESTRE ###########
|
||||||
|
BULLETIN_SEMESTRE_FIELDS = {
|
||||||
|
"etapes",
|
||||||
|
"date_debut",
|
||||||
|
"date_fin",
|
||||||
|
"annee_universitaire",
|
||||||
|
"numero",
|
||||||
|
"inscription",
|
||||||
|
"groupes",
|
||||||
|
"absences",
|
||||||
|
"ECTS",
|
||||||
|
"notes",
|
||||||
|
"rang",
|
||||||
|
}
|
||||||
|
|
||||||
|
BULLETIN_SEMESTRE_ABSENCES_FIELDS = {"injustifie", "total"}
|
||||||
|
|
||||||
|
BULLETIN_SEMESTRE_ECTS_FIELDS = {"acquis", "total"}
|
||||||
|
|
||||||
|
BULLETIN_SEMESTRE_NOTES_FIELDS = {"value", "min", "moy", "max"}
|
||||||
|
|
||||||
|
BULLETIN_SEMESTRE_RANG_FIELDS = {"value", "total"}
|
||||||
|
|
||||||
|
|
||||||
|
EVAL_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"description",
|
||||||
|
"datetime_epreuve",
|
||||||
|
"heure_fin",
|
||||||
|
"coefficient",
|
||||||
|
"comptee",
|
||||||
|
"inscrits",
|
||||||
|
"manquantes",
|
||||||
|
"ABS",
|
||||||
|
"ATT",
|
||||||
|
"EXC",
|
||||||
|
"saisie_notes",
|
||||||
|
}
|
||||||
|
|
||||||
|
SAISIE_NOTES_FIELDS = {"datetime_debut", "datetime_fin", "datetime_mediane"}
|
||||||
|
|
||||||
|
REF_COMP_FIELDS = {
|
||||||
|
"dept_id",
|
||||||
|
"annexe",
|
||||||
|
"specialite",
|
||||||
|
"specialite_long",
|
||||||
|
"type_structure",
|
||||||
|
"type_departement",
|
||||||
|
"type_titre",
|
||||||
|
"version_orebut",
|
||||||
|
"scodoc_date_loaded",
|
||||||
|
"scodoc_orig_filename",
|
||||||
|
"competences",
|
||||||
|
"parcours",
|
||||||
|
}
|
||||||
|
|
||||||
|
ABSENCES_FIELDS = {
|
||||||
|
"jour",
|
||||||
|
"matin",
|
||||||
|
"estabs",
|
||||||
|
"estjust",
|
||||||
|
"description",
|
||||||
|
"begin",
|
||||||
|
"end",
|
||||||
|
}
|
||||||
|
|
||||||
|
ABSENCES_GROUP_ETAT_FIELDS = {"etudid", "list_abs"}
|
||||||
|
|
||||||
|
|
||||||
|
FORMSEMESTRE_ETUS_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"nip",
|
||||||
|
"ine",
|
||||||
|
"nom",
|
||||||
|
"nom_usuel",
|
||||||
|
"prenom",
|
||||||
|
"civilite",
|
||||||
|
"groups",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMSEMESTRE_ETUS_GROUPS_FIELDS = {
|
||||||
|
"partition_id",
|
||||||
|
"id",
|
||||||
|
"formsemestre_id",
|
||||||
|
"partition_name",
|
||||||
|
"numero",
|
||||||
|
"bul_show_rank",
|
||||||
|
"show_in_lists",
|
||||||
|
"group_id",
|
||||||
|
"group_name",
|
||||||
|
}
|
||||||
|
|
||||||
|
EVALUATIONS_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"jour",
|
||||||
|
"heure_fin",
|
||||||
|
"note_max",
|
||||||
|
"visibulletin",
|
||||||
|
"evaluation_type",
|
||||||
|
"moduleimpl_id",
|
||||||
|
"heure_debut",
|
||||||
|
"description",
|
||||||
|
"coefficient",
|
||||||
|
"publish_incomplete",
|
||||||
|
"numero",
|
||||||
|
"evaluation_id",
|
||||||
|
"date_debut",
|
||||||
|
"date_fin",
|
||||||
|
"poids",
|
||||||
|
"jouriso",
|
||||||
|
"duree",
|
||||||
|
"descrheure",
|
||||||
|
"matin",
|
||||||
|
"apresmidi",
|
||||||
|
}
|
||||||
|
|
||||||
|
EVALUATION_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"etudid",
|
||||||
|
"evaluation_id",
|
||||||
|
"value",
|
||||||
|
"comment",
|
||||||
|
"date",
|
||||||
|
"uid",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PARTITIONS_FIELDS = {
|
||||||
|
"partition_id",
|
||||||
|
"id",
|
||||||
|
"formsemestre_id",
|
||||||
|
"partition_name",
|
||||||
|
"numero",
|
||||||
|
"bul_show_rank",
|
||||||
|
"show_in_lists",
|
||||||
|
}
|
||||||
|
|
||||||
|
PARTITIONS_GROUPS_ETU_FIELDS = {
|
||||||
|
"etudid",
|
||||||
|
"id",
|
||||||
|
"dept_id",
|
||||||
|
"nom",
|
||||||
|
"prenom",
|
||||||
|
"nom_usuel",
|
||||||
|
"civilite",
|
||||||
|
"date_naissance",
|
||||||
|
"lieu_naissance",
|
||||||
|
"dept_naissance",
|
||||||
|
"nationalite",
|
||||||
|
"statut",
|
||||||
|
"boursier",
|
||||||
|
"photo_filename",
|
||||||
|
"code_nip",
|
||||||
|
"code_ine",
|
||||||
|
"scodoc7_id",
|
||||||
|
"email",
|
||||||
|
"emailperso",
|
||||||
|
"domicile",
|
||||||
|
"codepostaldomicile",
|
||||||
|
"villedomicile",
|
||||||
|
"paysdomicile",
|
||||||
|
"telephone",
|
||||||
|
"telephonemobile",
|
||||||
|
"fax",
|
||||||
|
"typeadresse",
|
||||||
|
"description",
|
||||||
|
"group_id",
|
||||||
|
"etat",
|
||||||
|
"civilite_str",
|
||||||
|
"nom_disp",
|
||||||
|
"nomprenom",
|
||||||
|
"ne",
|
||||||
|
"email_default",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMSEMESTRE_BULLETINS_FIELDS = {
|
||||||
|
"version",
|
||||||
|
"type",
|
||||||
|
"date",
|
||||||
|
"publie",
|
||||||
|
"etudiant",
|
||||||
|
"formation",
|
||||||
|
"formsemestre_id",
|
||||||
|
"etat_inscription",
|
||||||
|
"options",
|
||||||
|
"ressources",
|
||||||
|
"saes",
|
||||||
|
"ues",
|
||||||
|
"semestre",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMSEMESTRE_BULLETINS_ETU_FIELDS = {
|
||||||
|
"civilite",
|
||||||
|
"code_ine",
|
||||||
|
"code_nip",
|
||||||
|
"date_naissance",
|
||||||
|
"dept_id",
|
||||||
|
"dept_acronym",
|
||||||
|
"email",
|
||||||
|
"emailperso",
|
||||||
|
"etudid",
|
||||||
|
"nom",
|
||||||
|
"prenom",
|
||||||
|
"nomprenom",
|
||||||
|
"lieu_naissance",
|
||||||
|
"dept_naissance",
|
||||||
|
"nationalite",
|
||||||
|
"boursier",
|
||||||
|
"fiche_url",
|
||||||
|
"photo_url",
|
||||||
|
"id",
|
||||||
|
"codepostaldomicile",
|
||||||
|
"paysdomicile",
|
||||||
|
"telephonemobile",
|
||||||
|
"typeadresse",
|
||||||
|
"domicile",
|
||||||
|
"villedomicile",
|
||||||
|
"telephone",
|
||||||
|
"fax",
|
||||||
|
"description",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMSEMESTRE_BULLETINS_FORMATION_FIELDS = {
|
||||||
|
"id",
|
||||||
|
"acronyme",
|
||||||
|
"titre_officiel",
|
||||||
|
"titre",
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMSEMESTRE_BULLETINS_OPT_FIELDS = {
|
||||||
|
"show_abs",
|
||||||
|
"show_abs_modules",
|
||||||
|
"show_ects",
|
||||||
|
"show_codemodules",
|
||||||
|
"show_matieres",
|
||||||
|
"show_rangs",
|
||||||
|
"show_ue_rangs",
|
||||||
|
"show_mod_rangs",
|
||||||
|
"show_moypromo",
|
||||||
|
"show_minmax",
|
||||||
|
"show_minmax_mod",
|
||||||
|
"show_minmax_eval",
|
||||||
|
"show_coef",
|
||||||
|
"show_ue_cap_details",
|
||||||
|
"show_ue_cap_current",
|
||||||
|
"show_temporary",
|
||||||
|
"temporary_txt",
|
||||||
|
"show_uevalid",
|
||||||
|
"show_date_inscr",
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
FLASK_DEBUG=1
|
FLASK_DEBUG=1
|
||||||
|
|
||||||
2) En tant qu'utilisateur scodoc, lancer:
|
2) En tant qu'utilisateur scodoc, lancer:
|
||||||
tools/create_database.sh SCODOC_TEST_API
|
tools/create_database.sh
|
||||||
flask db upgrade
|
flask db upgrade
|
||||||
flask sco-db-init --erase
|
flask sco-db-init --erase
|
||||||
flask init-test-database
|
flask init-test-database
|
||||||
@ -24,12 +24,32 @@
|
|||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
import random
|
import random
|
||||||
|
import time
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from app.auth.models import Role, User
|
from app.auth.models import Role, User
|
||||||
from app import models
|
from app import models
|
||||||
from app.models import Departement, Formation, FormSemestre, Identite
|
from app.models import (
|
||||||
|
Departement,
|
||||||
|
Formation,
|
||||||
|
FormSemestre,
|
||||||
|
Identite,
|
||||||
|
ModuleImpl,
|
||||||
|
NotesNotes,
|
||||||
|
ApcReferentielCompetences,
|
||||||
|
ApcCompetence,
|
||||||
|
Absence,
|
||||||
|
FormSemestreEtape,
|
||||||
|
)
|
||||||
from app import db
|
from app import db
|
||||||
|
from app.models.but_refcomp import (
|
||||||
|
ApcParcours,
|
||||||
|
ApcAnneeParcours,
|
||||||
|
ApcSituationPro,
|
||||||
|
ApcComposanteEssentielle,
|
||||||
|
ApcNiveau,
|
||||||
|
ApcAppCritique,
|
||||||
|
)
|
||||||
from app.scodoc import (
|
from app.scodoc import (
|
||||||
sco_cache,
|
sco_cache,
|
||||||
sco_evaluation_db,
|
sco_evaluation_db,
|
||||||
@ -38,6 +58,7 @@ from app.scodoc import (
|
|||||||
sco_groups,
|
sco_groups,
|
||||||
)
|
)
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from app.scodoc.sco_saisie_notes import notes_add
|
||||||
from tools.fakeportal.gen_nomprenoms import nomprenom
|
from tools.fakeportal.gen_nomprenoms import nomprenom
|
||||||
|
|
||||||
random.seed(12345678) # tests reproductibles
|
random.seed(12345678) # tests reproductibles
|
||||||
@ -160,13 +181,31 @@ def create_formsemestre(
|
|||||||
def inscrit_etudiants(etuds: list, formsemestre: FormSemestre):
|
def inscrit_etudiants(etuds: list, formsemestre: FormSemestre):
|
||||||
"""Inscrit les etudiants aux semestres et à tous ses modules"""
|
"""Inscrit les etudiants aux semestres et à tous ses modules"""
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
aleatoire = random.randint(0, 10)
|
||||||
formsemestre.id,
|
if aleatoire <= 3:
|
||||||
etud.id,
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
||||||
group_ids=[],
|
formsemestre.id,
|
||||||
etat="I",
|
etud.id,
|
||||||
method="init db test",
|
group_ids=[],
|
||||||
)
|
etat="I",
|
||||||
|
method="init db test",
|
||||||
|
)
|
||||||
|
elif 3 < aleatoire <= 6:
|
||||||
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
||||||
|
formsemestre.id,
|
||||||
|
etud.id,
|
||||||
|
group_ids=[],
|
||||||
|
etat="D",
|
||||||
|
method="init db test",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
||||||
|
formsemestre.id,
|
||||||
|
etud.id,
|
||||||
|
group_ids=[],
|
||||||
|
etat="DEF",
|
||||||
|
method="init db test",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_evaluations(formsemestre: FormSemestre):
|
def create_evaluations(formsemestre: FormSemestre):
|
||||||
@ -188,6 +227,286 @@ def create_evaluations(formsemestre: FormSemestre):
|
|||||||
evaluation_id = sco_evaluation_db.do_evaluation_create(**args)
|
evaluation_id = sco_evaluation_db.do_evaluation_create(**args)
|
||||||
|
|
||||||
|
|
||||||
|
def saisie_notes_evaluations(formsemestre: FormSemestre, user: User):
|
||||||
|
"""
|
||||||
|
Saisie les notes des evaluations d'un semestre
|
||||||
|
"""
|
||||||
|
etuds = formsemestre.etuds
|
||||||
|
list_etuds = []
|
||||||
|
for etu in etuds:
|
||||||
|
list_etuds.append(etu)
|
||||||
|
|
||||||
|
date_debut = formsemestre.date_debut
|
||||||
|
date_fin = formsemestre.date_fin
|
||||||
|
|
||||||
|
list_ues = formsemestre.query_ues()
|
||||||
|
|
||||||
|
def saisir_notes(evaluation_id: int, condition: int):
|
||||||
|
"""
|
||||||
|
Permet de saisir les notes de manière aléatoire suivant une condition
|
||||||
|
Définition des valeurs de condition :
|
||||||
|
0 : all_notes_saisies
|
||||||
|
1 : all_notes_manquantes
|
||||||
|
2 : some_notes_manquantes
|
||||||
|
"""
|
||||||
|
if condition == 0 or condition == 2:
|
||||||
|
if condition == 0:
|
||||||
|
for etu in list_etuds:
|
||||||
|
note = NotesNotes(
|
||||||
|
etu.id,
|
||||||
|
evaluation_id,
|
||||||
|
random.uniform(0, 20),
|
||||||
|
"",
|
||||||
|
date_debut + random.random() * (date_fin - date_debut),
|
||||||
|
user.id,
|
||||||
|
)
|
||||||
|
db.session.add(note)
|
||||||
|
db.session.commit()
|
||||||
|
else:
|
||||||
|
percent = 80 / 100
|
||||||
|
len_etuds = len(list_etuds)
|
||||||
|
new_list_etuds = random.sample(list_etuds, k=int(percent * len_etuds))
|
||||||
|
for etu in new_list_etuds:
|
||||||
|
note = NotesNotes(
|
||||||
|
etu.id,
|
||||||
|
evaluation_id,
|
||||||
|
random.uniform(0, 20),
|
||||||
|
"",
|
||||||
|
date_debut + random.random() * (date_fin - date_debut),
|
||||||
|
user.id,
|
||||||
|
)
|
||||||
|
db.session.add(note)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
for ue in list_ues:
|
||||||
|
mods = ue.modules
|
||||||
|
for mod in mods:
|
||||||
|
moduleimpl = ModuleImpl.query.get_or_404(mod.id)
|
||||||
|
for evaluation in moduleimpl.evaluations:
|
||||||
|
condition_saisie_notes = random.randint(0, 2)
|
||||||
|
saisir_notes(evaluation.id, condition_saisie_notes)
|
||||||
|
|
||||||
|
|
||||||
|
def create_ref_comp(formation: Formation):
|
||||||
|
"""
|
||||||
|
Créer un referentiel de competences
|
||||||
|
"""
|
||||||
|
# ### ApcSituationPro ###
|
||||||
|
# apc_situation_pro_id = 1
|
||||||
|
# apc_situation_pro_competence_id = 1
|
||||||
|
# apc_situation_pro_libelle = ""
|
||||||
|
#
|
||||||
|
# apc_situation_pro = ApcSituationPro(
|
||||||
|
# apc_situation_pro_id, apc_situation_pro_competence_id, apc_situation_pro_libelle
|
||||||
|
# )
|
||||||
|
# db.session.add(apc_situation_pro)
|
||||||
|
# db.session.commit()
|
||||||
|
#
|
||||||
|
# ### ApcComposanteEssentielle ###
|
||||||
|
# apc_composante_essentielle_id = 1
|
||||||
|
# apc_composante_essentielle_competence_id = 1
|
||||||
|
# apc_composante_essentielle_libelle = ""
|
||||||
|
#
|
||||||
|
# apc_composante_essentielle = ApcComposanteEssentielle(
|
||||||
|
# apc_composante_essentielle_id,
|
||||||
|
# apc_composante_essentielle_competence_id,
|
||||||
|
# apc_composante_essentielle_libelle,
|
||||||
|
# )
|
||||||
|
# db.session.add(apc_composante_essentielle)
|
||||||
|
# db.session.commit()
|
||||||
|
#
|
||||||
|
# ### ApcAppCritique ###
|
||||||
|
# apc_app_critique_id = 1
|
||||||
|
# apc_app_critique_niveau_id = 1
|
||||||
|
# apc_app_critique_code = ""
|
||||||
|
# apc_app_critique_libelle = ""
|
||||||
|
# apc_app_critique_modules = formation.modules
|
||||||
|
#
|
||||||
|
# apc_app_critique = ApcAppCritique(
|
||||||
|
# apc_app_critique_id,
|
||||||
|
# apc_app_critique_niveau_id,
|
||||||
|
# apc_app_critique_code,
|
||||||
|
# apc_app_critique_libelle,
|
||||||
|
# apc_app_critique_modules,
|
||||||
|
# )
|
||||||
|
# db.session.add(apc_app_critique)
|
||||||
|
# db.session.commit()
|
||||||
|
#
|
||||||
|
# ### ApcNiveau ###
|
||||||
|
# apc_niveau_id = 1
|
||||||
|
# apc_niveau_competence_id = 1
|
||||||
|
# apc_niveau_libelle = ""
|
||||||
|
# apc_niveau_annee = ""
|
||||||
|
# apc_niveau_ordre = 1
|
||||||
|
# apc_niveau_app_critiques = apc_app_critique
|
||||||
|
#
|
||||||
|
# apc_niveau = ApcNiveau(
|
||||||
|
# apc_niveau_id,
|
||||||
|
# apc_niveau_competence_id,
|
||||||
|
# apc_niveau_libelle,
|
||||||
|
# apc_niveau_annee,
|
||||||
|
# apc_niveau_ordre,
|
||||||
|
# apc_niveau_app_critiques,
|
||||||
|
# )
|
||||||
|
# db.session.add(apc_niveau)
|
||||||
|
# db.session.commit()
|
||||||
|
#
|
||||||
|
# ### ApcCompetence ###
|
||||||
|
# apc_competence_id = 1
|
||||||
|
# apc_competence_referentiel_id = 1
|
||||||
|
# apc_competence_id_orebut = ""
|
||||||
|
# apc_competence_titre = ""
|
||||||
|
# apc_competence_titre_long = ""
|
||||||
|
# apc_competence_couleur = ""
|
||||||
|
# apc_competence_numero = 1
|
||||||
|
# apc_competence_xml_attribs = { # xml_attrib : attribute
|
||||||
|
# "id": "id_orebut",
|
||||||
|
# "nom_court": "titre", # was name
|
||||||
|
# "libelle_long": "titre_long",
|
||||||
|
# }
|
||||||
|
# apc_competence_situations = apc_situation_pro
|
||||||
|
# apc_competence_composantes_essentielles = apc_composante_essentielle
|
||||||
|
# apc_competence_niveaux = apc_niveau
|
||||||
|
#
|
||||||
|
# apc_competence = ApcCompetence(
|
||||||
|
# apc_competence_id,
|
||||||
|
# apc_competence_referentiel_id,
|
||||||
|
# apc_competence_id_orebut,
|
||||||
|
# apc_competence_titre,
|
||||||
|
# apc_competence_titre_long,
|
||||||
|
# apc_competence_couleur,
|
||||||
|
# apc_competence_numero,
|
||||||
|
# apc_competence_xml_attribs,
|
||||||
|
# apc_competence_situations,
|
||||||
|
# apc_competence_composantes_essentielles,
|
||||||
|
# apc_competence_niveaux,
|
||||||
|
# )
|
||||||
|
# db.session.add(apc_competence)
|
||||||
|
# db.session.commit()
|
||||||
|
#
|
||||||
|
# ### ApcAnneeParcours ###
|
||||||
|
# apc_annee_parcours_id = 1
|
||||||
|
# apc_annee_parcours_parcours_id = 1
|
||||||
|
# apc_annee_parcours_ordre = 1
|
||||||
|
#
|
||||||
|
# ap_annee_parcours = ApcAnneeParcours(
|
||||||
|
# apc_annee_parcours_id, apc_annee_parcours_parcours_id, apc_annee_parcours_ordre
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# ### ApcParcours ###
|
||||||
|
# apc_parcours_id = 1
|
||||||
|
# apc_parcours_referentiel_id = 1
|
||||||
|
# apc_parcours_numero = 1
|
||||||
|
# apc_parcours_code = ""
|
||||||
|
# apc_parcours_libelle = ""
|
||||||
|
# apc_parcours_annees = ap_annee_parcours
|
||||||
|
#
|
||||||
|
# apc_parcours = ApcParcours(
|
||||||
|
# apc_parcours_id,
|
||||||
|
# apc_parcours_referentiel_id,
|
||||||
|
# apc_parcours_numero,
|
||||||
|
# apc_parcours_code,
|
||||||
|
# apc_parcours_libelle,
|
||||||
|
# apc_parcours_annees,
|
||||||
|
# )
|
||||||
|
# db.session.add(apc_parcours)
|
||||||
|
# db.session.commit()
|
||||||
|
|
||||||
|
### ApcReferentielCompetences ###
|
||||||
|
apc_referentiel_competences_id = 1
|
||||||
|
apc_referentiel_competences_dept_id = 1
|
||||||
|
apc_referentiel_competences_annexe = ""
|
||||||
|
apc_referentiel_competences_specialite = ""
|
||||||
|
apc_referentiel_competences_specialite_long = ""
|
||||||
|
apc_referentiel_competences_type_titre = ""
|
||||||
|
apc_referentiel_competences_type_structure = ""
|
||||||
|
apc_referentiel_competences_type_departement = ""
|
||||||
|
apc_referentiel_competences_version_orebut = ""
|
||||||
|
apc_referentiel_competences_xml_attribs = {
|
||||||
|
"type": "type_titre",
|
||||||
|
"version": "version_orebut",
|
||||||
|
}
|
||||||
|
apc_referentiel_competences_scodoc_date_loaded = ""
|
||||||
|
apc_referentiel_competences_scodoc_orig_filename = ""
|
||||||
|
# apc_referentiel_competences_competences = apc_competence
|
||||||
|
# apc_referentiel_competences_parcours = apc_parcours
|
||||||
|
# apc_referentiel_competences_formations = formation
|
||||||
|
|
||||||
|
apc_referentiel_competences = ApcReferentielCompetences(
|
||||||
|
apc_referentiel_competences_id,
|
||||||
|
apc_referentiel_competences_dept_id,
|
||||||
|
apc_referentiel_competences_annexe,
|
||||||
|
apc_referentiel_competences_specialite,
|
||||||
|
apc_referentiel_competences_specialite_long,
|
||||||
|
apc_referentiel_competences_type_titre,
|
||||||
|
apc_referentiel_competences_type_structure,
|
||||||
|
apc_referentiel_competences_type_departement,
|
||||||
|
apc_referentiel_competences_version_orebut,
|
||||||
|
apc_referentiel_competences_xml_attribs,
|
||||||
|
# apc_referentiel_competences_scodoc_date_loaded,
|
||||||
|
apc_referentiel_competences_scodoc_orig_filename,
|
||||||
|
# apc_referentiel_competences_competences,
|
||||||
|
# apc_referentiel_competences_parcours,
|
||||||
|
# apc_referentiel_competences_formations,
|
||||||
|
)
|
||||||
|
db.session.add(apc_referentiel_competences)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
formation.referentiel_competence_id = apc_referentiel_competences.id
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def add_absences(formsemestre: FormSemestre):
|
||||||
|
"""
|
||||||
|
Ajoute des absences en base
|
||||||
|
"""
|
||||||
|
date_debut = formsemestre.date_debut
|
||||||
|
date_fin = formsemestre.date_fin
|
||||||
|
|
||||||
|
etuds = formsemestre.etuds
|
||||||
|
id_db = 1
|
||||||
|
for etu in etuds:
|
||||||
|
aleatoire = random.randint(0, 1)
|
||||||
|
if aleatoire == 1:
|
||||||
|
nb_absences = random.randint(1, 5)
|
||||||
|
for absence in range(0, nb_absences):
|
||||||
|
id = id_db
|
||||||
|
etudid = etu.id
|
||||||
|
jour = date_debut + random.random() * (date_fin - date_debut)
|
||||||
|
estabs = True
|
||||||
|
estjust = True if random.randint(0, 1) == 1 else False
|
||||||
|
matin = True if random.randint(0, 1) == 1 else False
|
||||||
|
description = ""
|
||||||
|
abs = Absence(id, etudid, jour, estabs, estjust, matin, description)
|
||||||
|
db.session.add(abs)
|
||||||
|
db.session.commit()
|
||||||
|
id_db += 1
|
||||||
|
|
||||||
|
|
||||||
|
def create_etape_apo(formsemestre: FormSemestre):
|
||||||
|
"""
|
||||||
|
Ajoute étape apoge au formsemestre
|
||||||
|
"""
|
||||||
|
etape_apo1 = FormSemestreEtape(
|
||||||
|
id=1, formsemestre_id=formsemestre.id, etape_apo="A1"
|
||||||
|
)
|
||||||
|
db.session.add(etape_apo1)
|
||||||
|
|
||||||
|
etape_apo2 = FormSemestreEtape(
|
||||||
|
id=2, formsemestre_id=formsemestre.id, etape_apo="A2"
|
||||||
|
)
|
||||||
|
db.session.add(etape_apo2)
|
||||||
|
|
||||||
|
etape_apo3 = FormSemestreEtape(
|
||||||
|
id=3, formsemestre_id=formsemestre.id, etape_apo="A3"
|
||||||
|
)
|
||||||
|
db.session.add(etape_apo3)
|
||||||
|
|
||||||
|
list_etapes = [etape_apo1, etape_apo2, etape_apo3]
|
||||||
|
formsemestre.etapes = list_etapes
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
def init_test_database():
|
def init_test_database():
|
||||||
"""Appelé par la commande `flask init-test-database`
|
"""Appelé par la commande `flask init-test-database`
|
||||||
|
|
||||||
@ -201,6 +520,10 @@ def init_test_database():
|
|||||||
formsemestre = create_formsemestre(formation, user_lecteur)
|
formsemestre = create_formsemestre(formation, user_lecteur)
|
||||||
create_evaluations(formsemestre)
|
create_evaluations(formsemestre)
|
||||||
inscrit_etudiants(etuds, formsemestre)
|
inscrit_etudiants(etuds, formsemestre)
|
||||||
|
saisie_notes_evaluations(formsemestre, user_lecteur)
|
||||||
|
create_ref_comp(formation)
|
||||||
|
add_absences(formsemestre)
|
||||||
|
create_etape_apo(formsemestre)
|
||||||
# à compléter
|
# à compléter
|
||||||
# - groupes
|
# - groupes
|
||||||
# - absences
|
# - absences
|
||||||
|
Loading…
Reference in New Issue
Block a user