merge du master + ajout de abs_group_etat + ajout de test pour departements et etudiants

This commit is contained in:
leonard_montalbano 2022-05-09 16:26:23 +02:00
parent 864d90e22c
commit 61830180a5
44 changed files with 1169 additions and 1243 deletions

View File

@ -5,7 +5,7 @@ from flask import jsonify
from app.api import bp from app.api import bp
from app.api.errors import error_response from app.api.errors import error_response
from app.api.auth import token_auth, token_permission_required from app.api.auth import token_auth, token_permission_required
from app.api.tools import get_etu_from_etudid_or_nip_or_ine from app.api.tools import get_etud_from_etudid_or_nip_or_ine
from app.scodoc import notesdb as ndb from app.scodoc import notesdb as ndb
from app.scodoc import sco_abs from app.scodoc import sco_abs
@ -50,12 +50,11 @@ def absences(etudid: int = None, nip: int = None, ine: int = None):
""" """
if etudid is None: if etudid is None:
# Récupération de l'étudiant # Récupération de l'étudiant
etud = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine) etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
if etud is None: if etud is None:
return error_response( return error_response(
409, 404,
message="La requête ne peut être traitée en létat actuel.\n " message="id de l'étudiant (etudid, nip, ine) inconnu",
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
) )
etudid = etud.etudid etudid = etud.etudid
@ -103,16 +102,13 @@ def absences_just(etudid: int = None, nip: int = None, ine: int = None):
] ]
""" """
if etudid is None: if etudid is None:
# Récupération de l'étudiant etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
try: if etud is None:
etu = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
etudid = etu.etudid
except AttributeError:
return error_response( return error_response(
409, 404,
message="La requête ne peut être traitée en létat actuel.\n " message="id de l'étudiant (etudid, nip, ine) inconnu",
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
) )
etudid = etud.etudid
# Récupération des absences justifiées de l'étudiant # Récupération des absences justifiées de l'étudiant
abs_just = [ abs_just = [

View File

@ -1,57 +1,66 @@
############################################### Departements ########################################################## ############################################### Departements ##########################################################
import json
from flask import jsonify from flask import jsonify
import app
from app import models from app import models
from app.api import bp from app.api import bp
from app.api.auth import token_auth, token_permission_required from app.api.auth import token_auth, token_permission_required
from app.api.errors import error_response from app.models import Departement, FormSemestre
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
@bp.route("/departements", methods=["GET"]) 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_ids", methods=["GET"])
@token_auth.login_required @token_auth.login_required
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def departements(): def departements_ids():
"""Liste des ids de départements"""
return jsonify([dept.id for dept in Departement.query])
@bp.route("/departement/<string:dept_ident>", methods=["GET"])
@token_auth.login_required
@token_permission_required(Permission.APIView)
def departement(dept_ident: str):
""" """
Retourne la liste des départements visibles Info sur un département. Accès par id ou acronyme.
Exemple de résultat : Exemple de résultat :
[
{ {
"id": 1, "id": 1,
"acronym": "TAPI", "acronym": "TAPI",
"description": null, "description": null,
"visible": true, "visible": true,
"date_creation": "Fri, 15 Apr 2022 12:19:28 GMT" "date_creation": "Fri, 15 Apr 2022 12:19:28 GMT"
}, }
{
"id": 2,
"acronym": "MMI",
"description": null,
"visible": false,
"date_creation": "Fri, 18 Apr 2022 11:20:8 GMT"
},
...
]
""" """
# Récupération de tous les départements dept = get_departement(dept_ident)
depts = models.Departement.query.all() return jsonify(dept.to_dict())
# Mise en place de la liste avec tous les départements
data = [d.to_dict() for d in depts]
return jsonify(data)
@bp.route("/departements/<string:dept>/etudiants/list", methods=["GET"]) @bp.route("/departements", methods=["GET"])
@bp.route(
"/departements/<string:dept>/etudiants/list/<int:formsemestre_id>", methods=["GET"]
)
@token_auth.login_required @token_auth.login_required
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def list_etudiants(dept: str, formsemestre_id=None): def departements():
"""Liste les départements"""
return jsonify([dept.to_dict() for dept in Departement.query])
@bp.route("/departement/<string:dept_ident>/etudiants", methods=["GET"])
@token_auth.login_required
@token_permission_required(Permission.APIView)
def list_etudiants(dept_ident: str):
""" """
Retourne la liste des étudiants d'un département Retourne la liste des étudiants d'un département
@ -61,54 +70,39 @@ def list_etudiants(dept: str, formsemestre_id=None):
Exemple de résultat : Exemple de résultat :
[ [
{ {
"civilite": "X", "civilite": "M",
"code_ine": null, "ine": "7899X61616",
"code_nip": null, "nip": "F6777H88",
"date_naissance": null, "date_naissance": null,
"email": null, "email": "toto@toto.fr",
"emailperso": null, "emailperso": null,
"etudid": 18, "etudid": 18,
"nom": "MOREL", "nom": "MOREL",
"prenom": "JACQUES" "prenom": "JACQUES"
}, },
{
"civilite": "X",
"code_ine": null,
"code_nip": null,
"date_naissance": null,
"email": null,
"emailperso": null,
"etudid": 19,
"nom": "FOURNIER",
"prenom": "ANNE"
},
... ...
] ]
""" """
# Si le formsemestre_id a été renseigné # Le département, spécifié par un id ou un acronyme
if formsemestre_id is not None: dept = get_departement(dept_ident)
# Récupération du formsemestre
formsemestre = models.FormSemestre.query.filter_by(
id=formsemestre_id
).first_or_404()
# Récupération du département
departement = formsemestre.departement
# Si le formsemestre_id n'a pas été renseigné return jsonify([etud.to_dict_short() for etud in dept.etudiants])
else:
# Récupération du formsemestre
departement = models.Departement.query.filter_by(acronym=dept).first_or_404()
# Mise en forme des données
list_etu = [etu.to_dict_bul(include_urls=False) for etu in departement.etudiants]
return jsonify(list_etu)
@bp.route("/departements/<string:dept>/semestres_courants", methods=["GET"]) @bp.route("/departement/<string:dept_ident>/formsemestres_ids", methods=["GET"])
@token_auth.login_required @token_auth.login_required
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def liste_semestres_courant(dept: str): def formsemestres_ids(dept_ident: str):
"""liste des ids formsemestre du département"""
# Le département, spécifié par un id ou un acronyme
dept = get_departement(dept_ident)
return jsonify([formsemestre.id for formsemestre in dept.formsemestres])
@bp.route("/departement/<string:dept_ident>/formsemestres_courants", methods=["GET"])
@token_auth.login_required
@token_permission_required(Permission.APIView)
def liste_semestres_courant(dept_ident: str):
""" """
Liste des semestres actifs d'un départements donné Liste des semestres actifs d'un départements donné
@ -117,11 +111,16 @@ def liste_semestres_courant(dept: str):
Exemple de résultat : Exemple de résultat :
[ [
{ {
"date_fin": "31/08/2022", "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, "resp_can_edit": false,
"dept_id": 1, "dept_id": 1,
"etat": true, "etat": true,
"resp_can_change_ens": true, "resp_can_change_ens": false,
"id": 1, "id": 1,
"modalite": "FI", "modalite": "FI",
"ens_can_edit_eval": false, "ens_can_edit_eval": false,
@ -131,32 +130,27 @@ def liste_semestres_courant(dept: str):
"semestre_id": 1, "semestre_id": 1,
"bul_hide_xml": false, "bul_hide_xml": false,
"elt_annee_apo": null, "elt_annee_apo": null,
"titre": "Semestre test",
"block_moyennes": false, "block_moyennes": false,
"scodoc7_id": null,
"date_debut": "01/09/2021",
"gestion_semestrielle": false,
"bul_bgcolor": "white",
"formsemestre_id": 1, "formsemestre_id": 1,
"titre_num": "Semestre test semestre 1", "titre_num": "master machine info semestre 1",
"date_debut_iso": "2021-09-01", "date_debut_iso": "2021-09-01",
"date_fin_iso": "2022-08-31", "date_fin_iso": "2022-12-15",
"responsables": [ "responsables": [
12, 3,
42 2
], ]
"titre_court": "BUT MMI"
}, },
... ...
] ]
""" """
# Récupération des départements comportant l'acronym mit en paramètre # Le département, spécifié par un id ou un acronyme
dept = models.Departement.query.filter_by(acronym=dept).first_or_404() dept = get_departement(dept_ident)
# Récupération des semestres suivant id_dept # Les semestres en cours de ce département
semestres = models.FormSemestre.query.filter_by(dept_id=dept.id, etat=True) formsemestres = models.FormSemestre.query.filter(
FormSemestre.dept_id == dept.id,
FormSemestre.date_debut <= app.db.func.now(),
FormSemestre.date_fin >= app.db.func.now(),
)
# Mise en forme des données return jsonify([d.to_dict() for d in formsemestres])
data = [d.to_dict_api() for d in semestres]
return jsonify(data)

View File

@ -7,12 +7,10 @@ from app import models
from app.api import bp from app.api import bp
from app.api.errors import error_response from app.api.errors import error_response
from app.api.auth import token_auth, token_permission_required from app.api.auth import token_auth, token_permission_required
from app.api.tools import get_etu_from_etudid_or_nip_or_ine from app.api.tools import get_etud_from_etudid_or_nip_or_ine
from app.models import FormSemestreInscription, FormSemestre, Identite from app.models import FormSemestreInscription, FormSemestre, Identite
from app.scodoc import sco_bulletins from app.scodoc import sco_bulletins
from app.scodoc import sco_groups from app.scodoc import sco_groups
from app.scodoc.sco_bulletins import do_formsemestre_bulletinetud
from app.scodoc.sco_bulletins_pdf import get_etud_bulletins_pdf
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
@ -22,7 +20,7 @@ from app.scodoc.sco_permissions import Permission
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def etudiants_courant(long=False): def etudiants_courant(long=False):
""" """
Retourne la liste des étudiants courant Liste des étudiants inscrits dans un formsemestre actuellement en cours.
Exemple de résultat : Exemple de résultat :
[ [
@ -43,7 +41,6 @@ def etudiants_courant(long=False):
... ...
] ]
""" """
# Récupération de tous les étudiants
etuds = Identite.query.filter( etuds = Identite.query.filter(
Identite.id == FormSemestreInscription.etudid, Identite.id == FormSemestreInscription.etudid,
FormSemestreInscription.formsemestre_id == FormSemestre.id, FormSemestreInscription.formsemestre_id == FormSemestre.id,
@ -99,8 +96,12 @@ def etudiant(etudid: int = None, nip: int = None, ine: int = None):
} }
""" """
# Récupération de l'étudiant # Récupération de l'étudiant
etud = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine) etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
if etud is None:
return error_response(
404,
message="id de l'étudiant (etudid, nip, ine) inconnu",
)
# Mise en forme des données # Mise en forme des données
data = etud.to_dict_bul(include_urls=False) data = etud.to_dict_bul(include_urls=False)
@ -122,110 +123,81 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
Exemple de résultat : Exemple de résultat :
[ [
{ {
"date_fin": "31/08/2022", "date_fin": "31/08/2022",
"resp_can_edit": false, "resp_can_edit": false,
"dept_id": 1, "dept_id": 1,
"etat": true, "etat": true,
"resp_can_change_ens": true, "resp_can_change_ens": true,
"id": 1, "id": 1,
"modalite": "FI", "modalite": "FI",
"ens_can_edit_eval": false, "ens_can_edit_eval": false,
"formation_id": 1, "formation_id": 1,
"gestion_compensation": false, "gestion_compensation": false,
"elt_sem_apo": null, "elt_sem_apo": null,
"semestre_id": 1, "semestre_id": 1,
"bul_hide_xml": false, "bul_hide_xml": false,
"elt_annee_apo": null, "elt_annee_apo": null,
"titre": "Semestre test", "titre": "Semestre test",
"block_moyennes": false, "block_moyennes": false,
"scodoc7_id": null, "scodoc7_id": null,
"date_debut": "01/09/2021", "date_debut": "01/09/2021",
"gestion_semestrielle": false, "gestion_semestrielle": false,
"bul_bgcolor": "white", "bul_bgcolor": "white",
"formsemestre_id": 1, "formsemestre_id": 1,
"titre_num": "Semestre test semestre 1", "titre_num": "Semestre test semestre 1",
"date_debut_iso": "2021-09-01", "date_debut_iso": "2021-09-01",
"date_fin_iso": "2022-08-31", "date_fin_iso": "2022-08-31",
"responsables": [ "responsables": []
12, },
42 ...
],
"titre_court": "BUT MMI"
},
...
] ]
""" """
# Récupération de l'étudiant # Récupération de l'étudiant
etud = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine) etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
if etud is None:
return error_response(
404,
message="id de l'étudiant (etudid, nip, ine) inconnu",
)
formsemestres = models.FormSemestre.query.filter( formsemestres = models.FormSemestre.query.filter(
models.FormSemestreInscription.etudid == etud.id, models.FormSemestreInscription.etudid == etud.id,
models.FormSemestreInscription.formsemestre_id == models.FormSemestre.id, models.FormSemestreInscription.formsemestre_id == models.FormSemestre.id,
).order_by(models.FormSemestre.date_debut) ).order_by(models.FormSemestre.date_debut)
return jsonify([formsemestre.to_dict_api() for formsemestre in formsemestres]) return jsonify([formsemestre.to_dict() for formsemestre in formsemestres])
@bp.route( @bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin", "/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"], methods=["GET"],
defaults={"version": "long", "format": "json"}, defaults={"version": "long"},
) )
@bp.route( @bp.route(
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin", "/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"], methods=["GET"],
defaults={"version": "long", "format": "json"}, defaults={"version": "long"},
) )
@bp.route( @bp.route(
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin", "/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"], methods=["GET"],
defaults={"version": "long", "format": "json"}, defaults={"version": "long"},
)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
methods=["GET"],
defaults={"version": "long", "format": "pdf"},
)
@bp.route(
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
methods=["GET"],
defaults={"version": "long", "format": "pdf"},
)
@bp.route(
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/pdf",
methods=["GET"],
defaults={"version": "long", "format": "pdf"},
) )
@bp.route( @bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short", "/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"], methods=["GET"],
defaults={"version": "short", "format": "json"}, defaults={"version": "short"},
) )
@bp.route( @bp.route(
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/short", "/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"], methods=["GET"],
defaults={"version": "short", "format": "json"}, defaults={"version": "short"},
) )
@bp.route( @bp.route(
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/short", "/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"], methods=["GET"],
defaults={"version": "short", "format": "json"}, defaults={"version": "short"},
)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
methods=["GET"],
defaults={"version": "short", "format": "pdf"},
)
@bp.route(
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
methods=["GET"],
defaults={"version": "short", "format": "pdf"},
)
@bp.route(
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
methods=["GET"],
defaults={"version": "short", "format": "pdf"},
) )
@token_auth.login_required @token_auth.login_required
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
@ -235,7 +207,6 @@ def etudiant_bulletin_semestre(
nip: int = None, nip: int = None,
ine: int = None, ine: int = None,
version="long", version="long",
format="json",
): ):
""" """
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é
@ -421,23 +392,15 @@ def etudiant_bulletin_semestre(
app.set_sco_dept(dept.acronym) app.set_sco_dept(dept.acronym)
# Récupération de l'étudiant etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
try: if etud is None:
etu = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
except AttributeError:
return error_response( return error_response(
409, 404,
message="La requête ne peut être traitée en létat actuel.\n " message="id de l'étudiant (etudid, nip, ine) inconnu",
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
) )
if format == "json": return sco_bulletins.get_formsemestre_bulletin_etud_json(
return sco_bulletins.get_formsemestre_bulletin_etud_json( formsemestre, etud, version
formsemestre, etu, version )
)
else:
etudid = etu.id
print(etudid)
return do_formsemestre_bulletinetud(formsemestre, etudid, version, format)
@bp.route( @bp.route(
@ -490,12 +453,11 @@ def etudiant_groups(
] ]
""" """
if etudid is None: if etudid is None:
etud = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine) etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
if etud is None: if etud is None:
return error_response( return error_response(
409, 404,
message="La requête ne peut être traitée en létat actuel.\n " message="id de l'étudiant (etudid, nip, ine) inconnu",
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
) )
etudid = etud.etudid etudid = etud.etudid

View File

@ -99,7 +99,7 @@ def evaluation_notes(evaluation_id: int):
data = do_evaluation_get_all_notes(evaluation_id) data = do_evaluation_get_all_notes(evaluation_id)
except AttributeError: # ??? except AttributeError: # ???
return error_response( return error_response(
409, 404,
message="La requête ne peut être traitée en létat actuel.", message="La requête ne peut être traitée en létat actuel.",
) )

View File

@ -29,10 +29,10 @@ def formations_ids():
return jsonify(data) return jsonify(data)
@bp.route("/formations/<int:formation_id>", methods=["GET"]) @bp.route("/formation/<int:formation_id>", methods=["GET"])
@token_auth.login_required @token_auth.login_required
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def formations_by_id(formation_id: int): def formation_by_id(formation_id: int):
""" """
Retourne une formation en fonction d'un id donné Retourne une formation en fonction d'un id donné
@ -63,12 +63,12 @@ def formations_by_id(formation_id: int):
@bp.route( @bp.route(
"/formations/formation_export/<int:formation_id>", "/formation/formation_export/<int:formation_id>",
methods=["GET"], methods=["GET"],
defaults={"export_ids": False}, defaults={"export_ids": False},
) )
@bp.route( @bp.route(
"/formations/formation_export/<int:formation_id>/with_ids", "/formation/formation_export/<int:formation_id>/with_ids",
methods=["GET"], methods=["GET"],
defaults={"export_ids": True}, defaults={"export_ids": True},
) )
@ -177,16 +177,12 @@ def formation_export_by_formation_id(formation_id: int, export_ids=False):
# Utilisation de la fonction formation_export # Utilisation de la fonction formation_export
data = sco_formations.formation_export(formation_id, export_ids) data = sco_formations.formation_export(formation_id, export_ids)
except ValueError: except ValueError:
return error_response( return error_response(500, message="Erreur inconnue")
409,
message="La requête ne peut être traitée en létat actuel. \n"
"Veillez vérifier la conformité du 'formation_id'",
)
return jsonify(data) return jsonify(data)
@bp.route("/formations/moduleimpl/<int:moduleimpl_id>", methods=["GET"]) @bp.route("/formation/moduleimpl/<int:moduleimpl_id>", methods=["GET"])
@token_auth.login_required @token_auth.login_required
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def moduleimpl(moduleimpl_id: int): def moduleimpl(moduleimpl_id: int):
@ -199,7 +195,6 @@ def moduleimpl(moduleimpl_id: int):
{ {
"id": 1, "id": 1,
"formsemestre_id": 1, "formsemestre_id": 1,
"computation_expr": null,
"module_id": 1, "module_id": 1,
"responsable_id": 2, "responsable_id": 2,
"moduleimpl_id": 1, "moduleimpl_id": 1,
@ -231,63 +226,7 @@ def moduleimpl(moduleimpl_id: int):
@bp.route( @bp.route(
"/formations/moduleimpl/formsemestre/<int:formsemestre_id>/list", "/formation/<int:formation_id>/referentiel_competences",
methods=["GET"],
)
@token_auth.login_required
@token_permission_required(Permission.APIView)
def moduleimpls_sem(formsemestre_id: int):
"""
Retourne la liste des moduleimpl d'un semestre
formsemestre_id : l'id d'un formsemestre
Exemple d'utilisation :
[
{
"id": 1,
"formsemestre_id": 1,
"computation_expr": null,
"module_id": 1,
"responsable_id": 2,
"module": {
"heures_tp": 0.0,
"code_apogee": "",
"titre": "Initiation aux r\u00e9seaux informatiques",
"coefficient": 1.0,
"module_type": 2,
"id": 1,
"ects": null,
"abbrev": "Init aux r\u00e9seaux informatiques",
"ue_id": 1,
"code": "R101",
"formation_id": 1,
"heures_cours": 0.0,
"matiere_id": 1,
"heures_td": 0.0,
"semestre_id": 1,
"numero": 10,
"module_id": 1
},
"moduleimpl_id": 1,
"ens": []
},
...
]
"""
formsemestre = models.FormSemestre.query.filter_by(
id=formsemestre_id
).first_or_404()
moduleimpls = formsemestre.modimpls_sorted
data = [moduleimpl.to_dict() for moduleimpl in moduleimpls]
return jsonify(data)
@bp.route(
"/formations/<int:formation_id>/referentiel_competences",
methods=["GET"], methods=["GET"],
) )
@token_auth.login_required @token_auth.login_required

View File

@ -4,14 +4,11 @@ from flask import jsonify
import app import app
from app import models from app import models
from app.api import bp from app.api import bp
from app.api.errors import error_response
from app.api.auth import token_auth, token_permission_required from app.api.auth import token_auth, token_permission_required
from app.api.tools import get_etu_from_etudid_or_nip_or_ine from app.models import Departement, FormSemestre, FormSemestreEtape
from app.models import FormSemestre, FormSemestreEtape
from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json
from app.scodoc.sco_bulletins_json import make_json_formsemestre_bulletinetud
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_pvjury import formsemestre_pvjury from app.scodoc.sco_utils import ModuleType
@bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"]) @bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"])
@ -19,47 +16,50 @@ from app.scodoc.sco_pvjury import formsemestre_pvjury
@token_permission_required(Permission.APIView) @token_permission_required(Permission.APIView)
def formsemestre(formsemestre_id: int): def formsemestre(formsemestre_id: int):
""" """
Retourne l'information sur le formsemestre correspondant au formsemestre_id Information sur le formsemestre indiqué.
formsemestre_id : l'id d'un formsemestre formsemestre_id : l'id du formsemestre
Exemple de résultat : Exemple de résultat :
{ {
"date_fin": "31/08/2022", "block_moyennes": false,
"resp_can_edit": false, "bul_bgcolor": "white",
"dept_id": 1, "bul_hide_xml": false,
"etat": true, "date_debut_iso": "2021-09-01",
"resp_can_change_ens": true, "date_debut": "01/09/2021",
"id": 1, "date_fin_iso": "2022-08-31",
"modalite": "FI", "date_fin": "31/08/2022",
"ens_can_edit_eval": false, "dept_id": 1,
"formation_id": 1, "elt_annee_apo": null,
"gestion_compensation": false, "elt_sem_apo": null,
"elt_sem_apo": null, "ens_can_edit_eval": false,
"semestre_id": 1, "etat": true,
"bul_hide_xml": false, "formation_id": 1,
"elt_annee_apo": null, "formsemestre_id": 1,
"titre": "Semestre test", "gestion_compensation": false,
"block_moyennes": false, "gestion_semestrielle": false,
"scodoc7_id": null, "id": 1,
"date_debut": "01/09/2021", "modalite": "FI",
"gestion_semestrielle": false, "resp_can_change_ens": true,
"bul_bgcolor": "white", "resp_can_edit": false,
"formsemestre_id": 1, "responsables": [1, 99], // uids
"titre_num": "Semestre test semestre 1", "scodoc7_id": null,
"date_debut_iso": "2021-09-01", "semestre_id": 1,
"date_fin_iso": "2022-08-31", "titre_formation" : "BUT GEA",
"responsables": [ "titre_num": "BUT GEA semestre 1",
12, "titre": "BUT GEA",
42 }
],
"titre_court": "BUT MMI"
}
""" """
formsemestre = models.FormSemestre.query.filter_by( formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
id=formsemestre_id id=formsemestre_id
).first_or_404() ).first_or_404()
data = formsemestre.to_dict_api() data = formsemestre.to_dict()
# Pour le moment on a besoin de fixer le departement
# pour accéder aux préferences
dept = Departement.query.get(formsemestre.dept_id)
app.set_sco_dept(dept.acronym)
data["session_id"] = formsemestre.session_id()
return jsonify(data) return jsonify(data)
@ -73,47 +73,17 @@ def formsemestre_apo(etape_apo: str):
etape_apo : un code étape apogée etape_apo : un code étape apogée
Exemple de résultat : Exemple de résultat :
[ [
{ { ...formsemestre...
"date_fin": "31/08/2022", }, ...
"resp_can_edit": false, ]
"dept_id": 1,
"etat": true,
"resp_can_change_ens": true,
"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,
"titre": "Semestre test",
"block_moyennes": false,
"scodoc7_id": null,
"date_debut": "01/09/2021",
"gestion_semestrielle": false,
"bul_bgcolor": "white",
"formsemestre_id": 1,
"titre_num": "Semestre test semestre 1",
"date_debut_iso": "2021-09-01",
"date_fin_iso": "2022-08-31",
"responsables": [
12,
42
],
"titre_court": "BUT MMI"
},
...
]
""" """
formsemestres = FormSemestre.query.filter( formsemestres = FormSemestre.query.filter(
FormSemestreEtape.etape_apo == etape_apo, FormSemestreEtape.etape_apo == etape_apo,
FormSemestreEtape.formsemestre_id == FormSemestre.id, FormSemestreEtape.formsemestre_id == FormSemestre.id,
) )
return jsonify([formsemestre.to_dict_api() for formsemestre in formsemestres]) return jsonify([formsemestre.to_dict() for formsemestre in formsemestres])
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"]) @bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
@ -349,114 +319,96 @@ def bulletins(formsemestre_id: int):
# return jsonify(data) # return jsonify(data)
# XXX A spécifier et compléter TODO @bp.route(
# @bp.route( "/formsemestre/<int:formsemestre_id>/programme",
# "/formsemestre/<int:formsemestre_id>/programme", methods=["GET"],
# methods=["GET"], )
# ) @token_auth.login_required
# @token_auth.login_required @token_permission_required(Permission.APIView)
# @token_permission_required(Permission.APIView) def formsemestre_programme(formsemestre_id: int):
# def programme(formsemestre_id: int): """
# """ Retourne la liste des Ues, ressources et SAE d'un semestre
# Retourne la liste des Ues, ressources et SAE d'un semestre
# formsemestre_id : l'id d'un formsemestre
# formsemestre_id : l'id d'un formsemestre
# Exemple de résultat :
# Exemple de résultat : {
# { "ues": [
# "ues": [ {
# { "type": 0,
# "type": 0, "formation_id": 1,
# "formation_id": 1, "ue_code": "UCOD11",
# "ue_code": "UCOD11", "id": 1,
# "id": 1, "ects": 12.0,
# "ects": 12.0, "acronyme": "RT1.1",
# "acronyme": "RT1.1", "is_external": false,
# "is_external": false, "numero": 1,
# "numero": 1, "code_apogee": "",
# "code_apogee": "", "titre": "Administrer les r\u00e9seaux et l\u2019Internet",
# "titre": "Administrer les r\u00e9seaux et l\u2019Internet", "coefficient": 0.0,
# "coefficient": 0.0, "semestre_idx": 1,
# "semestre_idx": 1, "color": "#B80004",
# "color": "#B80004", "ue_id": 1
# "ue_id": 1 },
# }, ...
# ... ],
# ], "ressources": [
# "ressources": [ {
# { "ens": [ 10, 18 ],
# "titre": "Fondamentaux de la programmation", "formsemestre_id": 1,
# "coefficient": 1.0, "id": 15,
# "module_type": 2, "module": {
# "id": 17, "abbrev": "Programmer",
# "ects": null, "code": "SAE15",
# "abbrev": null, "code_apogee": "V7GOP",
# "ue_id": 3, "coefficient": 1.0,
# "code": "R107", "formation_id": 1,
# "formation_id": 1, "heures_cours": 0.0,
# "heures_cours": 0.0, "heures_td": 0.0,
# "matiere_id": 3, "heures_tp": 0.0,
# "heures_td": 0.0, "id": 15,
# "semestre_id": 1, "matiere_id": 3,
# "heures_tp": 0.0, "module_id": 15,
# "numero": 70, "module_type": 3,
# "code_apogee": "", "numero": 50,
# "module_id": 17 "semestre_id": 1,
# }, "titre": "Programmer en Python",
# ... "ue_id": 3
# ], },
# "saes": [ "module_id": 15,
# { "moduleimpl_id": 15,
# "titre": "Se pr\u00e9senter sur Internet", "responsable_id": 2
# "coefficient": 1.0, },
# "module_type": 3, ...
# "id": 14, ],
# "ects": null, "saes": [
# "abbrev": null, {
# "ue_id": 3, ...
# "code": "SAE14", },
# "formation_id": 1, ...
# "heures_cours": 0.0, ],
# "matiere_id": 3, "modules" : [ ... les modules qui ne sont ni des SAEs ni des ressources ... ]
# "heures_td": 0.0, }
# "semestre_id": 1, """
# "heures_tp": 0.0, formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
# "numero": 40, id=formsemestre_id
# "code_apogee": "", ).first_or_404()
# "module_id": 14
# }, ues = formsemestre.query_ues()
# ... m_list = {
# ] ModuleType.RESSOURCE: [],
# } ModuleType.SAE: [],
# """ ModuleType.STANDARD: [],
# }
# formsemestre: FormSemestre = models.FormSemestre.query.filter_by( for modimpl in formsemestre.modimpls_sorted:
# id=formsemestre_id d = modimpl.to_dict()
# ).first_or_404() m_list[modimpl.module.module_type].append(d)
#
# ues = formsemestre.query_ues() return jsonify(
# {
# ues_dict = [] "ues": [ue.to_dict() for ue in ues],
# ressources = [] "ressources": m_list[ModuleType.RESSOURCE],
# saes = [] "saes": m_list[ModuleType.SAE],
# "modules": m_list[ModuleType.STANDARD],
# for ue in ues: }
# ues_dict.append(ue.to_dict()) )
# ressources = ue.get_ressources()
# saes = ue.get_saes()
#
# data_ressources = []
# for ressource in ressources:
# data_ressources.append(ressource.to_dict())
#
# data_saes = []
# for sae in saes:
# data_saes.append(sae.to_dict())
#
# data = {
# "ues": ues_dict,
# "ressources": data_ressources,
# "saes": data_saes,
# }
#
# return data

