############################################################################## # 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//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/") @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/") @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.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//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//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//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//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.get_or_404(dept_id) return [etud.to_dict_short() for etud in dept.etudiants] @bp.route("/departement//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//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.get_or_404(dept_id) return [formsemestre.id for formsemestre in dept.formsemestres] @bp.route("/departement//formsemestres_courants") @bp.route("/departement/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: 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.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 ) ]