ScoDoc/app/api/departements.py
2022-11-02 08:00:24 +01:00

297 lines
8.9 KiB
Python

##############################################################################
# ScoDoc
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
# See LICENSE
##############################################################################
"""
ScoDoc 9 API : accès aux départements
Note: les routes /departement[s] sont publiées sur l'API (/ScoDoc/api/),
mais évidemment pas sur l'API web (/ScoDoc/<dept>/api).
"""
from datetime import datetime
from flask import jsonify, request
from flask_login import login_required
import app
from app import db, log
from app.api import api_bp as bp
from app.scodoc.sco_utils import json_error
from app.decorators import scodoc, permission_required
from app.models import Departement, FormSemestre
from app.models import departements
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_permissions import Permission
def get_departement(dept_ident: str) -> Departement:
"Le departement, par id ou acronyme. Erreur 404 si pas trouvé."
try:
dept_id = int(dept_ident)
except ValueError:
dept_id = None
if dept_id is None:
return Departement.query.filter_by(acronym=dept_ident).first_or_404()
return Departement.query.get_or_404(dept_id)
@bp.route("/departements")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def departements_list():
"""Liste les départements"""
return jsonify([dept.to_dict() for dept in Departement.query])
@bp.route("/departements_ids")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def departements_ids():
"""Liste des ids de départements"""
return jsonify([dept.id for dept in Departement.query])
@bp.route("/departement/<string:acronym>")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def departement(acronym: str):
"""
Info sur un département. Accès par acronyme.
Exemple de résultat :
{
"id": 1,
"acronym": "TAPI",
"description": null,
"visible": true,
"date_creation": "Fri, 15 Apr 2022 12:19:28 GMT"
}
"""
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
return jsonify(dept.to_dict())
@bp.route("/departement/id/<int:dept_id>")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def departement_by_id(dept_id: int):
"""
Info sur un département. Accès par id.
"""
dept = Departement.query.get_or_404(dept_id)
return jsonify(dept.to_dict())
@bp.route("/departement/create", methods=["POST"])
@login_required
@scodoc
@permission_required(Permission.ScoSuperAdmin)
def departement_create():
"""
Création d'un département.
The request content type should be "application/json":
{
"acronym": str,
"visible":bool,
}
"""
data = request.get_json(force=True) # may raise 400 Bad Request
acronym = str(data.get("acronym", ""))
if not acronym:
return json_error(404, "missing acronym")
visible = bool(data.get("visible", True))
try:
dept = departements.create_dept(acronym, visible=visible)
except ScoValueError as exc:
return json_error(404, exc.args[0] if exc.args else "")
return jsonify(dept.to_dict())
@bp.route("/departement/<string:acronym>/edit", methods=["POST"])
@login_required
@scodoc
@permission_required(Permission.ScoSuperAdmin)
def departement_edit(acronym):
"""
Edition d'un département: seul visible peut être modifié
The request content type should be "application/json":
{
"visible":bool,
}
"""
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
data = request.get_json(force=True) # may raise 400 Bad Request
visible = bool(data.get("visible", None))
if visible is None:
return json_error(404, "missing argument: visible")
visible = bool(visible)
dept.visible = visible
db.session.add(dept)
db.session.commit()
return jsonify(dept.to_dict())
@bp.route("/departement/<string:acronym>/delete", methods=["POST"])
@login_required
@scodoc
@permission_required(Permission.ScoSuperAdmin)
def departement_delete(acronym):
"""
Suppression d'un département.
"""
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
db.session.delete(dept)
db.session.commit()
return jsonify({"OK": True})
@bp.route("/departement/<string:acronym>/etudiants", methods=["GET"])
@login_required
@scodoc
@permission_required(Permission.ScoView)
def dept_etudiants(acronym: str):
"""
Retourne la liste des étudiants d'un département
acronym: l'acronyme d'un département
Exemple de résultat :
[
{
"civilite": "M",
"code_ine": "7899X61616",
"code_nip": "F6777H88",
"date_naissance": null,
"email": "toto@toto.fr",
"emailperso": null,
"etudid": 18,
"nom": "MOREL",
"prenom": "JACQUES"
},
...
]
"""
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
return jsonify([etud.to_dict_short() for etud in dept.etudiants])
@bp.route("/departement/id/<int:dept_id>/etudiants")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def dept_etudiants_by_id(dept_id: int):
"""
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")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def dept_formsemestres_ids(acronym: str):
"""liste des ids formsemestre du département"""
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
return jsonify([formsemestre.id for formsemestre in dept.formsemestres])
@bp.route("/departement/id/<int:dept_id>/formsemestres_ids")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def dept_formsemestres_ids_by_id(dept_id: int):
"""liste des ids formsemestre du département"""
dept = Departement.query.get_or_404(dept_id)
return jsonify([formsemestre.id for formsemestre in dept.formsemestres])
@bp.route("/departement/<string:acronym>/formsemestres_courants")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def dept_formsemestres_courants(acronym: str):
"""
Liste des semestres actifs d'un département d'acronyme donné
Exemple de résultat :
[
{
"titre": "master machine info",
"gestion_semestrielle": false,
"scodoc7_id": null,
"date_debut": "01/09/2021",
"bul_bgcolor": null,
"date_fin": "15/12/2022",
"resp_can_edit": false,
"dept_id": 1,
"etat": true,
"resp_can_change_ens": false,
"id": 1,
"modalite": "FI",
"ens_can_edit_eval": false,
"formation_id": 1,
"gestion_compensation": false,
"elt_sem_apo": null,
"semestre_id": 1,
"bul_hide_xml": false,
"elt_annee_apo": null,
"block_moyennes": false,
"formsemestre_id": 1,
"titre_num": "master machine info semestre 1",
"date_debut_iso": "2021-09-01",
"date_fin_iso": "2022-12-15",
"responsables": [
3,
2
]
},
...
]
"""
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
faked_date = request.args.get("faked_date")
if faked_date:
test_date = datetime.fromisoformat(faked_date)
else:
test_date = app.db.func.now()
# Les semestres en cours de ce département
formsemestres = FormSemestre.query.filter(
FormSemestre.dept_id == dept.id,
FormSemestre.date_debut <= test_date,
FormSemestre.date_fin >= test_date,
)
return jsonify([d.to_dict(convert_objects=True) for d in formsemestres])
@bp.route("/departement/id/<int:dept_id>/formsemestres_courants")
@login_required
@scodoc
@permission_required(Permission.ScoView)
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)
faked_date = request.args.get("faked_date")
if faked_date:
test_date = datetime.fromisoformat(faked_date)
else:
test_date = app.db.func.now()
# Les semestres en cours de ce département
formsemestres = FormSemestre.query.filter(
FormSemestre.dept_id == dept.id,
FormSemestre.date_debut <= test_date,
FormSemestre.date_fin >= test_date,
)
return jsonify([d.to_dict(convert_objects=True) for d in formsemestres])