View File

@ -113,11 +113,7 @@ def etud_in_group(group_id: int, etat=None):
data = get_group_members(group_id, etat) data = get_group_members(group_id, etat)
if len(data) == 0: if len(data) == 0:
return error_response( return error_response(404, message="group_id inconnu")
409,
message="La requête ne peut être traitée en létat actuel. \n"
"Aucun groupe ne correspond au 'group_id' renseigné",
)
return jsonify(data) return jsonify(data)
@ -146,8 +142,4 @@ def set_groups(
setGroups(partition_id, groups_lists, groups_to_create, groups_to_delete) setGroups(partition_id, groups_lists, groups_to_create, groups_to_delete)
return error_response(200, message="Groups set") return error_response(200, message="Groups set")
except ValueError: except ValueError:
return error_response( return error_response(404, message="Erreur")
409,
message="La requête ne peut être traitée en létat actuel. \n"
"Veillez vérifier la conformité des éléments passé en paramètres",
)

View File

@ -1,15 +1,17 @@
from app import models from app import models
def get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine): def get_etud_from_etudid_or_nip_or_ine(
etudid=None, nip=None, ine=None
) -> models.Identite:
""" """
Fonction qui retourne un etudiant en fonction de l'etudid, code nip et code ine rentré en paramètres etudiant en fonction de l'etudid, code nip et code ine rentré en paramètres
etudid : None ou un int etudid etudid : None ou un int etudid
nip : None ou un int code_nip nip : None ou un int code_nip
ine : None ou un int code_ine ine : None ou un int code_ine
Exemple de résultat: <Itendite> Return None si étudiant inexistant.
""" """
if etudid is None: if etudid is None:
if nip is None: # si ine if nip is None: # si ine

