forked from ScoDoc/ScoDoc
286 lines
7.2 KiB
Python
286 lines
7.2 KiB
Python
##############################################################################
|
|
# ScoDoc
|
|
# Copyright (c) 1999 - 2024 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).
|
|
|
|
CATEGORY
|
|
--------
|
|
Département
|
|
|
|
"""
|
|
from datetime import datetime
|
|
|
|
from flask import request
|
|
from flask_json import as_json
|
|
from flask_login import login_required
|
|
|
|
from app import db, log
|
|
from app.api import api_bp as bp, API_CLIENT_ERROR
|
|
from app.api import api_permission_required as permission_required
|
|
from app.decorators import scodoc
|
|
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
|
|
from app.scodoc.sco_utils import json_error
|
|
|
|
|
|
@bp.route("/departements")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departements_list():
|
|
"""Liste tous les départements.
|
|
|
|
SAMPLES
|
|
-------
|
|
/departements;
|
|
|
|
"""
|
|
return [dept.to_dict(with_dept_name=True) for dept in Departement.query]
|
|
|
|
|
|
@bp.route("/departements_ids")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departements_ids():
|
|
"""Liste des ids de tous les départements.
|
|
|
|
SAMPLES
|
|
-------
|
|
/departements_ids;
|
|
|
|
"""
|
|
return [dept.id for dept in Departement.query]
|
|
|
|
|
|
@bp.route("/departement/<string:acronym>")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_by_acronym(acronym: str):
|
|
"""
|
|
Info sur un département. Accès par acronyme.
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/TAPI;
|
|
|
|
"""
|
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
|
return dept.to_dict(with_dept_name=True)
|
|
|
|
|
|
@bp.route("/departement/id/<int:dept_id>")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_get(dept_id: int):
|
|
"""
|
|
Info sur un département. Accès par id.
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/id/1;
|
|
|
|
"""
|
|
dept = Departement.query.get_or_404(dept_id)
|
|
return dept.to_dict()
|
|
|
|
|
|
@bp.route("/departement/create", methods=["POST"])
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoSuperAdmin)
|
|
@as_json
|
|
def departement_create():
|
|
"""
|
|
Création d'un département.
|
|
Le content type doit être `application/json`.
|
|
DATA
|
|
----
|
|
```json
|
|
{
|
|
"acronym": str,
|
|
"visible": bool,
|
|
}
|
|
```
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/create;{""acronym"":""MYDEPT"",""visible"":""1""}
|
|
"""
|
|
data = request.get_json(force=True) # may raise 400 Bad Request
|
|
acronym = str(data.get("acronym", ""))
|
|
if not acronym:
|
|
return json_error(API_CLIENT_ERROR, "missing acronym")
|
|
visible = bool(data.get("visible", True))
|
|
try:
|
|
dept = departements.create_dept(acronym, visible=visible)
|
|
except ScoValueError as exc:
|
|
return json_error(500, exc.args[0] if exc.args else "")
|
|
|
|
log(f"departement_create {dept.acronym}")
|
|
|
|
return dept.to_dict()
|
|
|
|
|
|
@bp.route("/departement/<string:acronym>/edit", methods=["POST"])
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoSuperAdmin)
|
|
@as_json
|
|
def departement_edit(acronym):
|
|
"""
|
|
Édition d'un département: seul le champ `visible` peut être modifié.
|
|
|
|
DATA
|
|
----
|
|
{
|
|
"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(API_CLIENT_ERROR, "missing argument: visible")
|
|
visible = bool(visible)
|
|
dept.visible = visible
|
|
db.session.add(dept)
|
|
db.session.commit()
|
|
log(f"departement_edit {dept.acronym}")
|
|
return 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 identifié par son acronyme.
|
|
"""
|
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
|
acronym = dept.acronym
|
|
db.session.delete(dept)
|
|
db.session.commit()
|
|
log(f"departement_delete {acronym}")
|
|
return {"OK": True}
|
|
|
|
|
|
@bp.route("/departement/<string:acronym>/etudiants", methods=["GET"])
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_etudiants(acronym: str):
|
|
"""
|
|
Retourne la liste des étudiants d'un département.
|
|
|
|
PARAMS
|
|
------
|
|
acronym : l'acronyme d'un département
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/TAPI/etudiants;
|
|
|
|
"""
|
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
|
return [etud.to_dict_short() for etud in dept.etudiants]
|
|
|
|
|
|
@bp.route("/departement/id/<int:dept_id>/etudiants")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_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 [etud.to_dict_short() for etud in dept.etudiants]
|
|
|
|
|
|
@bp.route("/departement/<string:acronym>/formsemestres_ids")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_formsemestres_ids(acronym: str):
|
|
"""Liste des ids de tous les formsemestres du département.
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/TAPI/formsemestres_ids;
|
|
|
|
"""
|
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
|
return [formsemestre.id for formsemestre in dept.formsemestres]
|
|
|
|
|
|
@bp.route("/departement/id/<int:dept_id>/formsemestres_ids")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_formsemestres_ids_by_id(dept_id: int):
|
|
"""Liste des ids de tous les formsemestres du département.
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/id/1/formsemestres_ids;
|
|
|
|
"""
|
|
dept = Departement.query.get_or_404(dept_id)
|
|
return [formsemestre.id for formsemestre in dept.formsemestres]
|
|
|
|
|
|
@bp.route("/departement/<string:acronym>/formsemestres_courants")
|
|
@bp.route("/departement/id/<int:dept_id>/formsemestres_courants")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def departement_formsemestres_courants(acronym: str = "", dept_id: int | None = None):
|
|
"""
|
|
Liste les formsemestres du département indiqué (par son acronyme ou son id)
|
|
contenant la date courante, ou à défaut celle indiquée en argument
|
|
(au format ISO).
|
|
|
|
QUERY
|
|
-----
|
|
date_courante:<string:date_courante>
|
|
|
|
SAMPLES
|
|
-------
|
|
/departement/id/1/formsemestres_courants?date_courante=2022-01-01
|
|
"""
|
|
dept = (
|
|
Departement.query.filter_by(acronym=acronym).first_or_404()
|
|
if acronym
|
|
else Departement.query.get_or_404(dept_id)
|
|
)
|
|
date_courante = request.args.get("date_courante")
|
|
date_courante = datetime.fromisoformat(date_courante) if date_courante else None
|
|
return [
|
|
formsemestre.to_dict_api()
|
|
for formsemestre in FormSemestre.get_dept_formsemestres_courants(
|
|
dept, date_courante
|
|
)
|
|
]
|