API: bulletins: re-ecriture et format json classic avec matières (long_mat, short_mat).

This commit is contained in:
Emmanuel Viennet 2022-11-27 23:31:48 +01:00
parent fe301720c9
commit 7653342142
5 changed files with 49 additions and 128 deletions

View File

@ -9,7 +9,7 @@
"""
from datetime import datetime
from flask import g, jsonify, request
from flask import abort, g, jsonify, request
from flask_login import current_user
from flask_login import login_required
from sqlalchemy import desc, or_
@ -210,160 +210,75 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "pdf": False},
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin",
)
@bp.route(
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "pdf": False},
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>",
)
@bp.route(
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "pdf": False},
)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
methods=["GET"],
defaults={"version": "long", "pdf": True},
)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "pdf": False},
)
@bp.route(
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "pdf": False},
)
@bp.route(
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "pdf": False},
)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
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},
)
@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},
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>/pdf",
defaults={"pdf": True},
)
@api_web_bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "pdf": False},
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin",
)
@api_web_bp.route(
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "pdf": False},
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>",
)
@api_web_bp.route(
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "pdf": False},
)
@api_web_bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
methods=["GET"],
defaults={"version": "long", "pdf": True},
)
@api_web_bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "pdf": False},
)
@api_web_bp.route(
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "pdf": False},
)
@api_web_bp.route(
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "pdf": False},
)
@api_web_bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
methods=["GET"],
defaults={"version": "short", "pdf": True},
)
@api_web_bp.route(
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
methods=["GET"],
defaults={"version": "short", "pdf": True},
)
@api_web_bp.route(
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
methods=["GET"],
defaults={"version": "short", "pdf": True},
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>/pdf",
defaults={"pdf": True},
)
@scodoc
@permission_required(Permission.ScoView)
def etudiant_bulletin_semestre(
formsemestre_id,
etudid: int = None,
nip: str = None,
ine: str = None,
version="long",
def bulletin(
code_type: str = "etudid",
code: str = None,
formsemestre_id: int = None,
version: str = "long",
pdf: bool = False,
):
"""
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
Exemple de résultat : voir https://scodoc.org/ScoDoc9API/#bulletin
code_type : "etudid", "nip" ou "ine"
code : valeur du code INE, NIP ou etudid, selon code_type.
version : type de bulletin (par défaut, "long"): short, long, long_mat
pdf : si spécifié, bulletin au format PDF (et non JSON).
Exemple de résultat : voir https://scodoc.org/ScoDoc9API/#bulletin
"""
if version == "pdf":
version = "long"
pdf = True
# return f"{code_type}={code}, version={version}, pdf={pdf}"
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
if g.scodoc_dept and dept.acronym != g.scodoc_dept:
return json_error(404, "formsemestre non trouve")
if etudid is not None:
query = Identite.query.filter_by(id=etudid)
elif nip is not None:
query = Identite.query.filter_by(code_nip=nip, dept_id=dept.id)
elif ine is not None:
query = Identite.query.filter_by(code_ine=ine, dept_id=dept.id)
else:
return json_error(404, message="parametre manquant")
app.set_sco_dept(dept.acronym)
if code_type == "nip":
query = Identite.query.filter_by(code_nip=code, dept_id=dept.id)
elif code_type == "etudid":
try:
etudid = int(code)
except ValueError:
return json_error(404, "invalid etudid type")
query = Identite.query.filter_by(id=etudid)
elif code_type == "ine":
query = Identite.query.filter_by(code_ine=code, dept_id=dept.id)
else:
return json_error(404, "invalid code_type")
etud = query.first()
if etud is None:
return json_error(404, message="etudiant inexistant")
app.set_sco_dept(dept.acronym)
if pdf:
pdf_response, _ = do_formsemestre_bulletinetud(
formsemestre, etud.id, version=version, format="pdf"
)
return pdf_response
return sco_bulletins.get_formsemestre_bulletin_etud_json(
formsemestre, etud, version=version
)

View File

@ -990,6 +990,8 @@ def do_formsemestre_bulletinetud(
version=version,
)
return bul, ""
if version.endswith("_mat"):
version = version[:-4] # enlève le "_mat"
if formsemestre.formation.is_apc():
etudiant = Identite.query.get(etudid)

View File

@ -79,6 +79,8 @@ def make_xml_formsemestre_bulletinetud(
"bulletin au format XML"
from app.scodoc import sco_bulletins
if version.endswith("_mat"):
version = version[:-4] # enlève le "_mat" (ignoré en XML)
log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid))
sem = sco_formsemestre.get_formsemestre(formsemestre_id)

View File

@ -5,7 +5,7 @@ Démarche générale:
1. On génère une base SQL de test: voir
`tools/fakedatabase/create_test_api_database.py`
1. modifier /opt/scodoc/.env pour indiquer
1. modifier `/opt/scodoc/.env` pour indiquer
```bash
FLASK_ENV=test_api
@ -27,20 +27,20 @@ Démarche générale:
2. On lance le serveur ScoDoc sur cette base
```
```bash
flask run --host 0.0.0.0
```
3. On lance les tests unitaires API
```
```bash
pytest tests/api/test_api_departements.py
```
Rappel: pour interroger l'API, il fait avoir un utilisateur avec (au moins) la permission
ScoView dans tous les départements. Pour en créer un:
```
```bash
flask user-create lecteur_api LecteurAPI @all
flask user-password lecteur_api
flask edit-role LecteurAPI -a ScoView

View File

@ -14,7 +14,6 @@
import requests
from tests.api.setup_test_api import API_URL, SCODOC_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
from app import create_app
from config import RunningConfig
@ -33,13 +32,15 @@ def test_permissions(api_headers):
r
for r in app.url_map.iter_rules()
if str(r).startswith("/ScoDoc/api")
and not "logo" in str(r) # ignore logos
and not "absence" in str(r) # ignore absences
and "logo" not in str(r) # ignore logos
and "absence" not in str(r) # ignore absences
and "GET" in r.methods
]
assert len(api_rules) > 0
args = {
"acronym": "TAPI",
"code_type": "etudid",
"code": 1,
"dept_id": 1,
"dept_ident": "TAPI",
"dept": "TAPI",
@ -57,6 +58,7 @@ def test_permissions(api_headers):
"partition_id": 1,
"role_name": "Ens",
"uid": 1,
"version": "long",
}
for rule in api_rules:
path = rule.build(args)[1]