View File

@ -127,6 +127,9 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
def ue_rows(self, rows: list, ue_acronym: str, ue: dict, title_bg: tuple): def ue_rows(self, rows: list, ue_acronym: str, ue: dict, title_bg: tuple):
"Décrit une UE dans la table synthèse: titre, sous-titre et liste modules" "Décrit une UE dans la table synthèse: titre, sous-titre et liste modules"
if (ue["type"] == UE_SPORT) and len(ue.get("modules", [])) == 0:
# ne mentionne l'UE que s'il y a des modules
return
# 1er ligne titre UE # 1er ligne titre UE
moy_ue = ue.get("moyenne") moy_ue = ue.get("moyenne")
t = { t = {
@ -206,7 +209,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
for mod_code, mod in ue["modules"].items(): for mod_code, mod in ue["modules"].items():
rows.append( rows.append(
{ {
"titre": f"{mod_code} {mod['titre']}", "titre": f"{mod_code or ''} {mod['titre'] or ''}",
} }
) )
self.evaluations_rows(rows, mod["evaluations"]) self.evaluations_rows(rows, mod["evaluations"])
@ -313,7 +316,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
"lignes des évaluations" "lignes des évaluations"
for e in evaluations: for e in evaluations:
t = { t = {
"titre": f"{e['description']}", "titre": f"{e['description'] or ''}",
"moyenne": e["note"]["value"], "moyenne": e["note"]["value"],
"_moyenne_pdf": Paragraph( "_moyenne_pdf": Paragraph(
f"""<para align=right>{e["note"]["value"]}</para>""" f"""<para align=right>{e["note"]["value"]}</para>"""

View File

@ -146,6 +146,7 @@ class Identite(db.Model):
return { return {
"id": self.id, "id": self.id,
"nip": self.code_nip, "nip": self.code_nip,
"ine": self.code_ine,
"nom": self.nom, "nom": self.nom,
"nom_usuel": self.nom_usuel, "nom_usuel": self.nom_usuel,
"prenom": self.prenom, "prenom": self.prenom,

View File

@ -178,11 +178,12 @@ def evaluation_enrich_dict(e):
else: else:
e["descrheure"] = "" e["descrheure"] = ""
# matin, apresmidi: utile pour se referer aux absences: # matin, apresmidi: utile pour se referer aux absences:
if heure_debut_dt < datetime.time(12, 00):
if e["jour"] and heure_debut_dt < datetime.time(12, 00):
e["matin"] = 1 e["matin"] = 1
else: else:
e["matin"] = 0 e["matin"] = 0
if heure_fin_dt > datetime.time(12, 00): if e["jour"] and heure_fin_dt > datetime.time(12, 00):
e["apresmidi"] = 1 e["apresmidi"] = 1
else: else:
e["apresmidi"] = 0 e["apresmidi"] = 0

View File

@ -139,6 +139,7 @@ class FormSemestre(db.Model):
else: else:
d["date_fin"] = d["date_fin_iso"] = "" d["date_fin"] = d["date_fin_iso"] = ""
d["responsables"] = [u.id for u in self.responsables] d["responsables"] = [u.id for u in self.responsables]
d["titre_formation"] = self.titre_formation()
return d return d
def to_dict_api(self): def to_dict_api(self):
@ -351,9 +352,10 @@ class FormSemestre(db.Model):
ANNEE=annee universitaire de debut (exemple: un S2 de 2013-2014 sera S2-2013) ANNEE=annee universitaire de debut (exemple: un S2 de 2013-2014 sera S2-2013)
""" """
imputation_dept = sco_preferences.get_preference("ImputationDept", self.id) prefs = sco_preferences.SemPreferences(dept_id=self.dept_id)
imputation_dept = prefs["ImputationDept"]
if not imputation_dept: if not imputation_dept:
imputation_dept = sco_preferences.get_preference("DeptName") imputation_dept = prefs["DeptName"]
imputation_dept = imputation_dept.upper() imputation_dept = imputation_dept.upper()
parcours_name = self.formation.get_parcours().NAME parcours_name = self.formation.get_parcours().NAME
modalite = self.modalite modalite = self.modalite
@ -368,7 +370,7 @@ class FormSemestre(db.Model):
scu.annee_scolaire_debut(self.date_debut.year, self.date_debut.month) scu.annee_scolaire_debut(self.date_debut.year, self.date_debut.month)
) )
return scu.sanitize_string( return scu.sanitize_string(
"-".join((imputation_dept, parcours_name, modalite, semestre_id, annee_sco)) f"{imputation_dept}-{parcours_name}-{modalite}-{semestre_id}-{annee_sco}"
) )
def titre_annee(self) -> str: def titre_annee(self) -> str:
@ -380,6 +382,12 @@ class FormSemestre(db.Model):
titre_annee += "-" + str(self.date_fin.year) titre_annee += "-" + str(self.date_fin.year)
return titre_annee return titre_annee
def titre_formation(self):
"""Titre avec formation, court, pour passerelle: "BUT R&T"
(méthode de formsemestre car on pourrait ajouter le semestre, ou d'autres infos, à voir)
"""
return self.formation.acronyme
def titre_mois(self) -> str: def titre_mois(self) -> str:
"""Le titre et les dates du semestre, pour affichage dans des listes """Le titre et les dates du semestre, pour affichage dans des listes
Ex: "BUT QLIO (PN 2022) semestre 1 FI (Sept 2022 - Jan 2023)" Ex: "BUT QLIO (PN 2022) semestre 1 FI (Sept 2022 - Jan 2023)"

View File

@ -97,7 +97,7 @@ class SetTag(pe_tagtable.TableTag):
"""Mémorise les semtag nécessaires au jury.""" """Mémorise les semtag nécessaires au jury."""
self.SemTagDict = {fid: SemTagDict[fid] for fid in self.get_Fids_in_settag()} self.SemTagDict = {fid: SemTagDict[fid] for fid in self.get_Fids_in_settag()}
if PE_DEBUG >= 1: if PE_DEBUG >= 1:
pe_print(u" => %d semestres fusionnés" % len(self.SemTagDict)) pe_print(" => %d semestres fusionnés" % len(self.SemTagDict))
# ------------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------------
def comp_data_settag(self): def comp_data_settag(self):
@ -243,7 +243,7 @@ class SetTagInterClasse(pe_tagtable.TableTag):
fid: SetTagDict[fid] for fid in self.get_Fids_in_settag() if fid != None fid: SetTagDict[fid] for fid in self.get_Fids_in_settag() if fid != None
} }
if PE_DEBUG >= 1: if PE_DEBUG >= 1:
pe_print(u" => %d semestres utilisés" % len(self.SetTagDict)) pe_print(" => %d semestres utilisés" % len(self.SetTagDict))
# ------------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------------
def comp_data_settag(self): def comp_data_settag(self):

View File

@ -965,7 +965,7 @@ def _tables_abs_etud(
)[0] )[0]
if format == "html": if format == "html":
ex.append( ex.append(
f"""<a href="{url_for('notes.moduleimpl_status', f"""<a title="{mod['module']['titre']}" href="{url_for('notes.moduleimpl_status',
scodoc_dept=g.scodoc_dept, moduleimpl_id=mod["moduleimpl_id"])} scodoc_dept=g.scodoc_dept, moduleimpl_id=mod["moduleimpl_id"])}
">{mod["module"]["code"] or "(module sans code)"}</a>""" ">{mod["module"]["code"] or "(module sans code)"}</a>"""
) )

View File

@ -132,10 +132,13 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
if sco_preferences.get_preference( if sco_preferences.get_preference(
"bul_show_minmax_mod", formsemestre_id "bul_show_minmax_mod", formsemestre_id
): ):
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % ( rang_minmax = (
mod["mod_rang_txt"], '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
scu.fmt_note(mod["stats"]["min"]), % (
scu.fmt_note(mod["stats"]["max"]), mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
scu.fmt_note(mod["stats"]["max"]),
)
) )
else: else:
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang rang_minmax = mod["mod_rang_txt"] # vide si pas option rang

View File

@ -131,8 +131,10 @@ def index_html(showcodes=0, showsemtable=0):
if not showsemtable: if not showsemtable:
H.append( H.append(
f"""<hr> f"""<hr>
<p><a class="stdlink" href="{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept, showsemtable=1) <p><a class="stdlink" href="{url_for('scolar.index_html',
}">Voir tous les semestres ({len(othersems)} verrouillés)</a> scodoc_dept=g.scodoc_dept, showsemtable=1)
}">Voir table des semestres (dont {len(othersems)}
verrouillé{'s' if len(othersems) else ''})</a>
</p>""" </p>"""
) )

View File

