forked from ScoDoc/ScoDoc
API: bulletins: re-ecriture et format json classic avec matières (long_mat, short_mat).
This commit is contained in:
parent
fe301720c9
commit
7653342142
@ -9,7 +9,7 @@
|
|||||||
"""
|
"""
|
||||||
from datetime import datetime
|
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 current_user
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
from sqlalchemy import desc, or_
|
from sqlalchemy import desc, or_
|
||||||
@ -210,160 +210,75 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
|
|||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin",
|
||||||
methods=["GET"],
|
|
||||||
defaults={"version": "long", "pdf": False},
|
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>",
|
||||||
methods=["GET"],
|
|
||||||
defaults={"version": "long", "pdf": False},
|
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>/pdf",
|
||||||
methods=["GET"],
|
defaults={"pdf": True},
|
||||||
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},
|
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin",
|
||||||
methods=["GET"],
|
|
||||||
defaults={"version": "long", "pdf": False},
|
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>",
|
||||||
methods=["GET"],
|
|
||||||
defaults={"version": "long", "pdf": False},
|
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
|
"/etudiant/<string:code_type>/<string:code>/formsemestre/<int:formsemestre_id>/bulletin/<string:version>/pdf",
|
||||||
methods=["GET"],
|
defaults={"pdf": True},
|
||||||
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},
|
|
||||||
)
|
)
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
def etudiant_bulletin_semestre(
|
def bulletin(
|
||||||
formsemestre_id,
|
code_type: str = "etudid",
|
||||||
etudid: int = None,
|
code: str = None,
|
||||||
nip: str = None,
|
formsemestre_id: int = None,
|
||||||
ine: str = None,
|
version: str = "long",
|
||||||
version="long",
|
|
||||||
pdf: bool = False,
|
pdf: bool = False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné
|
Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné
|
||||||
|
|
||||||
formsemestre_id : l'id d'un formsemestre
|
formsemestre_id : l'id d'un formsemestre
|
||||||
etudid : l'etudid d'un étudiant
|
code_type : "etudid", "nip" ou "ine"
|
||||||
nip : le code nip d'un étudiant
|
code : valeur du code INE, NIP ou etudid, selon code_type.
|
||||||
ine : le code ine d'un étudiant
|
version : type de bulletin (par défaut, "long"): short, long, long_mat
|
||||||
Exemple de résultat : voir https://scodoc.org/ScoDoc9API/#bulletin
|
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()
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
||||||
dept = Departement.query.filter_by(id=formsemestre.dept_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:
|
if g.scodoc_dept and dept.acronym != g.scodoc_dept:
|
||||||
return json_error(404, "formsemestre non trouve")
|
return json_error(404, "formsemestre non trouve")
|
||||||
if etudid is not None:
|
app.set_sco_dept(dept.acronym)
|
||||||
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")
|
|
||||||
|
|
||||||
|
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()
|
etud = query.first()
|
||||||
if etud is None:
|
if etud is None:
|
||||||
return json_error(404, message="etudiant inexistant")
|
return json_error(404, message="etudiant inexistant")
|
||||||
|
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
|
|
||||||
if pdf:
|
if pdf:
|
||||||
pdf_response, _ = do_formsemestre_bulletinetud(
|
pdf_response, _ = do_formsemestre_bulletinetud(
|
||||||
formsemestre, etud.id, version=version, format="pdf"
|
formsemestre, etud.id, version=version, format="pdf"
|
||||||
)
|
)
|
||||||
return pdf_response
|
return pdf_response
|
||||||
|
|
||||||
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
||||||
formsemestre, etud, version=version
|
formsemestre, etud, version=version
|
||||||
)
|
)
|
||||||
|
@ -990,6 +990,8 @@ def do_formsemestre_bulletinetud(
|
|||||||
version=version,
|
version=version,
|
||||||
)
|
)
|
||||||
return bul, ""
|
return bul, ""
|
||||||
|
if version.endswith("_mat"):
|
||||||
|
version = version[:-4] # enlève le "_mat"
|
||||||
|
|
||||||
if formsemestre.formation.is_apc():
|
if formsemestre.formation.is_apc():
|
||||||
etudiant = Identite.query.get(etudid)
|
etudiant = Identite.query.get(etudid)
|
||||||
|
@ -79,6 +79,8 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
"bulletin au format XML"
|
"bulletin au format XML"
|
||||||
from app.scodoc import sco_bulletins
|
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))
|
log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid))
|
||||||
|
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||||
|
@ -5,7 +5,7 @@ Démarche générale:
|
|||||||
1. On génère une base SQL de test: voir
|
1. On génère une base SQL de test: voir
|
||||||
`tools/fakedatabase/create_test_api_database.py`
|
`tools/fakedatabase/create_test_api_database.py`
|
||||||
|
|
||||||
1. modifier /opt/scodoc/.env pour indiquer
|
1. modifier `/opt/scodoc/.env` pour indiquer
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
FLASK_ENV=test_api
|
FLASK_ENV=test_api
|
||||||
@ -27,20 +27,20 @@ Démarche générale:
|
|||||||
|
|
||||||
2. On lance le serveur ScoDoc sur cette base
|
2. On lance le serveur ScoDoc sur cette base
|
||||||
|
|
||||||
```
|
```bash
|
||||||
flask run --host 0.0.0.0
|
flask run --host 0.0.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. On lance les tests unitaires API
|
3. On lance les tests unitaires API
|
||||||
|
|
||||||
```
|
```bash
|
||||||
pytest tests/api/test_api_departements.py
|
pytest tests/api/test_api_departements.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Rappel: pour interroger l'API, il fait avoir un utilisateur avec (au moins) la permission
|
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:
|
ScoView dans tous les départements. Pour en créer un:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
flask user-create lecteur_api LecteurAPI @all
|
flask user-create lecteur_api LecteurAPI @all
|
||||||
flask user-password lecteur_api
|
flask user-password lecteur_api
|
||||||
flask edit-role LecteurAPI -a ScoView
|
flask edit-role LecteurAPI -a ScoView
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tests.api.setup_test_api import API_URL, SCODOC_URL, CHECK_CERTIFICATE, api_headers
|
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 app import create_app
|
||||||
from config import RunningConfig
|
from config import RunningConfig
|
||||||
@ -33,13 +32,15 @@ def test_permissions(api_headers):
|
|||||||
r
|
r
|
||||||
for r in app.url_map.iter_rules()
|
for r in app.url_map.iter_rules()
|
||||||
if str(r).startswith("/ScoDoc/api")
|
if str(r).startswith("/ScoDoc/api")
|
||||||
and not "logo" in str(r) # ignore logos
|
and "logo" not in str(r) # ignore logos
|
||||||
and not "absence" in str(r) # ignore absences
|
and "absence" not in str(r) # ignore absences
|
||||||
and "GET" in r.methods
|
and "GET" in r.methods
|
||||||
]
|
]
|
||||||
assert len(api_rules) > 0
|
assert len(api_rules) > 0
|
||||||
args = {
|
args = {
|
||||||
"acronym": "TAPI",
|
"acronym": "TAPI",
|
||||||
|
"code_type": "etudid",
|
||||||
|
"code": 1,
|
||||||
"dept_id": 1,
|
"dept_id": 1,
|
||||||
"dept_ident": "TAPI",
|
"dept_ident": "TAPI",
|
||||||
"dept": "TAPI",
|
"dept": "TAPI",
|
||||||
@ -57,6 +58,7 @@ def test_permissions(api_headers):
|
|||||||
"partition_id": 1,
|
"partition_id": 1,
|
||||||
"role_name": "Ens",
|
"role_name": "Ens",
|
||||||
"uid": 1,
|
"uid": 1,
|
||||||
|
"version": "long",
|
||||||
}
|
}
|
||||||
for rule in api_rules:
|
for rule in api_rules:
|
||||||
path = rule.build(args)[1]
|
path = rule.build(args)[1]
|
||||||
|
Loading…
Reference in New Issue
Block a user