DocScoDoc/app/api/sco_api.py
2022-02-25 16:03:05 +01:00

1477 lines
50 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""API ScoDoc 9
"""
# PAS ENCORE IMPLEMENTEE, juste un essai
# Pour P. Bouron, il faudrait en priorité l'équivalent de
# Scolarite/Notes/moduleimpl_withmodule_list (alias scodoc7 do_moduleimpl_withmodule_list)
# Scolarite/Notes/evaluation_create
# Scolarite/Notes/evaluation_delete
# Scolarite/Notes/formation_list
# Scolarite/Notes/formsemestre_list
# Scolarite/Notes/formsemestre_partition_list
# Scolarite/Notes/groups_view
# Scolarite/Notes/moduleimpl_status
# Scolarite/setGroups
from datetime import datetime
from flask import jsonify, request, g, send_file
from sqlalchemy.sql import func
from app import db, log
from app.api import bp, requested_format
from app.api.auth import token_auth
from app.api.errors import error_response
from app import models
from app.models import FormSemestre, FormSemestreInscription, Identite
from app.models import ApcReferentielCompetences
from app.scodoc.sco_abs import annule_absence, annule_justif, add_absence, add_justif, list_abs_date
from app.scodoc.sco_bulletins import formsemestre_bulletinetud_dict
from app.scodoc.sco_bulletins_json import make_json_formsemestre_bulletinetud
from app.scodoc.sco_evaluation_db import do_evaluation_get_all_notes
from app.scodoc.sco_formations import formation_export
from app.scodoc.sco_formsemestre_inscriptions import do_formsemestre_inscription_listinscrits
from app.scodoc.sco_groups import setGroups, get_etud_groups, get_group_members
from app.scodoc.sco_logos import list_logos, find_logo, _list_dept_logos
from app.scodoc.sco_moduleimpl import moduleimpl_list
from app.scodoc.sco_permissions import Permission
############################################### Departements ##########################################################
from app.scodoc.sco_prepajury import feuille_preparation_jury
from app.scodoc.sco_pvjury import formsemestre_pvjury
from app.scodoc.sco_recapcomplet import formsemestre_recapcomplet
from app.scodoc.sco_saisie_notes import notes_add
@bp.route("/departements", methods=["GET"])
@token_auth.login_required
def departements():
"""
Retourne la liste des ids de départements
"""
# Récupération de tous les départements
depts = models.Departement.query.filter_by(visible=True).all()
# Mise en place de la liste avec tous les ids de départements
data = [d.id for d in depts]
return jsonify(data)
@bp.route("/departements/<string:dept>/etudiants/liste/<int:sem_id>", methods=["GET"])
@token_auth.login_required
def liste_etudiants(dept: str, formsemestre_id=None): # XXX TODO A REVOIR
"""
Retourne la liste des étudiants d'un département
dept: l'acronym d'un département
formsemestre_id: l'id d'un formesemestre
"""
# Si le formsemestre_id a été renseigné
if formsemestre_id is not None:
# Récupération du/des depts
list_depts = models.Departement.query.filter(
models.Departement.acronym == dept,
models.FormSemestre.semestre_id == formsemestre_id,
)
list_etuds = []
for dept in list_depts:
# Récupération des étudiants d'un département
x = models.Identite.query.filter(models.Identite.dept_id == dept.getId())
for y in x:
# Ajout des étudiants dans la liste global
list_etuds.append(y)
else: # Si le formsemestre_id n'a pas été renseigné
list_depts = models.Departement.query.filter(
models.Departement.acronym == dept,
models.FormSemestre.semestre_id == models.Departement.formsemestres,
)
list_etuds = []
for dept in list_depts:
x = models.Identite.query.filter(models.Identite.dept_id == dept.getId())
for y in x:
list_etuds.append(y)
# Mise en forme des données
data = [d.to_dict() for d in list_etuds]
# return jsonify(data)
return error_response(501, message="Not implemented")
@bp.route("/departements/<string:dept>/semestres_courant", methods=["GET"])
@token_auth.login_required
def liste_semestres_courant(dept: str):
"""
Liste des semestres actifs d'un départements donné
dept: l'acronym d'un département
"""
# Récupération des départements comportant l'acronym mit en paramètre
depts = models.Departement.query.filter_by(acronym=dept).all()
# Récupération de l'id
id_dept = depts[0].id
# Récupération des semestres suivant id_dept
semestres = models.FormSemestre.query.filter_by(dept_id=id_dept, etat=True).all()
# Mise en forme des données
data = semestres[0].to_dict()
return jsonify(data)
@bp.route(
"/departements/<string:dept>/formations/<int:formation_id>/referentiel_competences",
methods=["GET"],
)
def referenciel_competences(dept: str, formation_id: int):
"""
Retourne le référentiel de compétences
dept : l'acronym d'un département
formation_id : l'id d'une formation
"""
# depts = models.Departement.query.filter_by(acronym=dept).all()
#
# id_dept = depts[0].id
#
# formations = models.Formation.query.filter_by(id=formation_id, dept_id=id_dept).all()
#
# ref_comp = formations[0].referentiel_competence_id
#
# if ref_comp is None:
# return error_response(204, message="Pas de référenciel de compétences pour cette formation")
# else:
# return jsonify(ref_comp)
ref = ApcReferentielCompetences.query.get_or_404(formation_id)
return jsonify(ref.to_dict())
@bp.route("/departements/<string:dept>/formsemestre<string:formsemestre_id>/programme", methods=["GET"])
def semestre_index(dept: str, formsemestre_id: int):
"""
Retourne la liste des Ues, ressources et SAE d'un semestre
"""
return error_response(501, message="not implemented")
#################################################### Etudiants ########################################################
@bp.route("/etudiants", methods=["GET"])
def etudiants():
"""
Retourne la liste de tous les étudiants
"""
# Récupération de tous les étudiants
etu = models.Identite.query.all()
# Mise en forme des données
data = [d.to_dict_bul(include_urls=False) for d in etu]
return jsonify(data)
# return error_response(501, message="Not implemented")
@bp.route("/etudiants/courant", methods=["GET"])
def etudiants_courant():
"""
Retourne la liste des étudiants courant
"""
# Récupération de tous les étudiants
etus = models.Identite.query.all()
data = []
# Récupère uniquement les étudiants courant
for etu in etus:
if etu.inscription_courante() is not None:
data.append(etu.to_dict_bul(include_urls=False))
return jsonify(data)
# return error_response(501, message="Not implemented")
@bp.route("/etudiant/etudid/<int:etudid>", methods=["GET"])
@bp.route("/etudiant/nip/<int:nip>", methods=["GET"])
@bp.route("/etudiant/ine/<int:ine>", methods=["GET"])
def etudiant(etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne les informations de l'étudiant correspondant à l'id passé en paramètres.
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
etu = []
if etudid is not None: # Si route etudid
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(id=etudid).first()
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
# Mise en forme des données
data = etu.to_dict_bul(include_urls=False)
return jsonify(data)
@bp.route("/etudiant/etudid/<int:etudid>/formsemestres")
@bp.route("/etudiant/nip/<int:nip>/formsemestres")
@bp.route("/etudiant/ine/<int:ine>/formsemestres")
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne les semestres qu'un étudiant a suivis
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Récupération de toutes les inscriptions
inscriptions = models.FormSemestreInscription.query.all()
sems = []
# Filtre les inscriptions contenant l'étudiant
for sem in inscriptions:
if etudid is not None: # Si route etudid
if sem.etudid == etudid:
sems.append(sem)
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
if sem.etudid == etu.etudid:
sems.append(sem)
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).firt()
if sem.etudid == etu.etudid:
sems.append(sem)
# Mise en forme des données
data_inscriptions = [d.to_dict() for d in sems]
formsemestres = []
# Filtre les formsemestre contenant les inscriptions de l'étudiant
for sem in data_inscriptions:
res = models.FormSemestre.query.filter_by(id=sem['formsemestre_id']).first()
formsemestres.append(res)
data = []
# Mise en forme des données
for formsem in formsemestres:
data.append(formsem.to_dict())
return jsonify(data)
@bp.route("/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin", methods=["GET"])
@bp.route("/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin", methods=["GET"])
@bp.route("/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin", methods=["GET"])
def etudiant_bulletin_semestre(formsemestre_id, etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné
formsemestre_id : l'id d'un formsemestre
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_bulletins_json.make_json_formsemestre_bulletinetud()
etu = None
if etudid is not None: # Si route etudid
return make_json_formsemestre_bulletinetud(formsemestre_id, etudid)
else:
if nip is not None: # Si route nip
etu = models.Identite.query.filter_by(code_nip=nip).first()
if ine is not None: # Si route ine
etu = models.Identite.query.filter_by(code_nip=ine).first()
if etu is not None: # Si route nip ou ine
return make_json_formsemestre_bulletinetud(formsemestre_id, etu.etudid)
# return error_response(501, message="Not implemented")
@bp.route(
"/etudiant/etudid/<int:etudid>/semestre/<int:formsemestre_id>/groups", methods=["GET"]
)
@bp.route(
"/etudiant/nip/<int:nip>/semestre/<int:formsemestre_id>/groups", methods=["GET"]
)
@bp.route(
"/etudiant/ine/<int:ine>/semestre/<int:formsemestre_id>/groups", methods=["GET"]
)
def etudiant_groups(formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne la liste des groupes auxquels appartient l'étudiant dans le semestre indiqué
formsemestre_id : l'id d'un formsemestre
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_groups.get_etud_groups()
if etudid is None:
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
# Récupération de sont etudid
etudid = etu.etudid
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
# Récupération de sont etudid
etudid = etu.etudid
# Récupération du formsemestre
sem = models.FormSemestre.query.filter_by(id=formsemestre_id).first()
try:
# Utilisation de la fonction get_etud_groups
data = get_etud_groups(etudid, sem.to_dict())
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
##############################################" Formations ############################################################
@bp.route("/formations", methods=["GET"])
def formations():
"""
Retourne la liste des formations
"""
# Récupération de toutes les formations
list_formations = models.Formation.query.all()
# Mise en forme des données
data = [d.to_dict() for d in list_formations]
return jsonify(data)
@bp.route("/formations/<int:formation_id>", methods=["GET"])
def formations_by_id(formation_id: int):
"""
Retourne une formation en fonction d'un id donné
formation_id : l'id d'une formation
"""
# Récupération de la formation
forma = models.Formation.query.filter_by(id=formation_id).first()
# Mise en forme des données
data = [d.to_dict() for d in forma]
return jsonify(data)
@bp.route("/formations/formation_export/<int:formation_id>", methods=["GET"])
def formation_export_by_formation_id(formation_id: int, export_ids=False):
"""
Retourne la formation, avec UE, matières, modules
"""
# Fonction utilité : app.scodoc.sco_formations.formation_export()
try:
# Utilisation de la fonction formation_export
data = formation_export(formation_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
@bp.route("/formations/apo/<string:etape_apo>", methods=["GET"])
def formsemestre_apo(etape_apo: int):
"""
Retourne les informations sur les formsemestres
etape_apo : l'id d'une étape apogée
"""
# Récupération des formsemestres
apos = models.FormSemestreEtape.query.filter_by(etape_apo=etape_apo).all()
data = []
# Filtre les formsemestres correspondant + mise en forme des données
for apo in apos:
formsem = models.FormSemestre.query.filter_by(id=apo["formsemestre_id"]).first()
data.append(formsem.to_dict())
return jsonify(data)
# return error_response(501, message="Not implemented")
@bp.route("/formations/moduleimpl/<int:moduleimpl_id>", methods=["GET"])
def moduleimpls(moduleimpl_id: int):
"""
Retourne la liste des moduleimpl
moduleimpl_id : l'id d'un moduleimpl
"""
# Récupération des tous les moduleimpl
list_moduleimpls = models.ModuleImpl.query.filter_by(id=moduleimpl_id).all()
# Mise en forme des données
data = list_moduleimpls[0].to_dict()
return jsonify(data)
@bp.route(
"/formations/moduleimpl/<int:moduleimpl_id>/formsemestre/<int:formsemestre_id>", methods=["GET"])
def moduleimpls_sem(moduleimpl_id: int, formsemestre_id: int):
"""
Retourne la liste des moduleimpl d'un semestre
moduleimpl_id : l'id d'un moduleimpl
formsemestre_id : l'id d'un formsemestre
"""
# Fonction utilisée : app.scodoc.sco_moduleimpl.moduleimpl_list()
try:
# Utilisation de la fonction moduleimpl_list
data = moduleimpl_list(moduleimpl_id, formsemestre_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
#################################################### UE ###############################################################
@bp.route(
"/departements/<string:dept>/formations/programme/<string:sem_id>", methods=["GET"]
)
def eus(dept: str, sem_id: int):
"""
Liste des UES, ressources et SAE d'un semestre
"""
return error_response(501, message="Not implemented")
########################################## Formsemestres ##############################################################
@bp.route("/formations/formsemestre/<int:formsemestre_id>", methods=["GET"])
def formsemestre(formsemestre_id: int):
"""
Retourne l'information sur le formsemestre correspondant au formsemestre_id
formsemestre_id : l'id d'un formsemestre
"""
# Récupération de tous les formsemestres
list_formsemetre = models.FormSemestre.query.filter_by(id=formsemestre_id)
# Mise en forme des données
data = list_formsemetre[0].to_dict()
return jsonify(data)
@bp.route(
"/formsemestre/<int:formsemestre_id>/departements/<string:dept>/etudiant/etudid/<int:etudid>/bulletin",
methods=["GET"],
)
@bp.route(
"/formsemestre/<int:formsemestre_id>/departements/<string:dept>/etudiant/nip/<int:nip>/bulletin",
methods=["GET"],
)
@bp.route(
"/formsemestre/<int:formsemestre_id>/departements/<string:dept>/etudiant/ine/<int:ine>/bulletin",
methods=["GET"],
)
def etudiant_bulletin(formsemestre_id, dept, etudid, format="json", *args, size):
"""
Retourne le bulletin de note d'un étudiant
formsemestre_id : l'id d'un formsemestre
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_bulletins.formsemestre_billetinetud_dict()
data = []
if args[0] == "short":
data = formsemestre_bulletinetud_dict(formsemestre_id, etudid, version=args[0])
elif args[0] == "selectevals":
data = formsemestre_bulletinetud_dict(formsemestre_id, etudid, version=args[0])
elif args[0] == "long":
data = formsemestre_bulletinetud_dict(formsemestre_id, etudid)
else:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
def bulletins(formsemestre_id: int):
"""
Retourne les bulletins d'un formsemestre donné
formsemestre_id : l'id d'un formesemestre
"""
# Fonction utilisée : app.scodoc.sco_recapcomplet.formsemestre_recapcomplet()
try:
# Utilisation de la fonction formsemestre_recapcomplet
data = formsemestre_recapcomplet(formsemestre_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
@bp.route("/formsemestre/<int:formsemestre_id>/jury", methods=["GET"])
def jury(formsemestre_id: int):
"""
Retourne le récapitulatif des décisions jury
formsemestre_id : l'id d'un formsemestre
"""
# Fonction utilisée : app.scodoc.sco_pvjury.formsemestre_pvjury()
try:
# Utilisation de la fonction formsemestre_pvjury
data = formsemestre_pvjury(formsemestre_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
############################################### Partitions ############################################################
@bp.route("/partitions/<int:formsemestre_id>", methods=["GET"])
def partition(formsemestre_id: int):
"""
Retourne la liste de toutes les partitions d'un formsemestre
formsemestre_id : l'id d'un formsemestre
"""
# Récupération de toutes les partitions
partitions = models.Partition.query.filter_by(id=formsemestre_id).all()
# Mise en forme des données
data = [d.to_dict() for d in partitions]
return jsonify(data)
# return error_response(501, message="Not implemented")
# @bp.route(
# "/partitions/formsemestre/<int:formsemestre_id>/groups/group_ids?with_codes=&all_groups=&etat=",
# methods=["GET"],
# )
@bp.route("/partitions/groups/<int:group_id>", methods=["GET"])
@bp.route("/partitions/groups/<int:group_id>/etat/<string:etat>", methods=["GET"])
def etud_in_group(group_id: int, etat=None):
"""
Retourne la liste des étudiants dans un groupe
group_id : l'id d'un groupe
etat :
"""
# Fonction utilisée : app.scodoc.sco_groups.get_group_members()
if etat is None: # Si l'état n'est pas renseigné
try:
# Utilisation de la fonction get_group_members
data = get_group_members(group_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
else: # Si l'état est renseigné
try:
# Utilisation de la fonction get_group_members
data = get_group_members(group_id, etat)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
@bp.route(
"/partitions/set_groups?partition_id=<int:partition_id>&groups_lists=<int:groups_lists>&"
"groups_to_create=<int:groups_to_create>&groups_to_delete=<int:groups_to_delete>", methods=["POST"],
)
@token_auth.login_required
def set_groups(partition_id: int, groups_lists: int, groups_to_delete: int, groups_to_create: int):
"""
Set les groups
partition_id : l'id d'une partition
groups_lists :
groups_ti_delete : les groupes à supprimer
groups_to_create : les groupes à créer
"""
# Fonction utilisée : app.scodoc.sco_groups.setGroups()
try:
# Utilisation de la fonction setGroups
setGroups(partition_id, groups_lists, groups_to_create, groups_to_delete)
return error_response(200, message="Groups set")
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
############################################### Evaluations ###########################################################
@bp.route("/evaluations/<int:moduleimpl_id>", methods=["GET"])
def evaluations(moduleimpl_id: int):
"""
Retourne la liste des évaluations à partir de l'id d'un moduleimpl
moduleimpl_id : l'id d'un moduleimpl
"""
# Récupération de toutes les évaluations
evals = models.Evaluation.query.filter_by(id=moduleimpl_id).all()
# Mise en forme des données
data = [d.to_dict() for d in evals]
return jsonify(data)
# return error_response(501, message="Not implemented")
@bp.route("/evaluations/eval_notes/<int:evaluation_id>", methods=["GET"])
def evaluation_notes(evaluation_id: int):
"""
Retourne la liste des notes à partir de l'id d'une évaluation donnée
evaluation_id : l'id d'une évaluation
"""
# Fonction utilisée : app.scodoc.sco_evaluation_db.do_evaluation_get_all_notes()
try:
# Utilisation de la fonction do_evaluation_get_all_notes
data = do_evaluation_get_all_notes(evaluation_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return jsonify(data)
@bp.route("/evaluations/eval_set_notes?eval_id=<int:eval_id>&etudid=<int:etudid>&note=<float:note>", methods=["POST"])
@bp.route("/evaluations/eval_set_notes?eval_id=<int:eval_id>&nip=<int:nip>&note=<float:note>", methods=["POST"])
@bp.route("/evaluations/eval_set_notes?eval_id=<int:eval_id>&ine=<int:ine>&note=<float:note>", methods=["POST"])
@token_auth.login_required
def evaluation_set_notes(eval_id: int, note: float, etudid: int = None, nip: int = None, ine: int = None):
"""
Set les notes d'une évaluation pour un étudiant donnée
eval_id : l'id d'une évaluation
note : la note à attribuer
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_saisie_notes.notes_add()
# Qu'est ce qu'un user ???
# notes_add()
return error_response(501, message="Not implemented")
#################################################### Jury #############################################################
@bp.route("/jury/formsemestre/<int:formsemestre_id>/preparation_jury", methods=["GET"])
def jury_preparation(formsemestre_id: int): # XXX TODO check à quoi resemble le retour de la fonction
"""
Retourne la feuille de préparation du jury
formsemestre_id : l'id d'un formsemestre
"""
# Fonction utilisée : app.scodoc.sco_prepajury.feuille_preparation_jury()
# Utilisation de la fonction feuille_preparation_jury
prepa_jury = feuille_preparation_jury(formsemestre_id)
return error_response(501, message="Not implemented")
@bp.route("/jury/formsemestre/<int:formsemestre_id>/decisions_jury", methods=["GET"])
def jury_decisions(formsemestre_id: int): # XXX TODO check à quoi resemble le retour de la fonction
"""
Retourne les décisions du jury suivant un formsemestre donné
formsemestre_id : l'id d'un formsemestre
"""
# Fonction utilisée : app.scodoc.sco_pvjury.formsemestre_pvjury()
# Utilisation de la fonction formsemestre_pvjury
decision_jury = formsemestre_pvjury(formsemestre_id)
return error_response(501, message="Not implemented")
@bp.route("/jury/set_decision/etudid?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>", methods=["POST"])
@bp.route("/jury/set_decision/nip?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>", methods=["POST"])
@bp.route("/jury/set_decision/ine?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>", methods=["POST"])
def set_decision_jury(formsemestre_id: int, decision_jury: str, devenir_jury: str, assiduite: bool,
etudid: int = None, nip: int = None, ine: int = None):
"""
Attribuer la décision du jury et le devenir à un etudiant
formsemestre_id : l'id d'un formsemestre
decision_jury : la décision du jury
devenir_jury : le devenir du jury
assiduite : True ou False
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
return error_response(501, message="Not implemented")
@bp.route("/jury/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/annule_decision", methods=["DELETE"])
@bp.route("/jury/nip/<int:nip>/formsemestre/<int:formsemestre_id>/annule_decision", methods=["DELETE"])
@bp.route("/jury/ine/<int:ine>/formsemestre/<int:formsemestre_id>/annule_decision", methods=["DELETE"])
def annule_decision_jury(formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None):
"""
Supprime la déciosion du jury pour un étudiant donné
formsemestre_id : l'id d'un formsemestre
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
return error_response(501, message="Not implemented")
#################################################### Absences #########################################################
@bp.route("/absences/etudid/<int:etudid>", methods=["GET"])
@bp.route("/absences/nip/<int:nip>", methods=["GET"])
@bp.route("/absences/ine/<int:ine>", methods=["GET"])
def absences(etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne la liste des absences d'un étudiant donné
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
abs = None
if etudid is not None: # Si route etudid
# Récupération des absences de l'étudiant
abs = models.Absence.query.filter_by(etudid=etudid).all()
else:
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
# Récupération des absences de l'étudiant
abs = models.Absence.query.filter_by(etudid=etu.etudid).all()
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
# Récupération des absences de l'étudiant
abs = models.Absence.query.filter_by(etudid=etu.etudid).all()
if abs is not None: # Si des absences ont bien été trouvé
# Mise en forme des données
data = [d.to_dict() for d in abs]
return jsonify(data)
return error_response(501, message="Not implemented")
@bp.route("/absences/etudid/<int:etudid>/abs_just_only", methods=["GET"])
@bp.route("/absences/nip/<int:nip>/abs_just_only", methods=["GET"])
@bp.route("/absences/ine/<int:ine>/abs_just_only", methods=["GET"])
def absences_justify(etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne la liste des absences justifiées d'un étudiant donné
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
abs = None
if etudid is not None: # Si route etudid
# Récupération des absences justifiées de l'étudiant
abs = models.Absence.query.filter_by(etudid=etudid, estjust=True).all()
else:
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
# Récupération des absences justifiées de l'étudiant
abs = models.Absence.query.filter_by(etudid=etu.etudid, estjust=True).all()
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
# Récupération des absences justifiées de l'étudiant
abs = models.Absence.query.filter_by(etudid=etu.etudid, estjust=True).all()
if abs is not None: # Si des absences ont bien été trouvé
# Mise en forme des données
data = [d.to_dict() for d in abs]
return jsonify(data)
return error_response(501, message="Not implemented")
@bp.route("/absences/abs_signale?etudid=<int:etudid>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>", methods=["POST"])
@bp.route("/absences/abs_signale?nip=<int:nip>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>", methods=["POST"])
@bp.route("/absences/abs_signale?ine=<int:ine>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>", methods=["POST"])
@bp.route("/absences/abs_signale?ine=<int:ine>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>&moduleimpl_id=<int:moduleimpl_id>", methods=["POST"])
@token_auth.login_required
def abs_signale(date: datetime, matin: bool, justif: bool, etudid: int = None, nip: int = None, ine: int = None,
description: str = None, moduleimpl_id: int = None):
"""
Permet d'ajouter une absence en base
date : la date de l'absence
matin : True ou False
justif : True ou False
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
description : description possible à ajouter sur l'absence
moduleimpl_id : l'id d'un moduleimpl
"""
# Fonctions utilisées : app.scodoc.sco_abs.add_absence() et app.scodoc.sco_abs.add_justif()
if description is not None: # Si la description a été renseignée
if moduleimpl_id is not None: # Si le moduleimpl a été renseigné
if etudid is not None: # Si route etudid
try:
# Utilisation de la fonction add_absence
add_absence(etudid, date, matin, justif, description, moduleimpl_id)
# Utilisation de la fonction add_justif
add_justif(etudid, date, matin, description)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
try:
# Utilisation de la fonction add_absence
add_absence(etu.etudid, date, matin, justif, description, moduleimpl_id)
# Utilisation de la fonction add_justif
add_justif(etu.etudid, date, matin, description)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
try:
# Utilisation de la fonction add_absence
add_absence(etu.etudid, date, matin, justif, description, moduleimpl_id)
# Utilisation de la fonction add_justif
add_justif(etu.etudid, date, matin, description)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return error_response(409, message="La requête ne peut être traitée en létat actuel")
else: # Si le moduleimpl n'a pas été renseigné
if etudid is not None: # Si route etudid
try:
# Utilisation de la fonction add_absence
add_absence(etudid, date, matin, justif, description)
# Utilisation de la fonction add_justif
add_justif(etudid, date, matin, description)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
try:
# Utilisation de la fonction add_absence
add_absence(etu.etudid, date, matin, justif, description)
# Utilisation de la fonction add_justif
add_justif(etu.etudid, date, matin, description)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
try:
# Utilisation de la fonction add_absence
add_absence(etu.etudid, date, matin, justif, description)
# Utilisation de la fonction add_justif
add_justif(etu.etudid, date, matin, description)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return error_response(409, message="La requête ne peut être traitée en létat actuel")
else:
if etudid is not None: # Si route etudid
try:
# Utilisation de la fonction add_absence
add_absence(etudid, date, matin, justif)
# Utilisation de la fonction add_justif
add_justif(etudid, date, matin)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
try:
# Utilisation de la fonction add_absence
add_absence(etu.etudid, date, matin, justif)
# Utilisation de la fonction add_justif
add_justif(etu.etudid, date, matin)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
try:
# Utilisation de la fonction add_absence
add_absence(etu.etudid, date, matin, justif)
# Utilisation de la fonction add_justif
add_justif(etu.etudid, date, matin)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return error_response(200, message="OK")
@bp.route("/absences/abs_annule?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>", methods=["POST"])
@bp.route("/absences/abs_annule?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>", methods=["POST"])
@bp.route("/absences/abs_annule?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>", methods=["POST"])
@token_auth.login_required
def abs_annule(jour: datetime, matin: str, etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne un html
jour : la date de l'absence a annulé
matin : True ou False
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_abs.annule_absence()
if etudid is None:
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
# Récupération de l'etudid de l'étudiant
etudid = etu.etudid
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
# Récupération de l'etudid de l'étudiant
etudid = etu.etudid
try:
# Utilisation de la fonction annule_absence
annule_absence(etudid, jour, matin)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return error_response(200, message="OK")
@bp.route("/absences/abs_annule_justif?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>", methods=["POST"])
@bp.route("/absences/abs_annule_justif?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>", methods=["POST"])
@bp.route("/absences/abs_annule_justif?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>", methods=["POST"])
@token_auth.login_required
def abs_annule_justif(jour: datetime, matin: str, etudid: int = None, nip: int = None, ine: int = None):
"""
Retourne un html
jour : la date de l'absence a annulé
matin : True ou False
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_abs.annule_justif()
if etudid is None:
if nip is not None: # Si route nip
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_nip=nip).first()
# Récupération de l'etudid de l'étudiant
etudid = etu.etudid
if ine is not None: # Si route ine
# Récupération de l'étudiant
etu = models.Identite.query.filter_by(code_ine=ine).first()
# Récupération de l'etudid de l'étudiant
etudid = etu.etudid
try:
# Utilisation de la fonction annule_justif
annule_justif(etudid, jour, matin)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
return error_response(200, message="OK")
@bp.route("/absences/abs_group_etat/?group_id=<int:group_id>&date_debut=date_debut&date_fin=date_fin", methods=["GET"])
def abs_groupe_etat(group_id: int, date_debut, date_fin, with_boursier=True, format="html"):
"""
Retoune la liste des absences d'un ou plusieurs groupes entre deux dates
"""
# Fonction utilisée : app.scodoc.sco_groups.get_group_members() et app.scodoc.sco_abs.list_abs_date()
try:
# Utilisation de la fonction get_group_members
members = get_group_members(group_id)
except ValueError:
return error_response(409, message="La requête ne peut être traitée en létat actuel")
data = []
# Filtre entre les deux dates renseignées
for member in members:
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)
return error_response(501, message="Not implemented")
###################################################### Logos ##########################################################
# XXX TODO voir get_logo déjà existant dans app/views/scodoc.py
@bp.route("/logos", methods=["GET"])
def liste_logos(format="json"):
"""
Liste des logos définis pour le site scodoc.
"""
# fonction to use : list_logos()
# try:
# res = list_logos()
# except ValueError:
# return error_response(409, message="La requête ne peut être traitée en létat actuel")
#
# if res is None:
# return error_response(200, message="Aucun logo trouvé correspondant aux informations renseignés")
#
# return res
@bp.route("/logos/<string:logo_name>", methods=["GET"])
def recup_logo_global(logo_name: str):
"""
Retourne l'image au format png ou jpg
logo_name : le nom du logo rechercher
"""
# fonction to use find_logo
# try:
# res = find_logo(logo_name)
# except ValueError:
# return error_response(409, message="La requête ne peut être traitée en létat actuel")
#
# if res is None:
# return error_response(200, message="Aucun logo trouvé correspondant aux informations renseignés")
#
# return res
@bp.route("/departements/<string:dept>/logos", methods=["GET"])
def logo_dept(dept: str):
"""
Liste des logos définis pour le département visé.
dept : l'id d'un département
"""
# fonction to use: _list_dept_logos
# dept_id = models.Departement.query.filter_by(acronym=dept).first()
# try:
# res = _list_dept_logos(dept_id.id)
# except ValueError:
# return error_response(409, message="La requête ne peut être traitée en létat actuel")
#
# if res is None:
# return error_response(200, message="Aucun logo trouvé correspondant aux informations renseignés")
#
# return res
@bp.route("/departement/<string:dept>/logos/<string:logo_name>", methods=["GET"])
def recup_logo_dept_global(dept: str, logo_name: str):
"""
L'image format png ou jpg
dept : l'id d'un département
logo_name : le nom du logo rechercher
"""
# fonction to use find_logo
# dept_id = models.Departement.query.filter_by(acronym=dept).first()
# try:
# res = find_logo(logo_name, dept_id.id)
# except ValueError:
# return error_response(409, message="La requête ne peut être traitée en létat actuel")
#
# if res is None:
# return error_response(200, message="Aucun logo trouvé correspondant aux informations renseignés")
#
# return res
################################################## Tests ##############################################################
import requests
import os
SCODOC_USER = ""
SCODOC_PASSWORD = ""
SCODOC_URL = ""
CHECK_CERTIFICATE = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
r0 = requests.post(
SCODOC_URL + "/ScoDoc/api/tokens", auth=(SCODOC_USER, SCODOC_PASSWORD)
)
token = r0.json()["token"]
HEADERS = {"Authorization": f"Bearer {token}"}
def test_routes_departements():
"""
Test les routes de la partie Département
"""
# departements
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api/departements",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# liste_etudiants
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api/departements/<string:dept>/etudiants/liste/<int:sem_id>",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# liste_semestres_courant
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# referenciel_competences
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# semestre_index
r5 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_etudiants():
"""
Test les routes de la partie Etudiants
"""
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
r5 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
r6 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_formation():
"""
Test les routes de la partie Formation
"""
# formations
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# formations_by_id
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# formation_export_by_formation_id
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# formsemestre_apo
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# moduleimpls
r5 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# moduleimpls_sem
r6 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_formsemestres():
"""
Test les routes de la partie Formsemestres
"""
# formsemestre
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# etudiant_bulletin
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# bulletins
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# jury
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_partitions():
"""
Test les routes de la partie Partitions
"""
# partition
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# etud_in_group
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# set_groups
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_evaluations():
"""
Test les routes de la partie Evaluations
"""
# evaluations
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# evaluation_notes
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# evaluation_set_notes
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_jury():
"""
Test les routes de la partie Jury
"""
# jury_preparation
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# jury_decisions
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# set_decision_jury
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# annule_decision_jury
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_absences():
"""
Test les routes de la partie Absences
"""
# absences
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# absences_justify
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# abs_signale
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# abs_annule
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# abs_annule_justif
r5 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# abs_groupe_etat
r6 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
def test_routes_logos():
"""
Test les routes de la partie Logos
"""
# liste_logos
r1 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# recup_logo_global
r2 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# logo_dept
r3 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)
# recup_logo_dept_global
r4 = requests.post(
SCODOC_URL + "/ScoDoc/api",
auth=(SCODOC_USER, SCODOC_PASSWORD)
)