@ -534,11 +534,14 @@ def formsemestre_inscription_option(etudid, formsemestre_id):
ue_status = nt.get_etud_ue_status(etudid, ue_id) ue_status = nt.get_etud_ue_status(etudid, ue_id)
if ue_status and ue_status["is_capitalized"]: if ue_status and ue_status["is_capitalized"]:
sem_origin = sco_formsemestre.get_formsemestre(ue_status["formsemestre_id"]) sem_origin = sco_formsemestre.get_formsemestre(ue_status["formsemestre_id"])
ue_descr += ' <a class="discretelink" href="formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" title="%s">(capitalisée le %s)' % ( ue_descr += (
sem_origin["formsemestre_id"], ' <a class="discretelink" href="formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" title="%s">(capitalisée le %s)'
etudid, % (
sem_origin["titreannee"], sem_origin["formsemestre_id"],
ndb.DateISOtoDMY(ue_status["event_date"]), etudid,
sem_origin["titreannee"],
ndb.DateISOtoDMY(ue_status["event_date"]),
)
) )
descr.append( descr.append(
( (

View File

@ -303,9 +303,12 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
) )
for mod in options: for mod in options:
if can_change: if can_change:
c_link = '<a class="discretelink" href="moduleimpl_inscriptions_edit?moduleimpl_id=%s">%s</a>' % ( c_link = (
mod["moduleimpl_id"], '<a class="discretelink" href="moduleimpl_inscriptions_edit?moduleimpl_id=%s">%s</a>'
mod["descri"] or "<i>(inscrire des étudiants)</i>", % (
mod["moduleimpl_id"],
mod["descri"] or "<i>(inscrire des étudiants)</i>",
)
) )
else: else:
c_link = mod["descri"] c_link = mod["descri"]

View File

@ -296,17 +296,18 @@ def ficheEtud(etudid=None):
if not sco_permissions_check.can_suppress_annotation(a["id"]): if not sco_permissions_check.can_suppress_annotation(a["id"]):
a["dellink"] = "" a["dellink"] = ""
else: else:
a[ a["dellink"] = (
"dellink" '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>'
] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % ( % (
etudid, etudid,
a["id"], a["id"],
scu.icontag( scu.icontag(
"delete_img", "delete_img",
border="0", border="0",
alt="suppress", alt="suppress",
title="Supprimer cette annotation", title="Supprimer cette annotation",
), ),
)
) )
author = sco_users.user_info(a["author"]) author = sco_users.user_info(a["author"])
alist.append( alist.append(

View File

@ -132,9 +132,12 @@ def clear_base_preferences():
g._SCO_BASE_PREFERENCES = {} # { dept_id: BasePreferences instance } g._SCO_BASE_PREFERENCES = {} # { dept_id: BasePreferences instance }
def get_base_preferences(): def get_base_preferences(dept_id: int = None):
"""Return global preferences for the current department""" """Return global preferences for the specified department
dept_id = g.scodoc_dept_id or the current departement
"""
if dept_id is None:
dept_id = g.scodoc_dept_id
if not hasattr(g, "_SCO_BASE_PREFERENCES"): if not hasattr(g, "_SCO_BASE_PREFERENCES"):
g._SCO_BASE_PREFERENCES = {} g._SCO_BASE_PREFERENCES = {}
if not dept_id in g._SCO_BASE_PREFERENCES: if not dept_id in g._SCO_BASE_PREFERENCES:
@ -142,12 +145,12 @@ def get_base_preferences():
return g._SCO_BASE_PREFERENCES[dept_id] return g._SCO_BASE_PREFERENCES[dept_id]
def get_preference(name, formsemestre_id=None): def get_preference(name, formsemestre_id=None, dept_id=None):
"""Returns value of named preference. """Returns value of named preference.
All preferences have a sensible default value, so this All preferences have a sensible default value, so this
function always returns a usable value for all defined preferences names. function always returns a usable value for all defined preferences names.
""" """
return get_base_preferences().get(formsemestre_id, name) return get_base_preferences(dept_id=dept_id).get(formsemestre_id, name)
def _convert_pref_type(p, pref_spec): def _convert_pref_type(p, pref_spec):
@ -2145,9 +2148,9 @@ class BasePreferences(object):
class SemPreferences: class SemPreferences:
"""Preferences for a formsemestre""" """Preferences for a formsemestre"""
def __init__(self, formsemestre_id=None): def __init__(self, formsemestre_id=None, dept_id=None):
self.formsemestre_id = formsemestre_id self.formsemestre_id = formsemestre_id
self.base_prefs = get_base_preferences() self.base_prefs = get_base_preferences(dept_id=dept_id)
def __getitem__(self, name): def __getitem__(self, name):
return self.base_prefs.get(self.formsemestre_id, name) return self.base_prefs.get(self.formsemestre_id, name)

View File

@ -799,22 +799,22 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id}) evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")
E = evals[0] eval_dict = evals[0]
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=eval_dict["moduleimpl_id"])[0]
formsemestre_id = M["formsemestre_id"] formsemestre_id = M["formsemestre_id"]
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0] Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"]) sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
mod_responsable = sco_users.user_info(M["responsable_id"]) mod_responsable = sco_users.user_info(M["responsable_id"])
if E["jour"]: if eval_dict["jour"]:
indication_date = ndb.DateDMYtoISO(E["jour"]) indication_date = ndb.DateDMYtoISO(eval_dict["jour"])
else: else:
indication_date = scu.sanitize_filename(E["description"])[:12] indication_date = scu.sanitize_filename(eval_dict["description"])[:12]
evalname = "%s-%s" % (Mod["code"], indication_date) eval_name = "%s-%s" % (Mod["code"], indication_date)
if E["description"]: if eval_dict["description"]:
evaltitre = "%s du %s" % (E["description"], E["jour"]) evaltitre = "%s du %s" % (eval_dict["description"], eval_dict["jour"])
else: else:
evaltitre = "évaluation du %s" % E["jour"] evaltitre = "évaluation du %s" % eval_dict["jour"]
description = "%s en %s (%s) resp. %s" % ( description = "%s en %s (%s) resp. %s" % (
evaltitre, evaltitre,
Mod["abbrev"] or "", Mod["abbrev"] or "",
@ -847,7 +847,7 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
# une liste de liste de chaines: lignes de la feuille de calcul # une liste de liste de chaines: lignes de la feuille de calcul
L = [] L = []
etuds = _get_sorted_etuds(E, etudids, formsemestre_id) etuds = _get_sorted_etuds(eval_dict, etudids, formsemestre_id)
for e in etuds: for e in etuds:
etudid = e["etudid"] etudid = e["etudid"]
groups = sco_groups.get_etud_groups(etudid, formsemestre_id) groups = sco_groups.get_etud_groups(etudid, formsemestre_id)
@ -865,8 +865,10 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
] ]
) )
filename = "notes_%s_%s" % (evalname, gr_title_filename) filename = "notes_%s_%s" % (eval_name, gr_title_filename)
xls = sco_excel.excel_feuille_saisie(E, sem["titreannee"], description, lines=L) xls = sco_excel.excel_feuille_saisie(
eval_dict, sem["titreannee"], description, lines=L
)
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE) return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
# return sco_excel.send_excel_file(xls, filename) # return sco_excel.send_excel_file(xls, filename)
@ -1008,10 +1010,9 @@ def saisie_notes(evaluation_id, group_ids=[]):
return "\n".join(H) return "\n".join(H)
def _get_sorted_etuds(E, etudids, formsemestre_id): def _get_sorted_etuds(eval_dict: dict, etudids: list, formsemestre_id: int):
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
notes_db = sco_evaluation_db.do_evaluation_get_all_notes( notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
E["evaluation_id"] eval_dict["evaluation_id"]
) # Notes existantes ) # Notes existantes
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
etuds = [] etuds = []
@ -1028,9 +1029,9 @@ def _get_sorted_etuds(E, etudids, formsemestre_id):
e["groups"] = sco_groups.get_etud_groups(etudid, formsemestre_id) e["groups"] = sco_groups.get_etud_groups(etudid, formsemestre_id)
# Information sur absence (tenant compte de la demi-journée) # Information sur absence (tenant compte de la demi-journée)
jour_iso = ndb.DateDMYtoISO(E["jour"]) jour_iso = ndb.DateDMYtoISO(eval_dict["jour"])
warn_abs_lst = [] warn_abs_lst = []
if E["matin"]: if eval_dict["matin"]:
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=1) nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=1)
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=1) nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=1)
if nbabs: if nbabs:
@ -1038,7 +1039,7 @@ def _get_sorted_etuds(E, etudids, formsemestre_id):
warn_abs_lst.append("absent justifié le matin !") warn_abs_lst.append("absent justifié le matin !")
else: else:
warn_abs_lst.append("absent le matin !") warn_abs_lst.append("absent le matin !")
if E["apresmidi"]: if eval_dict["apresmidi"]:
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0) nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0)
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0) nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
if nbabs: if nbabs:

View File

@ -14,17 +14,17 @@ config = context.config
# Interpret the config file for Python logging. # Interpret the config file for Python logging.
# This line sets up loggers basically. # This line sets up loggers basically.
fileConfig(config.config_file_name) fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env') logger = logging.getLogger("alembic.env")
# add your model's MetaData object here # add your model's MetaData object here
# for 'autogenerate' support # for 'autogenerate' support
# from myapp import mymodel # from myapp import mymodel
# target_metadata = mymodel.Base.metadata # target_metadata = mymodel.Base.metadata
config.set_main_option( config.set_main_option(
'sqlalchemy.url', "sqlalchemy.url",
str(current_app.extensions['migrate'].db.get_engine().url).replace( str(current_app.extensions["migrate"].db.get_engine().url).replace("%", "%%"),
'%', '%%')) )
target_metadata = current_app.extensions['migrate'].db.metadata target_metadata = current_app.extensions["migrate"].db.metadata
# other values from the config, defined by the needs of env.py, # other values from the config, defined by the needs of env.py,
# can be acquired: # can be acquired:
@ -45,9 +45,7 @@ def run_migrations_offline():
""" """
url = config.get_main_option("sqlalchemy.url") url = config.get_main_option("sqlalchemy.url")
context.configure( context.configure(url=url, target_metadata=target_metadata, literal_binds=True)
url=url, target_metadata=target_metadata, literal_binds=True
)
with context.begin_transaction(): with context.begin_transaction():
context.run_migrations() context.run_migrations()
@ -65,20 +63,20 @@ def run_migrations_online():
# when there are no changes to the schema # when there are no changes to the schema
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
def process_revision_directives(context, revision, directives): def process_revision_directives(context, revision, directives):
if getattr(config.cmd_opts, 'autogenerate', False): if getattr(config.cmd_opts, "autogenerate", False):
script = directives[0] script = directives[0]
if script.upgrade_ops.is_empty(): if script.upgrade_ops.is_empty():
directives[:] = [] directives[:] = []
logger.info('No changes in schema detected.') logger.info("No changes in schema detected.")
connectable = current_app.extensions['migrate'].db.get_engine() connectable = current_app.extensions["migrate"].db.get_engine()
with connectable.connect() as connection: with connectable.connect() as connection:
context.configure( context.configure(
connection=connection, connection=connection,
target_metadata=target_metadata, target_metadata=target_metadata,
process_revision_directives=process_revision_directives, process_revision_directives=process_revision_directives,
**current_app.extensions['migrate'].configure_args **current_app.extensions["migrate"].configure_args
) )
with context.begin_transaction(): with context.begin_transaction():

View File

@ -10,21 +10,23 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '017e32eb4773' revision = "017e32eb4773"
down_revision = '6b071b7947e5' down_revision = "6b071b7947e5"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.add_column('identite', sa.Column('scodoc7_id', sa.Text(), nullable=True)) op.add_column("identite", sa.Column("scodoc7_id", sa.Text(), nullable=True))
op.add_column('notes_formsemestre', sa.Column('scodoc7_id', sa.Text(), nullable=True)) op.add_column(
"notes_formsemestre", sa.Column("scodoc7_id", sa.Text(), nullable=True)
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_column('notes_formsemestre', 'scodoc7_id') op.drop_column("notes_formsemestre", "scodoc7_id")
op.drop_column('identite', 'scodoc7_id') op.drop_column("identite", "scodoc7_id")
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,21 +10,38 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '1efe07413835' revision = "1efe07413835"
down_revision = '75cf18659984' down_revision = "75cf18659984"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('absences_notifications_formsemestre_id_fkey', 'absences_notifications', type_='foreignkey') op.drop_constraint(
op.create_foreign_key(None, 'absences_notifications', 'notes_formsemestre', ['formsemestre_id'], ['id'], ondelete='CASCADE') "absences_notifications_formsemestre_id_fkey",
"absences_notifications",
type_="foreignkey",
)
op.create_foreign_key(
None,
"absences_notifications",
"notes_formsemestre",
["formsemestre_id"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'absences_notifications', type_='foreignkey') op.drop_constraint(None, "absences_notifications", type_="foreignkey")
op.create_foreign_key('absences_notifications_formsemestre_id_fkey', 'absences_notifications', 'notes_formsemestre', ['formsemestre_id'], ['id']) op.create_foreign_key(
"absences_notifications_formsemestre_id_fkey",
"absences_notifications",
"notes_formsemestre",
["formsemestre_id"],
["id"],
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,25 +10,57 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '39818df276aa' revision = "39818df276aa"
down_revision = '1efe07413835' down_revision = "1efe07413835"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('itemsuivi_tags_assoc_tag_id_fkey', 'itemsuivi_tags_assoc', type_='foreignkey') op.drop_constraint(
op.drop_constraint('itemsuivi_tags_assoc_itemsuivi_id_fkey', 'itemsuivi_tags_assoc', type_='foreignkey') "itemsuivi_tags_assoc_tag_id_fkey", "itemsuivi_tags_assoc", type_="foreignkey"
op.create_foreign_key(None, 'itemsuivi_tags_assoc', 'itemsuivi', ['itemsuivi_id'], ['id'], ondelete='CASCADE') )
op.create_foreign_key(None, 'itemsuivi_tags_assoc', 'itemsuivi_tags', ['tag_id'], ['id'], ondelete='CASCADE') op.drop_constraint(
"itemsuivi_tags_assoc_itemsuivi_id_fkey",
"itemsuivi_tags_assoc",
type_="foreignkey",
)
op.create_foreign_key(
None,
"itemsuivi_tags_assoc",
"itemsuivi",
["itemsuivi_id"],
["id"],
ondelete="CASCADE",
)
op.create_foreign_key(
None,
"itemsuivi_tags_assoc",
"itemsuivi_tags",
["tag_id"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'itemsuivi_tags_assoc', type_='foreignkey') op.drop_constraint(None, "itemsuivi_tags_assoc", type_="foreignkey")
op.drop_constraint(None, 'itemsuivi_tags_assoc', type_='foreignkey') op.drop_constraint(None, "itemsuivi_tags_assoc", type_="foreignkey")
op.create_foreign_key('itemsuivi_tags_assoc_itemsuivi_id_fkey', 'itemsuivi_tags_assoc', 'itemsuivi', ['itemsuivi_id'], ['id']) op.create_foreign_key(
op.create_foreign_key('itemsuivi_tags_assoc_tag_id_fkey', 'itemsuivi_tags_assoc', 'itemsuivi_tags', ['tag_id'], ['id']) "itemsuivi_tags_assoc_itemsuivi_id_fkey",
"itemsuivi_tags_assoc",
"itemsuivi",
["itemsuivi_id"],
["id"],
)
op.create_foreign_key(
"itemsuivi_tags_assoc_tag_id_fkey",
"itemsuivi_tags_assoc",
"itemsuivi_tags",
["tag_id"],
["id"],
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,19 +10,24 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '669065fb2d20' revision = "669065fb2d20"
down_revision = 'a217bf588f4c' down_revision = "a217bf588f4c"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.add_column('notes_formsemestre', sa.Column('block_moyennes', sa.Boolean(), server_default='false', nullable=False)) op.add_column(
"notes_formsemestre",
sa.Column(
"block_moyennes", sa.Boolean(), server_default="false", nullable=False
),
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_column('notes_formsemestre', 'block_moyennes') op.drop_column("notes_formsemestre", "block_moyennes")
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,25 +10,31 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '6b071b7947e5' revision = "6b071b7947e5"
down_revision = '993ce4a01d57' down_revision = "993ce4a01d57"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.alter_column('notes_modules', 'code', op.alter_column(
existing_type=sa.VARCHAR(length=32), "notes_modules",
type_=sa.Text(), "code",
existing_nullable=False) existing_type=sa.VARCHAR(length=32),
type_=sa.Text(),
existing_nullable=False,
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.alter_column('notes_modules', 'code', op.alter_column(
existing_type=sa.Text(), "notes_modules",
type_=sa.VARCHAR(length=32), "code",
existing_nullable=False) existing_type=sa.Text(),
type_=sa.VARCHAR(length=32),
existing_nullable=False,
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,26 +10,33 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '6cfc21a7ae1b' revision = "6cfc21a7ae1b"
down_revision = 'ada0d1f3d84f' down_revision = "ada0d1f3d84f"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.create_table('module_ue_coef', op.create_table(
sa.Column('module_id', sa.Integer(), nullable=False), "module_ue_coef",
sa.Column('ue_id', sa.Integer(), nullable=False), sa.Column("module_id", sa.Integer(), nullable=False),
sa.Column('coef', sa.Float(), nullable=False), sa.Column("ue_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['module_id'], ['notes_modules.id'], ), sa.Column("coef", sa.Float(), nullable=False),
sa.ForeignKeyConstraint(['ue_id'], ['notes_ue.id'], ), sa.ForeignKeyConstraint(
sa.PrimaryKeyConstraint('module_id', 'ue_id') ["module_id"],
["notes_modules.id"],
),
sa.ForeignKeyConstraint(
["ue_id"],
["notes_ue.id"],
),
sa.PrimaryKeyConstraint("module_id", "ue_id"),
) )
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_table('module_ue_coef') op.drop_table("module_ue_coef")
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,25 +10,50 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '75cf18659984' revision = "75cf18659984"
down_revision = 'd74b4e16fb3c' down_revision = "d74b4e16fb3c"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('notes_modules_tags_tag_id_fkey', 'notes_modules_tags', type_='foreignkey') op.drop_constraint(
op.drop_constraint('notes_modules_tags_module_id_fkey', 'notes_modules_tags', type_='foreignkey') "notes_modules_tags_tag_id_fkey", "notes_modules_tags", type_="foreignkey"
op.create_foreign_key(None, 'notes_modules_tags', 'notes_tags', ['tag_id'], ['id'], ondelete='CASCADE') )
op.create_foreign_key(None, 'notes_modules_tags', 'notes_modules', ['module_id'], ['id'], ondelete='CASCADE') op.drop_constraint(
"notes_modules_tags_module_id_fkey", "notes_modules_tags", type_="foreignkey"
)
op.create_foreign_key(
None, "notes_modules_tags", "notes_tags", ["tag_id"], ["id"], ondelete="CASCADE"
)
op.create_foreign_key(
None,
"notes_modules_tags",
"notes_modules",
["module_id"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'notes_modules_tags', type_='foreignkey') op.drop_constraint(None, "notes_modules_tags", type_="foreignkey")
op.drop_constraint(None, 'notes_modules_tags', type_='foreignkey') op.drop_constraint(None, "notes_modules_tags", type_="foreignkey")
op.create_foreign_key('notes_modules_tags_module_id_fkey', 'notes_modules_tags', 'notes_modules', ['module_id'], ['id']) op.create_foreign_key(
op.create_foreign_key('notes_modules_tags_tag_id_fkey', 'notes_modules_tags', 'notes_tags', ['tag_id'], ['id']) "notes_modules_tags_module_id_fkey",
"notes_modules_tags",
"notes_modules",
["module_id"],
["id"],
)
op.create_foreign_key(
"notes_modules_tags_tag_id_fkey",
"notes_modules_tags",
"notes_tags",
["tag_id"],
["id"],
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,46 +10,77 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '92789d50f6b6' revision = "92789d50f6b6"
down_revision = '00ad500fb118' down_revision = "00ad500fb118"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_table('modules_acs') op.drop_table("modules_acs")
op.drop_table('app_crit') op.drop_table("app_crit")
op.add_column('apc_annee_parcours', sa.Column('ordre', sa.Integer(), nullable=True)) op.add_column("apc_annee_parcours", sa.Column("ordre", sa.Integer(), nullable=True))
op.drop_column('apc_annee_parcours', 'numero') op.drop_column("apc_annee_parcours", "numero")
op.create_index(op.f('ix_apc_app_critique_code'), 'apc_app_critique', ['code'], unique=False) op.create_index(
op.create_unique_constraint('apc_competence_referentiel_id_titre_key', 'apc_competence', ['referentiel_id', 'titre']) op.f("ix_apc_app_critique_code"), "apc_app_critique", ["code"], unique=False
op.create_index(op.f('ix_apc_competence_titre'), 'apc_competence', ['titre'], unique=False) )
op.add_column('apc_referentiel_competences', sa.Column('scodoc_date_loaded', sa.DateTime(), nullable=True)) op.create_unique_constraint(
op.add_column('apc_referentiel_competences', sa.Column('scodoc_orig_filename', sa.Text(), nullable=True)) "apc_competence_referentiel_id_titre_key",
"apc_competence",
["referentiel_id", "titre"],
)
op.create_index(
op.f("ix_apc_competence_titre"), "apc_competence", ["titre"], unique=False
)
op.add_column(
"apc_referentiel_competences",
sa.Column("scodoc_date_loaded", sa.DateTime(), nullable=True),
)
op.add_column(
"apc_referentiel_competences",
sa.Column("scodoc_orig_filename", sa.Text(), nullable=True),
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_column('apc_referentiel_competences', 'scodoc_orig_filename') op.drop_column("apc_referentiel_competences", "scodoc_orig_filename")
op.drop_column('apc_referentiel_competences', 'scodoc_date_loaded') op.drop_column("apc_referentiel_competences", "scodoc_date_loaded")
op.drop_index(op.f('ix_apc_competence_titre'), table_name='apc_competence') op.drop_index(op.f("ix_apc_competence_titre"), table_name="apc_competence")
op.drop_constraint('apc_competence_referentiel_id_titre_key', 'apc_competence', type_='unique') op.drop_constraint(
op.drop_index(op.f('ix_apc_app_critique_code'), table_name='apc_app_critique') "apc_competence_referentiel_id_titre_key", "apc_competence", type_="unique"
op.add_column('apc_annee_parcours', sa.Column('numero', sa.INTEGER(), autoincrement=False, nullable=True))
op.drop_column('apc_annee_parcours', 'ordre')
op.create_table('app_crit',
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('app_crit_id_seq'::regclass)"), autoincrement=True, nullable=False),
sa.Column('code', sa.TEXT(), autoincrement=False, nullable=False),
sa.Column('titre', sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint('id', name='app_crit_pkey'),
postgresql_ignore_search_path=False
) )
op.create_table('modules_acs', op.drop_index(op.f("ix_apc_app_critique_code"), table_name="apc_app_critique")
sa.Column('module_id', sa.INTEGER(), autoincrement=False, nullable=True), op.add_column(
sa.Column('ac_id', sa.INTEGER(), autoincrement=False, nullable=True), "apc_annee_parcours",
sa.ForeignKeyConstraint(['ac_id'], ['app_crit.id'], name='modules_acs_ac_id_fkey'), sa.Column("numero", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['module_id'], ['notes_modules.id'], name='modules_acs_module_id_fkey') )
op.drop_column("apc_annee_parcours", "ordre")
op.create_table(
"app_crit",
sa.Column(
"id",
sa.INTEGER(),
server_default=sa.text("nextval('app_crit_id_seq'::regclass)"),
autoincrement=True,
nullable=False,
),
sa.Column("code", sa.TEXT(), autoincrement=False, nullable=False),
sa.Column("titre", sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint("id", name="app_crit_pkey"),
postgresql_ignore_search_path=False,
)
op.create_table(
"modules_acs",
sa.Column("module_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("ac_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["ac_id"], ["app_crit.id"], name="modules_acs_ac_id_fkey"
),
sa.ForeignKeyConstraint(
["module_id"], ["notes_modules.id"], name="modules_acs_module_id_fkey"
),
) )
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,27 +10,50 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'a217bf588f4c' revision = "a217bf588f4c"
down_revision = 'f73251d1d825' down_revision = "f73251d1d825"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.alter_column('notes_semset_formsemestre', 'semset_id', op.alter_column(
existing_type=sa.INTEGER(), "notes_semset_formsemestre",
nullable=False) "semset_id",
op.drop_constraint('notes_semset_formsemestre_semset_id_fkey', 'notes_semset_formsemestre', type_='foreignkey') existing_type=sa.INTEGER(),
op.create_foreign_key(None, 'notes_semset_formsemestre', 'notes_semset', ['semset_id'], ['id'], ondelete='CASCADE') nullable=False,
)
op.drop_constraint(
"notes_semset_formsemestre_semset_id_fkey",
"notes_semset_formsemestre",
type_="foreignkey",
)
op.create_foreign_key(
None,
"notes_semset_formsemestre",
"notes_semset",
["semset_id"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'notes_semset_formsemestre', type_='foreignkey') op.drop_constraint(None, "notes_semset_formsemestre", type_="foreignkey")
op.create_foreign_key('notes_semset_formsemestre_semset_id_fkey', 'notes_semset_formsemestre', 'notes_semset', ['semset_id'], ['id']) op.create_foreign_key(
op.alter_column('notes_semset_formsemestre', 'semset_id', "notes_semset_formsemestre_semset_id_fkey",
existing_type=sa.INTEGER(), "notes_semset_formsemestre",
nullable=True) "notes_semset",
["semset_id"],
["id"],
)
op.alter_column(
"notes_semset_formsemestre",
"semset_id",
existing_type=sa.INTEGER(),
nullable=True,
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,21 +10,23 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'c8efc54586d8' revision = "c8efc54586d8"
down_revision = '6cfc21a7ae1b' down_revision = "6cfc21a7ae1b"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.add_column('notes_ue', sa.Column('semestre_idx', sa.Integer(), nullable=True)) op.add_column("notes_ue", sa.Column("semestre_idx", sa.Integer(), nullable=True))
op.create_index(op.f('ix_notes_ue_semestre_idx'), 'notes_ue', ['semestre_idx'], unique=False) op.create_index(
op.f("ix_notes_ue_semestre_idx"), "notes_ue", ["semestre_idx"], unique=False
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_notes_ue_semestre_idx'), table_name='notes_ue') op.drop_index(op.f("ix_notes_ue_semestre_idx"), table_name="notes_ue")
op.drop_column('notes_ue', 'semestre_idx') op.drop_column("notes_ue", "semestre_idx")
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,23 +10,25 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'd3d92b2d0092' revision = "d3d92b2d0092"
down_revision = '017e32eb4773' down_revision = "017e32eb4773"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.add_column('itemsuivi_tags', sa.Column('dept_id', sa.Integer(), nullable=True)) op.add_column("itemsuivi_tags", sa.Column("dept_id", sa.Integer(), nullable=True))
op.create_index(op.f('ix_itemsuivi_tags_dept_id'), 'itemsuivi_tags', ['dept_id'], unique=False) op.create_index(
op.create_foreign_key(None, 'itemsuivi_tags', 'departement', ['dept_id'], ['id']) op.f("ix_itemsuivi_tags_dept_id"), "itemsuivi_tags", ["dept_id"], unique=False
)
op.create_foreign_key(None, "itemsuivi_tags", "departement", ["dept_id"], ["id"])
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'itemsuivi_tags', type_='foreignkey') op.drop_constraint(None, "itemsuivi_tags", type_="foreignkey")
op.drop_index(op.f('ix_itemsuivi_tags_dept_id'), table_name='itemsuivi_tags') op.drop_index(op.f("ix_itemsuivi_tags_dept_id"), table_name="itemsuivi_tags")
op.drop_column('itemsuivi_tags', 'dept_id') op.drop_column("itemsuivi_tags", "dept_id")
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,49 +10,73 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'f6e7d2e01be1' revision = "f6e7d2e01be1"
down_revision = 'd3d92b2d0092' down_revision = "d3d92b2d0092"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.alter_column('notes_formsemestre_etapes', 'etape_apo', op.alter_column(
existing_type=sa.VARCHAR(length=16), "notes_formsemestre_etapes",
type_=sa.String(length=24), "etape_apo",
existing_nullable=True) existing_type=sa.VARCHAR(length=16),
op.alter_column('notes_formsemestre_inscription', 'etape', type_=sa.String(length=24),
existing_type=sa.VARCHAR(length=16), existing_nullable=True,
type_=sa.String(length=24), )
existing_nullable=True) op.alter_column(
op.alter_column('notes_modules', 'code_apogee', "notes_formsemestre_inscription",
existing_type=sa.VARCHAR(length=16), "etape",
type_=sa.String(length=24), existing_type=sa.VARCHAR(length=16),
existing_nullable=True) type_=sa.String(length=24),
op.alter_column('notes_ue', 'code_apogee', existing_nullable=True,
existing_type=sa.VARCHAR(length=16), )
type_=sa.String(length=24), op.alter_column(
existing_nullable=True) "notes_modules",
"code_apogee",
existing_type=sa.VARCHAR(length=16),
type_=sa.String(length=24),
existing_nullable=True,
)
op.alter_column(
"notes_ue",
"code_apogee",
existing_type=sa.VARCHAR(length=16),
type_=sa.String(length=24),
existing_nullable=True,
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.alter_column('notes_ue', 'code_apogee', op.alter_column(
existing_type=sa.String(length=24), "notes_ue",
type_=sa.VARCHAR(length=16), "code_apogee",
existing_nullable=True) existing_type=sa.String(length=24),
op.alter_column('notes_modules', 'code_apogee', type_=sa.VARCHAR(length=16),
existing_type=sa.String(length=24), existing_nullable=True,
type_=sa.VARCHAR(length=16), )
existing_nullable=True) op.alter_column(
op.alter_column('notes_formsemestre_inscription', 'etape', "notes_modules",
existing_type=sa.String(length=24), "code_apogee",
type_=sa.VARCHAR(length=16), existing_type=sa.String(length=24),
existing_nullable=True) type_=sa.VARCHAR(length=16),
op.alter_column('notes_formsemestre_etapes', 'etape_apo', existing_nullable=True,
existing_type=sa.String(length=24), )
type_=sa.VARCHAR(length=16), op.alter_column(
existing_nullable=True) "notes_formsemestre_inscription",
"etape",
existing_type=sa.String(length=24),
type_=sa.VARCHAR(length=16),
existing_nullable=True,
)
op.alter_column(
"notes_formsemestre_etapes",
"etape_apo",
existing_type=sa.String(length=24),
type_=sa.VARCHAR(length=16),
existing_nullable=True,
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,26 +10,29 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'f73251d1d825' revision = "f73251d1d825"
down_revision = 'f6e7d2e01be1' down_revision = "f6e7d2e01be1"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.create_table('scodoc_site_config', op.create_table(
sa.Column('id', sa.Integer(), nullable=False), "scodoc_site_config",
sa.Column('name', sa.String(length=128), nullable=False), sa.Column("id", sa.Integer(), nullable=False),
sa.Column('value', sa.Text(), nullable=True), sa.Column("name", sa.String(length=128), nullable=False),
sa.PrimaryKeyConstraint('id') sa.Column("value", sa.Text(), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(
op.f("ix_scodoc_site_config_name"), "scodoc_site_config", ["name"], unique=False
) )
op.create_index(op.f('ix_scodoc_site_config_name'), 'scodoc_site_config', ['name'], unique=False)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_scodoc_site_config_name'), table_name='scodoc_site_config') op.drop_index(op.f("ix_scodoc_site_config_name"), table_name="scodoc_site_config")
op.drop_table('scodoc_site_config') op.drop_table("scodoc_site_config")
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -10,21 +10,31 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'f86c013c9fbd' revision = "f86c013c9fbd"
down_revision = '669065fb2d20' down_revision = "669065fb2d20"
branch_labels = None branch_labels = None
depends_on = None depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('notes_formations_acronyme_titre_version_key', 'notes_formations', type_='unique') op.drop_constraint(
op.create_unique_constraint(None, 'notes_formations', ['dept_id', 'acronyme', 'titre', 'version']) "notes_formations_acronyme_titre_version_key",
"notes_formations",
type_="unique",
)
op.create_unique_constraint(
None, "notes_formations", ["dept_id", "acronyme", "titre", "version"]
)
# ### end Alembic commands ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'notes_formations', type_='unique') op.drop_constraint(None, "notes_formations", type_="unique")
op.create_unique_constraint('notes_formations_acronyme_titre_version_key', 'notes_formations', ['acronyme', 'titre', 'version']) op.create_unique_constraint(
"notes_formations_acronyme_titre_version_key",
"notes_formations",
["acronyme", "titre", "version"],
)
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -7,65 +7,84 @@ Source: http://wikipython.flibuste.net/moin.py/JouerAvecUnicode#head-1213938516c
""" """
_reptable = {} _reptable = {}
def _fill_reptable(): def _fill_reptable():
_corresp = [ _corresp = [
(u"A", [0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x0100,0x0102,0x0104]), ("A", [0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x0100, 0x0102, 0x0104]),
(u"AE", [0x00C6]), ("AE", [0x00C6]),
(u"a", [0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x0101,0x0103,0x0105]), ("a", [0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x0101, 0x0103, 0x0105]),
(u"ae", [0x00E6]), ("ae", [0x00E6]),
(u"C", [0x00C7,0x0106,0x0108,0x010A,0x010C]), ("C", [0x00C7, 0x0106, 0x0108, 0x010A, 0x010C]),
(u"c", [0x00E7,0x0107,0x0109,0x010B,0x010D]), ("c", [0x00E7, 0x0107, 0x0109, 0x010B, 0x010D]),
(u"D", [0x00D0,0x010E,0x0110]), ("D", [0x00D0, 0x010E, 0x0110]),
(u"d", [0x00F0,0x010F,0x0111]), ("d", [0x00F0, 0x010F, 0x0111]),
(u"E", [0x00C8,0x00C9,0x00CA,0x00CB,0x0112,0x0114,0x0116,0x0118,0x011A]), ("E", [0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0112, 0x0114, 0x0116, 0x0118, 0x011A]),
(u"e", [0x00E8,0x00E9,0x00EA,0x00EB,0x0113,0x0115,0x0117,0x0119,0x011B]), ("e", [0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0113, 0x0115, 0x0117, 0x0119, 0x011B]),
(u"G", [0x011C,0x011E,0x0120,0x0122]), ("G", [0x011C, 0x011E, 0x0120, 0x0122]),
(u"g", [0x011D,0x011F,0x0121,0x0123]), ("g", [0x011D, 0x011F, 0x0121, 0x0123]),
(u"H", [0x0124,0x0126]), ("H", [0x0124, 0x0126]),
(u"h", [0x0125,0x0127]), ("h", [0x0125, 0x0127]),
(u"I", [0x00CC,0x00CD,0x00CE,0x00CF,0x0128,0x012A,0x012C,0x012E,0x0130]), ("I", [0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0128, 0x012A, 0x012C, 0x012E, 0x0130]),
(u"i", [0x00EC,0x00ED,0x00EE,0x00EF,0x0129,0x012B,0x012D,0x012F,0x0131]), ("i", [0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0129, 0x012B, 0x012D, 0x012F, 0x0131]),
(u"IJ", [0x0132]), ("IJ", [0x0132]),
(u"ij", [0x0133]), ("ij", [0x0133]),
(u"J", [0x0134]), ("J", [0x0134]),
(u"j", [0x0135]), ("j", [0x0135]),
(u"K", [0x0136]), ("K", [0x0136]),
(u"k", [0x0137,0x0138]), ("k", [0x0137, 0x0138]),
(u"L", [0x0139,0x013B,0x013D,0x013F,0x0141]), ("L", [0x0139, 0x013B, 0x013D, 0x013F, 0x0141]),
(u"l", [0x013A,0x013C,0x013E,0x0140,0x0142]), ("l", [0x013A, 0x013C, 0x013E, 0x0140, 0x0142]),
(u"N", [0x00D1,0x0143,0x0145,0x0147,0x014A]), ("N", [0x00D1, 0x0143, 0x0145, 0x0147, 0x014A]),
(u"n", [0x00F1,0x0144,0x0146,0x0148,0x0149,0x014B]), ("n", [0x00F1, 0x0144, 0x0146, 0x0148, 0x0149, 0x014B]),
(u"O", [0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D8,0x014C,0x014E,0x0150]), ("O", [0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8, 0x014C, 0x014E, 0x0150]),
(u"o", [0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F8,0x014D,0x014F,0x0151]), ("o", [0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x014D, 0x014F, 0x0151]),
(u"OE", [0x0152]), ("OE", [0x0152]),
(u"oe", [0x0153]), ("oe", [0x0153]),
(u"R", [0x0154,0x0156,0x0158]), ("R", [0x0154, 0x0156, 0x0158]),
(u"r", [0x0155,0x0157,0x0159]), ("r", [0x0155, 0x0157, 0x0159]),
(u"S", [0x015A,0x015C,0x015E,0x0160]), ("S", [0x015A, 0x015C, 0x015E, 0x0160]),
(u"s", [0x015B,0x015D,0x015F,0x01610,0x017F]), ("s", [0x015B, 0x015D, 0x015F, 0x01610, 0x017F]),
(u"T", [0x0162,0x0164,0x0166]), ("T", [0x0162, 0x0164, 0x0166]),
(u"t", [0x0163,0x0165,0x0167]), ("t", [0x0163, 0x0165, 0x0167]),
(u"U", [0x00D9,0x00DA,0x00DB,0x00DC,0x0168,0x016A,0x016C,0x016E,0x0170,0x172]), (
(u"u", [0x00F9,0x00FA,0x00FB,0x00FC,0x0169,0x016B,0x016D,0x016F,0x0171]), "U",
(u"W", [0x0174]), [
(u"w", [0x0175]), 0x00D9,
(u"Y", [0x00DD,0x0176,0x0178]), 0x00DA,
(u"y", [0x00FD,0x00FF,0x0177]), 0x00DB,
(u"Z", [0x0179,0x017B,0x017D]), 0x00DC,
(u"z", [0x017A,0x017C,0x017E]), 0x0168,
(u"2", [0x00B2]), # deux exposant 0x016A,
(u" ", [0x00A0]), # &nbsp 0x016C,
(u"", [0xB0]), # degre 0x016E,
(u"", [0xA9]), # copyright 0x0170,
(u"1/2", [0xBD]), # 1/2 0x172,
] ],
),
("u", [0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x016D, 0x016F, 0x0171]),
("W", [0x0174]),
("w", [0x0175]),
("Y", [0x00DD, 0x0176, 0x0178]),
("y", [0x00FD, 0x00FF, 0x0177]),
("Z", [0x0179, 0x017B, 0x017D]),
("z", [0x017A, 0x017C, 0x017E]),
("2", [0x00B2]), # deux exposant
(" ", [0x00A0]), # &nbsp
("", [0xB0]), # degre
("", [0xA9]), # copyright
("1/2", [0xBD]), # 1/2
]
global _reptable global _reptable
for repchar,codes in _corresp : for repchar, codes in _corresp:
for code in codes : for code in codes:
_reptable[code] = repchar _reptable[code] = repchar
_fill_reptable() _fill_reptable()
def suppression_diacritics(s) :
def suppression_diacritics(s):
"""Suppression des accents et autres marques. """Suppression des accents et autres marques.
@param s: le texte à nettoyer. @param s: le texte à nettoyer.
@ -73,6 +92,6 @@ def suppression_diacritics(s) :
@return: le texte nettoyé de ses marques diacritiques. @return: le texte nettoyé de ses marques diacritiques.
@rtype: unicode @rtype: unicode
""" """
if isinstance(s,str) : if isinstance(s, str):
s = unicode(s,"utf8","replace") s = unicode(s, "utf8", "replace")
return s.translate(_reptable) return s.translate(_reptable)

View File

@ -20,112 +20,100 @@ Utilisation :
import requests import requests
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields from tests.api.tools_test_api import verify_fields, DEPARTEMENT_FIELDS
def test_departements(api_headers): def test_departements(api_headers):
""" "
Routes: /departements_ids, /departement, /departement/<string:dept>/formsemestres_ids
""" """
Test 'departements' # --- Liste des ids
Route :
- /departements
"""
fields = [
"id",
"acronym",
"description",
"visible",
"date_creation",
]
r = requests.get( r = requests.get(
API_URL + "/departements", API_URL + "/departements_ids",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
assert r.status_code == 200 assert r.status_code == 200
assert len(r.json()) == 1 departements_ids = r.json()
assert isinstance(departements_ids, list)
assert len(departements_ids) > 0
assert all(isinstance(x, int) for x in departements_ids)
dept = r.json()[0] dept_id = departements_ids[0]
# --- Infos sur un département, accès par id
r = requests.get(
f"{API_URL}/departement/{dept_id}",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
dept_a = r.json()
assert verify_fields(dept_a, DEPARTEMENT_FIELDS) is True
# --- Infos sur un département, accès par acronyme4
r = requests.get(
f"{API_URL}/departement/{dept_a['acronym']}",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
dept_b = r.json()
assert dept_a == dept_b
fields_OK = verify_fields(dept, fields) # Liste des formsemestres
r = requests.get(
assert fields_OK is True f"{API_URL}/departement/{dept_a['acronym']}/formsemestres_ids",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
dept_ids = r.json()
assert isinstance(dept_ids, list)
assert all(isinstance(x, int) for x in dept_ids)
assert len(dept_ids) > 0
assert dept_id in dept_ids
def test_list_etudiants(api_headers): def test_list_etudiants(api_headers):
""" fields = {"id", "nip", "ine", "nom", "nom_usuel", "prenom", "civilite"}
Test 'list_etudiants'
Routes :
- /departements/<string:dept>/etudiants/list
- /departements/<string:dept>/etudiants/list/<int:formsemestre_id>
"""
fields = {
"civilite",
"code_ine",
"code_nip",
"date_naissance",
"email",
"emailperso",
"etudid",
"nom",
"prenom",
"nomprenom",
"lieu_naissance",
"dept_naissance",
"nationalite",
"boursier",
"id",
"codepostaldomicile",
"paysdomicile",
"telephonemobile",
"typeadresse",
"domicile",
"villedomicile",
"telephone",
"fax",
"description",
}
r = requests.get( r = requests.get(
API_URL + "/departements/TAPI/etudiants/list", API_URL + "/departement/TAPI/etudiants",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
etu = r.json()[0]
fields_OK = verify_fields(etu, fields)
assert r.status_code == 200 assert r.status_code == 200
assert len(r.json()) == 16 etud = r.json()[0]
assert fields_OK is True assert verify_fields(etud, fields) is True
assert isinstance(etud["id"], int)
r = requests.get( # Vérification que chaque id, nip et ine sont uniques (EN CHANTIER)
API_URL + "/departements/TAPI/etudiants/list/1", # all_uniques = True
headers=api_headers, # d = dict()
verify=CHECK_CERTIFICATE, # i = 0
) #
# for etu in r.json():
etu = r.json()[0] # d[i] = [etu["id"], etu["nip"], etu["ine"]]
# i += 1
fields_OK = verify_fields(etu, fields) #
# d[4][2] = 65
assert r.status_code == 200 #
assert len(r.json()) == 16 # for i in range(len(d)-1):
assert fields_OK is True # if d[i][0] == d[i+1][0]:
# all_uniques = False
# else:
# if d[i][1] == d[i+1][1]:
# all_uniques = False
# else:
# if d[i][2] == d[i+1][2]:
# all_uniques = False
# i += 1
#
# assert all_uniques is True
# liste_semestres_courant # liste_semestres_courant
def test_semestres_courant(api_headers): def test_semestres_courant(api_headers):
"""
Test 'liste_semestres_courant'
Route :
- /departements/<string:dept>/semestres_courants
"""
fields = [ fields = [
"titre", "titre",
"gestion_semestrielle", "gestion_semestrielle",
@ -149,22 +137,39 @@ def test_semestres_courant(api_headers):
"block_moyennes", "block_moyennes",
"formsemestre_id", "formsemestre_id",
"titre_num", "titre_num",
"titre_formation",
"date_debut_iso", "date_debut_iso",
"date_fin_iso", "date_fin_iso",
"responsables", "responsables",
"titre_court",
] ]
dept_id = 1
r = requests.get( r = requests.get(
API_URL + "/departements/TAPI/semestres_courants", f"{API_URL}/departement/{dept_id}",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
sem = r.json()[0]
fields_OK = verify_fields(sem, fields)
assert r.status_code == 200 assert r.status_code == 200
assert len(r.json()) == 1 dept = r.json()
assert fields_OK is True assert dept["id"] == dept_id
# Accès via acronyme
r = requests.get(
f"{API_URL}/departement/{dept['acronym']}/formsemestres_courants",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
result_a = r.json()
assert isinstance(result_a, list) # liste de formsemestres
assert len(result_a) > 0
sem = result_a[0]
assert verify_fields(sem, fields) is True
# accès via dept_id
r = requests.get(
f"{API_URL}/departement/{dept['id']}/formsemestres_courants",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
result_b = r.json()
assert result_a == result_b

View File

@ -16,30 +16,19 @@ Utilisation :
Lancer : Lancer :
pytest tests/api/test_api_etudiants.py pytest tests/api/test_api_etudiants.py
""" """
from random import randint
import requests import requests
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields from tests.api.tools_test_api import verify_fields
from tests.api.tools_test_api import ETUD_FIELDS, FSEM_FIELDS
# etudiants_courant
def test_etudiants_courant(api_headers): def test_etudiants_courant(api_headers):
""" """
Test 'etudiants_courant' Route: /etudiants/courant
Routes :
- /etudiants/courant
- /etudiants/courant/long
""" """
fields = [ fields = {"id", "nip", "nom", "prenom", "civilite"}
"id",
"nip",
"nom",
"nom_usuel",
"prenom",
"civilite",
]
r = requests.get( r = requests.get(
API_URL + "/etudiants/courant", API_URL + "/etudiants/courant",
@ -48,43 +37,26 @@ def test_etudiants_courant(api_headers):
) )
assert r.status_code == 200 assert r.status_code == 200
etudiants = r.json() etudiants = r.json()
assert len(etudiants) == 16 # XXX HARDCODED assert len(etudiants) > 0
etud = etudiants[-1] etud = etudiants[-1]
assert verify_fields(etud, fields) is True
assert isinstance(etud["id"], int)
assert isinstance(etud["nip"], str)
assert isinstance(etud["nom"], str)
assert isinstance(etud["prenom"], str)
assert isinstance(etud["civilite"], str)
fields_ok = verify_fields(etud, fields) all_unique = True
list_ids = [etu["id"] for etu in etudiants]
assert fields_ok is True for i in range(len(etudiants) - 1):
if etudiants.count(list_ids[i]) > 1:
all_unique = False
assert all_unique is True
########## Version long ################ ########## Version long ################
fields_long = [
"civilite",
"code_ine",
"code_nip",
"date_naissance",
"email",
"emailperso",
"etudid",
"nom",
"prenom",
"nomprenom",
"lieu_naissance",
"dept_naissance",
"nationalite",
"boursier",
"id",
"codepostaldomicile",
"paysdomicile",
"telephonemobile",
"typeadresse",
"domicile",
"villedomicile",
"telephone",
"fax",
"description",
]
r = requests.get( r = requests.get(
API_URL + "/etudiants/courant/long", API_URL + "/etudiants/courant/long",
headers=api_headers, headers=api_headers,
@ -95,46 +67,13 @@ def test_etudiants_courant(api_headers):
assert len(etudiants) == 16 # HARDCODED assert len(etudiants) == 16 # HARDCODED
etud = etudiants[-1] etud = etudiants[-1]
fields_ok = verify_fields(etud, fields_long) assert verify_fields(etud, ETUD_FIELDS) is True
assert fields_ok is True
def test_etudiant(api_headers): def test_etudiant(api_headers):
""" """
Test 'etudiant' Route:
Routes :
- /etudiant/etudid/<int:etudid>
- /etudiant/nip/<int:nip>
- /etudiant/ine/<int:ine>
""" """
fields = [
"civilite",
"code_ine",
"code_nip",
"date_naissance",
"email",
"emailperso",
"etudid",
"nom",
"prenom",
"nomprenom",
"lieu_naissance",
"dept_naissance",
"nationalite",
"boursier",
"id",
"domicile",
"villedomicile",
"telephone",
"fax",
"description",
"codepostaldomicile",
"paysdomicile",
"telephonemobile",
"typeadresse",
]
######### Test etudid ######### ######### Test etudid #########
r = requests.get( r = requests.get(
@ -144,10 +83,8 @@ def test_etudiant(api_headers):
) )
assert r.status_code == 200 assert r.status_code == 200
etud = r.json() etud = r.json()
assert len(etud) == 24 # ? HARDCODED
fields_ok = verify_fields(etud, fields) assert verify_fields(etud, ETUD_FIELDS) is True
assert fields_ok is True
######### Test code nip ######### ######### Test code nip #########
@ -158,8 +95,7 @@ def test_etudiant(api_headers):
) )
assert r.status_code == 200 assert r.status_code == 200
etud = r.json() etud = r.json()
assert len(etud) == 24 fields_ok = verify_fields(etud, ETUD_FIELDS)
fields_ok = verify_fields(etud, fields)
assert fields_ok is True assert fields_ok is True
######### Test code ine ######### ######### Test code ine #########
@ -172,47 +108,14 @@ def test_etudiant(api_headers):
assert r.status_code == 200 assert r.status_code == 200
etud = r.json() etud = r.json()
assert len(etud) == 24 assert len(etud) == 24
fields_ok = verify_fields(etud, fields) fields_ok = verify_fields(etud, ETUD_FIELDS)
assert fields_ok is True assert fields_ok is True
def test_etudiant_formsemestres(api_headers): def test_etudiant_formsemestres(api_headers):
""" """
Test 'etudiant_formsemestres' Route: /etudiant/etudid/<etudid:int>/formsemestres
Routes :
- /etudiant/etudid/<int:etudid>/formsemestres
- /etudiant/nip/<int:nip>/formsemestres
- /etudiant/ine/<int:ine>/formsemestres
""" """
fields = [
"date_fin",
"resp_can_edit",
"dept_id",
"etat",
"resp_can_change_ens",
"id",
"modalite",
"ens_can_edit_eval",
"formation_id",
"gestion_compensation",
"elt_sem_apo",
"semestre_id",
"bul_hide_xml",
"elt_annee_apo",
"titre",
"block_moyennes",
"scodoc7_id",
"date_debut",
"gestion_semestrielle",
"bul_bgcolor",
"formsemestre_id",
"titre_num",
"date_debut_iso",
"date_fin_iso",
"responsables",
"titre_court",
]
######### Test etudid ######### ######### Test etudid #########
@ -226,9 +129,7 @@ def test_etudiant_formsemestres(api_headers):
assert len(formsemestres) == 1 assert len(formsemestres) == 1
formsemestre = formsemestres[0] formsemestre = formsemestres[0]
assert verify_fields(formsemestre, FSEM_FIELDS) is True
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
######### Test code nip ######### ######### Test code nip #########
r = requests.get( r = requests.get(
@ -241,9 +142,7 @@ def test_etudiant_formsemestres(api_headers):
assert len(formsemestres) == 1 assert len(formsemestres) == 1
formsemestre = formsemestres[0] formsemestre = formsemestres[0]
assert verify_fields(formsemestre, FSEM_FIELDS) is True
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
######### Test code ine ######### ######### Test code ine #########
r = requests.get( r = requests.get(
@ -256,29 +155,13 @@ def test_etudiant_formsemestres(api_headers):
assert len(formsemestres) == 1 assert len(formsemestres) == 1
formsemestre = formsemestres[0] formsemestre = formsemestres[0]
assert verify_fields(formsemestre, FSEM_FIELDS) is True
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
def test_etudiant_bulletin_semestre(api_headers): def test_etudiant_bulletin_semestre(api_headers):
""" """
Test 'etudiant_bulletin_semestre' Route: /etudiant/etudid/<etudid>/formsemestre/<formsemestre_id>/bulletin
"""
Routes :
- /etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin
- /etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin
- /etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin
- /etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/pdf
- /etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/pdf
- /etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/pdf
- /etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short
- /etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/short
- /etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/short
- /etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf
- /etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf
- /etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf
"""
######### Test etudid ######### ######### Test etudid #########
r = requests.get( r = requests.get(
@ -311,15 +194,19 @@ def test_etudiant_bulletin_semestre(api_headers):
bul = r.json() bul = r.json()
assert len(bul) == 13 # HARDCODED assert len(bul) == 13 # HARDCODED
### --- Test étudiant inexistant
r = requests.get(
API_URL + "/etudiant/ine/189919919119191/formsemestre/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 404
def test_etudiant_groups(api_headers): def test_etudiant_groups(api_headers):
""" """
Test 'etudiant_groups' Route:
/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups
Routes :
- /etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups
- /etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/groups
- /etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/groups
""" """
fields = [ fields = [
"partition_id", "partition_id",

View File

@ -21,15 +21,12 @@ import requests
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields from tests.api.tools_test_api import verify_fields
from tests.api.tools_test_api import FORMATION_FIELDS, MODIMPL_FIELDS
# formations
def test_formations_ids(api_headers): def test_formations_ids(api_headers):
""" """
Test 'formations_ids' Route: /formations_ids
Routes :
- /formations_ids
""" """
r = requests.get( r = requests.get(
API_URL + "/formations_ids", API_URL + "/formations_ids",
@ -44,150 +41,67 @@ def test_formations_ids(api_headers):
assert all(isinstance(x, int) for x in formations_ids) assert all(isinstance(x, int) for x in formations_ids)
# formations_by_id
def test_formations_by_id(api_headers): def test_formations_by_id(api_headers):
""" """
Test 'formations_by_id' Route: /formation/<int:formation_id>
Routes :
- /formations/<int:formation_id>
""" """
fields = [
"id",
"acronyme",
"titre_officiel",
"formation_code",
"code_specialite",
"dept_id",
"titre",
"version",
"type_parcours",
"referentiel_competence_id",
"formation_id",
]
r = requests.get( r = requests.get(
API_URL + "/formations/1", API_URL + "/formation/1",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
assert r.status_code == 200 assert r.status_code == 200
formation = r.json() formation = r.json()
assert verify_fields(formation, FORMATION_FIELDS) is True
fields_ok = verify_fields(formation, fields)
assert fields_ok is True
# TODO tester le contenu de certains champs # TODO tester le contenu de certains champs
def test_formation_export(api_headers): def test_formation_export(api_headers):
""" """
Test 'formation_export_by_formation_id' Route: /formation/formation_export/<int:formation_id>
Routes :
- /formations/formation_export/<int:formation_id>
- /formations/formation_export/<int:formation_id>/with_ids
""" """
fields = [
"id",
"acronyme",
"titre_officiel",
"formation_code",
"code_specialite",
"dept_id",
"titre",
"version",
"type_parcours",
"referentiel_competence_id",
"formation_id",
"ue",
]
r = requests.get( r = requests.get(
API_URL + "/formations/formation_export/1", API_URL + "/formation/formation_export/1",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
assert r.status_code == 200 assert r.status_code == 200
export_formation = r.json() export_formation = r.json()
assert verify_fields(export_formation, FORMATION_FIELDS) is True
fields_ok = verify_fields(export_formation, fields)
assert fields_ok is True
# TODO tester le contenu de certains champs # TODO tester le contenu de certains champs
# TODO
# def test_formsemestre_apo(api_headers):
# r = requests.get(
# API_URL + "/formation/apo/<string:etape_apo>",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
def test_moduleimpl(api_headers): def test_moduleimpl(api_headers):
""" """
Test 'moduleimpl' Route: /formation/moduleimpl/<int:moduleimpl_id>
Route :
- /formations/moduleimpl/<int:moduleimpl_id>
""" """
fields = [
"id",
"formsemestre_id",
"computation_expr",
"module_id",
"responsable_id",
"moduleimpl_id",
"ens",
"module",
]
r = requests.get( r = requests.get(
API_URL + "/formations/moduleimpl/1", API_URL + "/formation/moduleimpl/1",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
assert r.status_code == 200 assert r.status_code == 200
moduleimpl = r.json() moduleimpl = r.json()
assert verify_fields(moduleimpl, MODIMPL_FIELDS) is True
fields_ok = verify_fields(moduleimpl, fields)
assert fields_ok is True
# TODO tester le contenu de certains champs # TODO tester le contenu de certains champs
def test_moduleimpls_sem(api_headers):
"""
Test 'moduleimpls_sem'
Route :
- /formations/moduleimpl/formsemestre/<int:formsemestre_id>/list
"""
fields = [
"id",
"formsemestre_id",
"computation_expr",
"module_id",
"responsable_id",
"moduleimpl_id",
"ens",
"module",
"moduleimpl_id",
"ens",
]
r = requests.get(
API_URL + "/formations/moduleimpl/formsemestre/1/list",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
moduleimpls = r.json()
moduleimpl = moduleimpls[0]
fields_ok = verify_fields(moduleimpl, fields)
assert len(moduleimpls) == 21 # XXX HARDCODED !
assert fields_ok is True
def test_referentiel_competences(api_headers): def test_referentiel_competences(api_headers):
""" """
Test 'referentiel_competences' Route: "/formation/<int:formation_id>/referentiel_competences",
Route :
- /formations/<int:formation_id>/referentiel_competences
""" """
r = requests.get( r = requests.get(
API_URL + "/formations/1/referentiel_competences", API_URL + "/formation/1/referentiel_competences",
headers=api_headers, headers=api_headers,
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )

View File

@ -18,17 +18,16 @@ Utilisation :
""" """
import requests import requests
from app.api.formsemestres import formsemestre
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields from tests.api.tools_test_api import MODIMPL_FIELDS, verify_fields
from tests.api.tools_test_api import FSEM_FIELDS, UE_FIELDS, MODULE_FIELDS
def test_formsemestre(api_headers): def test_formsemestre(api_headers):
""" """
Test 'formsemestre' Route: /formsemestre/<id>
Route :
- /formsemestre/<int:formsemestre_id>
""" """
r = requests.get( r = requests.get(
API_URL + "/formsemestre/1", API_URL + "/formsemestre/1",
@ -36,64 +35,48 @@ def test_formsemestre(api_headers):
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
assert r.status_code == 200 assert r.status_code == 200
formsemestre = r.json() formsemestre = r.json()
assert verify_fields(formsemestre, FSEM_FIELDS)
fields = [
"date_fin",
"resp_can_edit",
"dept_id",
"etat",
"resp_can_change_ens",
"id",
"modalite",
"ens_can_edit_eval",
"formation_id",
"gestion_compensation",
"elt_sem_apo",
"semestre_id",
"bul_hide_xml",
"elt_annee_apo",
"titre",
"block_moyennes",
"scodoc7_id",
"date_debut",
"gestion_semestrielle",
"bul_bgcolor",
"formsemestre_id",
"titre_num",
"date_debut_iso",
"date_fin_iso",
"responsables",
]
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
# TODO def test_etudiant_bulletin(api_headers):
# def test_formsemestre_apo(api_headers): """
# """ Route:
# Test 'formsemestre_apo' """
# formsemestre_id = 1
# Route : r = requests.get(
# - /formsemestre/apo/<string:etape_apo> f"{API_URL}/etudiant/etudid/1/formsemestre/{formsemestre_id}/bulletin",
# """ headers=api_headers,
# r = requests.get( verify=CHECK_CERTIFICATE,
# API_URL + "/formations/apo/<string:etape_apo>", )
# headers=api_headers, assert r.status_code == 200
# verify=CHECK_CERTIFICATE, bull_a = r.json()
# )
# assert r.status_code == 200 r = requests.get(
f"{API_URL}/etudiant/nip/1/formsemestre/{formsemestre_id}/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
bull_b = r.json()
r = requests.get(
f"{API_URL}/etudiant/ine/1/formsemestre/{formsemestre_id}/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
bull_c = r.json()
# elimine les dates de publication pour comparer les autres champs
del bull_a["date"]
del bull_b["date"]
del bull_c["date"]
assert bull_a == bull_b == bull_c
def test_bulletins(api_headers): def test_bulletins(api_headers):
""" """
Test 'bulletins' Route:
Route :
- /formsemestre/<int:formsemestre_id>/bulletins
""" """
r = requests.get( r = requests.get(
API_URL + "/formsemestre/1/bulletins", API_URL + "/formsemestre/1/bulletins",
@ -105,12 +88,6 @@ def test_bulletins(api_headers):
# # jury # # jury
# def test_jury(): # def test_jury():
# """
# Test 'jury'
#
# Route :
# - /formsemestre/<int:formsemestre_id>/jury
# """
# r = requests.get( # r = requests.get(
# API_URL + "/formsemestre/1/jury", # API_URL + "/formsemestre/1/jury",
# headers=api_headers, # headers=api_headers,
@ -118,70 +95,11 @@ def test_bulletins(api_headers):
# ) # )
# assert r.status_code == 200 # assert r.status_code == 200
# TODO A revoir
def test_programme(api_headers): def test_formsemestre_programme(api_headers):
""" """
Test 'programme' Route: /formsemestre/1/programme
Route :
- /formsemestre/<int:formsemestre_id>/programme
""" """
ue_fields = [
"semestre_idx",
"type",
"formation_id",
"ue_code",
"id",
"ects",
"acronyme",
"is_external",
"numero",
"code_apogee",
"titre",
"coefficient",
"color",
"ue_id",
]
ressource_fields = [
"heures_tp",
"code_apogee",
"titre",
"coefficient",
"module_type",
"id",
"ects",
"abbrev",
"ue_id",
"code",
"formation_id",
"heures_cours",
"matiere_id",
"heures_td",
"semestre_id",
"numero",
"module_id",
]
sae_fields = [
"heures_tp",
"code_apogee",
"titre",
"coefficient",
"module_type",
"id",
"ects",
"abbrev",
"ue_id",
"code",
"formation_id",
"heures_cours",
"matiere_id",
"heures_td",
"semestre_id",
"numero",
"module_id",
]
r = requests.get( r = requests.get(
API_URL + "/formsemestre/1/programme", API_URL + "/formsemestre/1/programme",
@ -189,16 +107,22 @@ def test_programme(api_headers):
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
assert r.status_code == 200 assert r.status_code == 200
assert len(r.json()) == 3 prog = r.json()
assert isinstance(prog, dict)
assert "ues" in prog
assert "modules" in prog
assert "ressources" in prog
assert "saes" in prog
assert isinstance(prog["ues"], list)
assert isinstance(prog["modules"], list)
ue = prog["ues"][0]
modules = prog["modules"]
# Il y a toujours au moins une SAE et une ressources dans notre base de test
ressource = prog["ressources"][0]
sae = prog["saes"][0]
ue = r.json()["ues"][0] assert verify_fields(ue, UE_FIELDS)
ressource = r.json()["ressources"][0] if len(modules) > 1:
sae = r.json()["saes"][0] assert verify_fields(modules[0], MODIMPL_FIELDS)
assert verify_fields(ressource, MODIMPL_FIELDS)
fields_ue_OK = verify_fields(ue, ue_fields) assert verify_fields(sae, MODIMPL_FIELDS)
fields_ressource_OK = verify_fields(ressource, ressource_fields)
fields_sae_OK = verify_fields(sae, sae_fields)
assert fields_ue_OK is True
assert fields_ressource_OK is True
assert fields_sae_OK is True

View File

@ -43,6 +43,8 @@ def test_permissions(api_headers):
# "date_debut": # "date_debut":
# "date_fin": # "date_fin":
"dept": "TAPI", "dept": "TAPI",
"dept_ident": "TAPI",
"dept_id": 1,
"etape_apo": "???", "etape_apo": "???",
"etat": "I", "etat": "I",
"evaluation_id": 1, "evaluation_id": 1,

View File

@ -2,16 +2,138 @@
""" """
def verify_fields(json_response: dict, fields: set) -> bool: def verify_fields(json_response: dict, expected_fields: set) -> bool:
""" """
Vérifie si les champs attendu de la réponse json sont présents Vérifie si les champs attendu de la réponse json sont présents
json_response : la réponse de la requête json_response : la réponse de la requête
fields : ensemble des champs à vérifier expected_fields : ensemble des champs à vérifier
Retourne True ou False Retourne True ou False
""" """
for field in json_response: return all(field in json_response for field in expected_fields)
if field not in fields:
return False
return True DEPARTEMENT_FIELDS = [
"id",
"acronym",
"description",
"visible",
"date_creation",
]
ETUD_FIELDS = {
"boursier",
"civilite",
"code_ine",
"code_nip",
"codepostaldomicile",
"date_naissance",
"dept_naissance",
"description",
"domicile",
"email",
"emailperso",
"etudid",
"id",
"lieu_naissance",
"nationalite",
"nom",
"nomprenom",
"paysdomicile",
"prenom",
"telephone",
"telephonemobile",
"typeadresse",
"villedomicile",
}
FORMATION_FIELDS = {
"id",
"acronyme",
"titre_officiel",
"formation_code",
"code_specialite",
"dept_id",
"titre",
"version",
"type_parcours",
"referentiel_competence_id",
"formation_id",
}
FSEM_FIELDS = {
"block_moyennes",
"bul_bgcolor",
"bul_hide_xml",
"date_debut_iso",
"date_debut",
"date_fin_iso",
"date_fin",
"dept_id",
"elt_annee_apo",
"elt_sem_apo",
"ens_can_edit_eval",
"etat",
"formation_id",
"formsemestre_id",
"gestion_compensation",
"gestion_semestrielle",
"id",
"modalite",
"resp_can_change_ens",
"resp_can_edit",
"responsables",
"semestre_id",
"titre_formation",
"titre_num",
"titre",
}
MODIMPL_FIELDS = {
"id",
"formsemestre_id",
"computation_expr",
"module_id",
"responsable_id",
"moduleimpl_id",
"ens",
"module",
}
MODULE_FIELDS = {
"heures_tp",
"code_apogee",
"titre",
"coefficient",
"module_type",
"id",
"ects",
"abbrev",
"ue_id",
"code",
"formation_id",
"heures_cours",
"matiere_id",
"heures_td",
"semestre_id",
"numero",
"module_id",
}
UE_FIELDS = {
"semestre_idx",
"type",
"formation_id",
"ue_code",
"id",
"ects",
"acronyme",
"is_external",
"numero",
"code_apogee",
"titre",
"coefficient",
"color",
"ue_id",
}

View File

@ -138,4 +138,4 @@ def test_export_xml(test_client):
</row> </row>
</table> </table>
""" """
assert xmls_compare(table_xml, expected_result) assert xmls_compare(table_xml, expected_result)