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.errors import error_response
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 sco_abs
@ -50,12 +50,11 @@ def absences(etudid: int = None, nip: int = None, ine: int = None):
"""
if etudid is None:
# 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(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
404,
message="id de l'étudiant (etudid, nip, ine) inconnu",
)
etudid = etud.etudid
@ -103,16 +102,13 @@ def absences_just(etudid: int = None, nip: int = None, ine: int = None):
]
"""
if etudid is None:
# Récupération de l'étudiant
try:
etu = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
etudid = etu.etudid
except AttributeError:
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
if etud is None:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
404,
message="id de l'étudiant (etudid, nip, ine) inconnu",
)
etudid = etud.etudid
# Récupération des absences justifiées de l'étudiant
abs_just = [

View File

@ -1,57 +1,66 @@
############################################### Departements ##########################################################
import json
from flask import jsonify
import app
from app import models
from app.api import bp
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
@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_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 :
[
{
"id": 1,
"acronym": "TAPI",
"description": null,
"visible": true,
"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
depts = models.Departement.query.all()
# Mise en place de la liste avec tous les départements
data = [d.to_dict() for d in depts]
return jsonify(data)
dept = get_departement(dept_ident)
return jsonify(dept.to_dict())
@bp.route("/departements/<string:dept>/etudiants/list", methods=["GET"])
@bp.route(
"/departements/<string:dept>/etudiants/list/<int:formsemestre_id>", methods=["GET"]
)
@bp.route("/departements", methods=["GET"])
@token_auth.login_required
@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
@ -61,54 +70,39 @@ def list_etudiants(dept: str, formsemestre_id=None):
Exemple de résultat :
[
{
"civilite": "X",
"code_ine": null,
"code_nip": null,
"civilite": "M",
"ine": "7899X61616",
"nip": "F6777H88",
"date_naissance": null,
"email": null,
"email": "toto@toto.fr",
"emailperso": null,
"etudid": 18,
"nom": "MOREL",
"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é
if formsemestre_id is not None:
# 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
# Le département, spécifié par un id ou un acronyme
dept = get_departement(dept_ident)
# Si le formsemestre_id n'a pas été renseigné
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)
return jsonify([etud.to_dict_short() for etud in dept.etudiants])
@bp.route("/departements/<string:dept>/semestres_courants", methods=["GET"])
@bp.route("/departement/<string:dept_ident>/formsemestres_ids", methods=["GET"])
@token_auth.login_required
@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é
@ -117,11 +111,16 @@ def liste_semestres_courant(dept: str):
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,
"dept_id": 1,
"etat": true,
"resp_can_change_ens": true,
"resp_can_change_ens": false,
"id": 1,
"modalite": "FI",
"ens_can_edit_eval": false,
@ -131,32 +130,27 @@ def liste_semestres_courant(dept: str):
"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",
"titre_num": "master machine info semestre 1",
"date_debut_iso": "2021-09-01",
"date_fin_iso": "2022-08-31",
"date_fin_iso": "2022-12-15",
"responsables": [
12,
42
],
"titre_court": "BUT MMI"
3,
2
]
},
...
]
"""
# Récupération des départements comportant l'acronym mit en paramètre
dept = models.Departement.query.filter_by(acronym=dept).first_or_404()
# Le département, spécifié par un id ou un acronyme
dept = get_departement(dept_ident)
# Récupération des semestres suivant id_dept
semestres = models.FormSemestre.query.filter_by(dept_id=dept.id, etat=True)
# Les semestres en cours de ce département
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
data = [d.to_dict_api() for d in semestres]
return jsonify(data)
return jsonify([d.to_dict() for d in formsemestres])

View File

@ -7,12 +7,10 @@ from app import models
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.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.scodoc import sco_bulletins
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
@ -22,7 +20,7 @@ from app.scodoc.sco_permissions import Permission
@token_permission_required(Permission.APIView)
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 :
[
@ -43,7 +41,6 @@ def etudiants_courant(long=False):
...
]
"""
# Récupération de tous les étudiants
etuds = Identite.query.filter(
Identite.id == FormSemestreInscription.etudid,
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
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
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 :
[
{
"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"
},
...
{
"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": []
},
...
]
"""
# 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(
models.FormSemestreInscription.etudid == etud.id,
models.FormSemestreInscription.formsemestre_id == models.FormSemestre.id,
).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(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "format": "json"},
defaults={"version": "long"},
)
@bp.route(
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "format": "json"},
defaults={"version": "long"},
)
@bp.route(
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin",
methods=["GET"],
defaults={"version": "long", "format": "json"},
)
@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"},
defaults={"version": "long"},
)
@bp.route(
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "format": "json"},
defaults={"version": "short"},
)
@bp.route(
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "format": "json"},
defaults={"version": "short"},
)
@bp.route(
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
methods=["GET"],
defaults={"version": "short", "format": "json"},
)
@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"},
defaults={"version": "short"},
)
@token_auth.login_required
@token_permission_required(Permission.APIView)
@ -235,7 +207,6 @@ def etudiant_bulletin_semestre(
nip: int = None,
ine: int = None,
version="long",
format="json",
):
"""
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)
# Récupération de l'étudiant
try:
etu = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
except AttributeError:
etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
if etud is None:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
404,
message="id de l'étudiant (etudid, nip, ine) inconnu",
)
if format == "json":
return sco_bulletins.get_formsemestre_bulletin_etud_json(
formsemestre, etu, version
)
else:
etudid = etu.id
print(etudid)
return do_formsemestre_bulletinetud(formsemestre, etudid, version, format)
return sco_bulletins.get_formsemestre_bulletin_etud_json(
formsemestre, etud, version
)
@bp.route(
@ -490,12 +453,11 @@ def etudiant_groups(
]
"""
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:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
404,
message="id de l'étudiant (etudid, nip, ine) inconnu",
)
etudid = etud.etudid

View File

@ -99,7 +99,7 @@ def evaluation_notes(evaluation_id: int):
data = do_evaluation_get_all_notes(evaluation_id)
except AttributeError: # ???
return error_response(
409,
404,
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)
@bp.route("/formations/<int:formation_id>", methods=["GET"])
@bp.route("/formation/<int:formation_id>", methods=["GET"])
@token_auth.login_required
@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é
@ -63,12 +63,12 @@ def formations_by_id(formation_id: int):
@bp.route(
"/formations/formation_export/<int:formation_id>",
"/formation/formation_export/<int:formation_id>",
methods=["GET"],
defaults={"export_ids": False},
)
@bp.route(
"/formations/formation_export/<int:formation_id>/with_ids",
"/formation/formation_export/<int:formation_id>/with_ids",
methods=["GET"],
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
data = sco_formations.formation_export(formation_id, export_ids)
except ValueError:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel. \n"
"Veillez vérifier la conformité du 'formation_id'",
)
return error_response(500, message="Erreur inconnue")
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_permission_required(Permission.APIView)
def moduleimpl(moduleimpl_id: int):
@ -199,7 +195,6 @@ def moduleimpl(moduleimpl_id: int):
{
"id": 1,
"formsemestre_id": 1,
"computation_expr": null,
"module_id": 1,
"responsable_id": 2,
"moduleimpl_id": 1,
@ -231,63 +226,7 @@ def moduleimpl(moduleimpl_id: int):
@bp.route(
"/formations/moduleimpl/formsemestre/<int:formsemestre_id>/list",
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",
"/formation/<int:formation_id>/referentiel_competences",
methods=["GET"],
)
@token_auth.login_required

View File

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

View File

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

View File

@ -1,15 +1,17 @@
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
nip : None ou un int code_nip
ine : None ou un int code_ine
Exemple de résultat: <Itendite>
Return None si étudiant inexistant.
"""
if etudid is None:
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):
"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
moy_ue = ue.get("moyenne")
t = {
@ -206,7 +209,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
for mod_code, mod in ue["modules"].items():
rows.append(
{
"titre": f"{mod_code} {mod['titre']}",
"titre": f"{mod_code or ''} {mod['titre'] or ''}",
}
)
self.evaluations_rows(rows, mod["evaluations"])
@ -313,7 +316,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
"lignes des évaluations"
for e in evaluations:
t = {
"titre": f"{e['description']}",
"titre": f"{e['description'] or ''}",
"moyenne": e["note"]["value"],
"_moyenne_pdf": Paragraph(
f"""<para align=right>{e["note"]["value"]}</para>"""

View File

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

View File

@ -178,11 +178,12 @@ def evaluation_enrich_dict(e):
else:
e["descrheure"] = ""
# 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
else:
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
else:
e["apresmidi"] = 0

View File

@ -139,6 +139,7 @@ class FormSemestre(db.Model):
else:
d["date_fin"] = d["date_fin_iso"] = ""
d["responsables"] = [u.id for u in self.responsables]
d["titre_formation"] = self.titre_formation()
return d
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)
"""
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:
imputation_dept = sco_preferences.get_preference("DeptName")
imputation_dept = prefs["DeptName"]
imputation_dept = imputation_dept.upper()
parcours_name = self.formation.get_parcours().NAME
modalite = self.modalite
@ -368,7 +370,7 @@ class FormSemestre(db.Model):
scu.annee_scolaire_debut(self.date_debut.year, self.date_debut.month)
)
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:
@ -380,6 +382,12 @@ class FormSemestre(db.Model):
titre_annee += "-" + str(self.date_fin.year)
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:
"""Le titre et les dates du semestre, pour affichage dans des listes
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."""
self.SemTagDict = {fid: SemTagDict[fid] for fid in self.get_Fids_in_settag()}
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):
@ -243,7 +243,7 @@ class SetTagInterClasse(pe_tagtable.TableTag):
fid: SetTagDict[fid] for fid in self.get_Fids_in_settag() if fid != None
}
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):

View File

@ -965,7 +965,7 @@ def _tables_abs_etud(
)[0]
if format == "html":
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"])}
">{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(
"bul_show_minmax_mod", formsemestre_id
):
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
scu.fmt_note(mod["stats"]["max"]),
rang_minmax = (
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
% (
mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
scu.fmt_note(mod["stats"]["max"]),
)
)
else:
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:
H.append(
f"""<hr>
<p><a class="stdlink" href="{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept, showsemtable=1)
}">Voir tous les semestres ({len(othersems)} verrouillés)</a>
<p><a class="stdlink" href="{url_for('scolar.index_html',
scodoc_dept=g.scodoc_dept, showsemtable=1)
}">Voir table des semestres (dont {len(othersems)}
verrouillé{'s' if len(othersems) else ''})</a>
</p>"""
)

View File

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

View File

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

View File

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

View File

@ -132,9 +132,12 @@ def clear_base_preferences():
g._SCO_BASE_PREFERENCES = {} # { dept_id: BasePreferences instance }
def get_base_preferences():
"""Return global preferences for the current department"""
dept_id = g.scodoc_dept_id
def get_base_preferences(dept_id: int = None):
"""Return global preferences for the specified department
or the current departement
"""
if dept_id is None:
dept_id = g.scodoc_dept_id
if not hasattr(g, "_SCO_BASE_PREFERENCES"):
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]
def get_preference(name, formsemestre_id=None):
def get_preference(name, formsemestre_id=None, dept_id=None):
"""Returns value of named preference.
All preferences have a sensible default value, so this
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):
@ -2145,9 +2148,9 @@ class BasePreferences(object):
class SemPreferences:
"""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.base_prefs = get_base_preferences()
self.base_prefs = get_base_preferences(dept_id=dept_id)
def __getitem__(self, 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})
if not evals:
raise ScoValueError("invalid evaluation_id")
E = evals[0]
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
eval_dict = evals[0]
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=eval_dict["moduleimpl_id"])[0]
formsemestre_id = M["formsemestre_id"]
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
mod_responsable = sco_users.user_info(M["responsable_id"])
if E["jour"]:
indication_date = ndb.DateDMYtoISO(E["jour"])
if eval_dict["jour"]:
indication_date = ndb.DateDMYtoISO(eval_dict["jour"])
else:
indication_date = scu.sanitize_filename(E["description"])[:12]
evalname = "%s-%s" % (Mod["code"], indication_date)
indication_date = scu.sanitize_filename(eval_dict["description"])[:12]
eval_name = "%s-%s" % (Mod["code"], indication_date)
if E["description"]:
evaltitre = "%s du %s" % (E["description"], E["jour"])
if eval_dict["description"]:
evaltitre = "%s du %s" % (eval_dict["description"], eval_dict["jour"])
else:
evaltitre = "évaluation du %s" % E["jour"]
evaltitre = "évaluation du %s" % eval_dict["jour"]
description = "%s en %s (%s) resp. %s" % (
evaltitre,
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
L = []
etuds = _get_sorted_etuds(E, etudids, formsemestre_id)
etuds = _get_sorted_etuds(eval_dict, etudids, formsemestre_id)
for e in etuds:
etudid = e["etudid"]
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)
xls = sco_excel.excel_feuille_saisie(E, sem["titreannee"], description, lines=L)
filename = "notes_%s_%s" % (eval_name, gr_title_filename)
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 sco_excel.send_excel_file(xls, filename)
@ -1008,10 +1010,9 @@ def saisie_notes(evaluation_id, group_ids=[]):
return "\n".join(H)
def _get_sorted_etuds(E, etudids, formsemestre_id):
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
def _get_sorted_etuds(eval_dict: dict, etudids: list, formsemestre_id: int):
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(
E["evaluation_id"]
eval_dict["evaluation_id"]
) # Notes existantes
cnx = ndb.GetDBConnexion()
etuds = []
@ -1028,9 +1029,9 @@ def _get_sorted_etuds(E, etudids, formsemestre_id):
e["groups"] = sco_groups.get_etud_groups(etudid, formsemestre_id)
# 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 = []
if E["matin"]:
if eval_dict["matin"]:
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)
if nbabs:
@ -1038,7 +1039,7 @@ def _get_sorted_etuds(E, etudids, formsemestre_id):
warn_abs_lst.append("absent justifié le matin !")
else:
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)
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
if nbabs:

View File

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

View File

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

View File

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

View File

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

View File

@ -10,19 +10,24 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '669065fb2d20'
down_revision = 'a217bf588f4c'
revision = "669065fb2d20"
down_revision = "a217bf588f4c"
branch_labels = None
depends_on = None
def upgrade():
# ### 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 ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('notes_formsemestre', 'block_moyennes')
op.drop_column("notes_formsemestre", "block_moyennes")
# ### end Alembic commands ###

View File

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

View File

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

View File

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

View File

@ -10,46 +10,77 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '92789d50f6b6'
down_revision = '00ad500fb118'
revision = "92789d50f6b6"
down_revision = "00ad500fb118"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('modules_acs')
op.drop_table('app_crit')
op.add_column('apc_annee_parcours', sa.Column('ordre', sa.Integer(), nullable=True))
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_unique_constraint('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))
op.drop_table("modules_acs")
op.drop_table("app_crit")
op.add_column("apc_annee_parcours", sa.Column("ordre", sa.Integer(), nullable=True))
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_unique_constraint(
"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 ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('apc_referentiel_competences', 'scodoc_orig_filename')
op.drop_column('apc_referentiel_competences', 'scodoc_date_loaded')
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_index(op.f('ix_apc_app_critique_code'), table_name='apc_app_critique')
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.drop_column("apc_referentiel_competences", "scodoc_orig_filename")
op.drop_column("apc_referentiel_competences", "scodoc_date_loaded")
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.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')
op.drop_index(op.f("ix_apc_app_critique_code"), table_name="apc_app_critique")
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",
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 ###

View File

@ -10,27 +10,50 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'a217bf588f4c'
down_revision = 'f73251d1d825'
revision = "a217bf588f4c"
down_revision = "f73251d1d825"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('notes_semset_formsemestre', 'semset_id',
existing_type=sa.INTEGER(),
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')
op.alter_column(
"notes_semset_formsemestre",
"semset_id",
existing_type=sa.INTEGER(),
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 ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
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.alter_column('notes_semset_formsemestre', 'semset_id',
existing_type=sa.INTEGER(),
nullable=True)
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.alter_column(
"notes_semset_formsemestre",
"semset_id",
existing_type=sa.INTEGER(),
nullable=True,
)
# ### end Alembic commands ###

View File

@ -10,21 +10,23 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'c8efc54586d8'
down_revision = '6cfc21a7ae1b'
revision = "c8efc54586d8"
down_revision = "6cfc21a7ae1b"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
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.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
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_notes_ue_semestre_idx'), table_name='notes_ue')
op.drop_column('notes_ue', 'semestre_idx')
op.drop_index(op.f("ix_notes_ue_semestre_idx"), table_name="notes_ue")
op.drop_column("notes_ue", "semestre_idx")
# ### end Alembic commands ###

View File

@ -10,23 +10,25 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'd3d92b2d0092'
down_revision = '017e32eb4773'
revision = "d3d92b2d0092"
down_revision = "017e32eb4773"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
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_foreign_key(None, 'itemsuivi_tags', 'departement', ['dept_id'], ['id'])
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_foreign_key(None, "itemsuivi_tags", "departement", ["dept_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'itemsuivi_tags', type_='foreignkey')
op.drop_index(op.f('ix_itemsuivi_tags_dept_id'), table_name='itemsuivi_tags')
op.drop_column('itemsuivi_tags', 'dept_id')
op.drop_constraint(None, "itemsuivi_tags", type_="foreignkey")
op.drop_index(op.f("ix_itemsuivi_tags_dept_id"), table_name="itemsuivi_tags")
op.drop_column("itemsuivi_tags", "dept_id")
# ### end Alembic commands ###

View File

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

View File

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

View File

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

View File

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

View File

@ -20,112 +20,100 @@ Utilisation :
import requests
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):
""" "
Routes: /departements_ids, /departement, /departement/<string:dept>/formsemestres_ids
"""
Test 'departements'
Route :
- /departements
"""
fields = [
"id",
"acronym",
"description",
"visible",
"date_creation",
]
# --- Liste des ids
r = requests.get(
API_URL + "/departements",
API_URL + "/departements_ids",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
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)
assert fields_OK is True
# Liste des formsemestres
r = requests.get(
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):
"""
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",
}
fields = {"id", "nip", "ine", "nom", "nom_usuel", "prenom", "civilite"}
r = requests.get(
API_URL + "/departements/TAPI/etudiants/list",
API_URL + "/departement/TAPI/etudiants",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
etu = r.json()[0]
fields_OK = verify_fields(etu, fields)
assert r.status_code == 200
assert len(r.json()) == 16
assert fields_OK is True
etud = r.json()[0]
assert verify_fields(etud, fields) is True
assert isinstance(etud["id"], int)
r = requests.get(
API_URL + "/departements/TAPI/etudiants/list/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
etu = r.json()[0]
fields_OK = verify_fields(etu, fields)
assert r.status_code == 200
assert len(r.json()) == 16
assert fields_OK is True
# Vérification que chaque id, nip et ine sont uniques (EN CHANTIER)
# all_uniques = True
# d = dict()
# i = 0
#
# for etu in r.json():
# d[i] = [etu["id"], etu["nip"], etu["ine"]]
# i += 1
#
# d[4][2] = 65
#
# for i in range(len(d)-1):
# 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
def test_semestres_courant(api_headers):
"""
Test 'liste_semestres_courant'
Route :
- /departements/<string:dept>/semestres_courants
"""
fields = [
"titre",
"gestion_semestrielle",
@ -149,22 +137,39 @@ def test_semestres_courant(api_headers):
"block_moyennes",
"formsemestre_id",
"titre_num",
"titre_formation",
"date_debut_iso",
"date_fin_iso",
"responsables",
"titre_court",
]
dept_id = 1
r = requests.get(
API_URL + "/departements/TAPI/semestres_courants",
f"{API_URL}/departement/{dept_id}",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
sem = r.json()[0]
fields_OK = verify_fields(sem, fields)
assert r.status_code == 200
assert len(r.json()) == 1
assert fields_OK is True
dept = r.json()
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 :
pytest tests/api/test_api_etudiants.py
"""
from random import randint
import requests
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 ETUD_FIELDS, FSEM_FIELDS
# etudiants_courant
def test_etudiants_courant(api_headers):
"""
Test 'etudiants_courant'
Routes :
- /etudiants/courant
- /etudiants/courant/long
Route: /etudiants/courant
"""
fields = [
"id",
"nip",
"nom",
"nom_usuel",
"prenom",
"civilite",
]
fields = {"id", "nip", "nom", "prenom", "civilite"}
r = requests.get(
API_URL + "/etudiants/courant",
@ -48,43 +37,26 @@ def test_etudiants_courant(api_headers):
)
assert r.status_code == 200
etudiants = r.json()
assert len(etudiants) == 16 # XXX HARDCODED
assert len(etudiants) > 0
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 ################
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(
API_URL + "/etudiants/courant/long",
headers=api_headers,
@ -95,46 +67,13 @@ def test_etudiants_courant(api_headers):
assert len(etudiants) == 16 # HARDCODED
etud = etudiants[-1]
fields_ok = verify_fields(etud, fields_long)
assert fields_ok is True
assert verify_fields(etud, ETUD_FIELDS) is True
def test_etudiant(api_headers):
"""
Test 'etudiant'
Routes :
- /etudiant/etudid/<int:etudid>
- /etudiant/nip/<int:nip>
- /etudiant/ine/<int:ine>
Route:
"""
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 #########
r = requests.get(
@ -144,10 +83,8 @@ def test_etudiant(api_headers):
)
assert r.status_code == 200
etud = r.json()
assert len(etud) == 24 # ? HARDCODED
fields_ok = verify_fields(etud, fields)
assert fields_ok is True
assert verify_fields(etud, ETUD_FIELDS) is True
######### Test code nip #########
@ -158,8 +95,7 @@ def test_etudiant(api_headers):
)
assert r.status_code == 200
etud = r.json()
assert len(etud) == 24
fields_ok = verify_fields(etud, fields)
fields_ok = verify_fields(etud, ETUD_FIELDS)
assert fields_ok is True
######### Test code ine #########
@ -172,47 +108,14 @@ def test_etudiant(api_headers):
assert r.status_code == 200
etud = r.json()
assert len(etud) == 24
fields_ok = verify_fields(etud, fields)
fields_ok = verify_fields(etud, ETUD_FIELDS)
assert fields_ok is True
def test_etudiant_formsemestres(api_headers):
"""
Test 'etudiant_formsemestres'
Routes :
- /etudiant/etudid/<int:etudid>/formsemestres
- /etudiant/nip/<int:nip>/formsemestres
- /etudiant/ine/<int:ine>/formsemestres
Route: /etudiant/etudid/<etudid:int>/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 #########
@ -226,9 +129,7 @@ def test_etudiant_formsemestres(api_headers):
assert len(formsemestres) == 1
formsemestre = formsemestres[0]
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
assert verify_fields(formsemestre, FSEM_FIELDS) is True
######### Test code nip #########
r = requests.get(
@ -241,9 +142,7 @@ def test_etudiant_formsemestres(api_headers):
assert len(formsemestres) == 1
formsemestre = formsemestres[0]
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
assert verify_fields(formsemestre, FSEM_FIELDS) is True
######### Test code ine #########
r = requests.get(
@ -256,29 +155,13 @@ def test_etudiant_formsemestres(api_headers):
assert len(formsemestres) == 1
formsemestre = formsemestres[0]
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
assert verify_fields(formsemestre, FSEM_FIELDS) is True
def test_etudiant_bulletin_semestre(api_headers):
"""
Test 'etudiant_bulletin_semestre'
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
"""
Route: /etudiant/etudid/<etudid>/formsemestre/<formsemestre_id>/bulletin
"""
######### Test etudid #########
r = requests.get(
@ -311,15 +194,19 @@ def test_etudiant_bulletin_semestre(api_headers):
bul = r.json()
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):
"""
Test 'etudiant_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
Route:
/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups
"""
fields = [
"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.tools_test_api import verify_fields
from tests.api.tools_test_api import FORMATION_FIELDS, MODIMPL_FIELDS
# formations
def test_formations_ids(api_headers):
"""
Test 'formations_ids'
Routes :
- /formations_ids
Route: /formations_ids
"""
r = requests.get(
API_URL + "/formations_ids",
@ -44,150 +41,67 @@ def test_formations_ids(api_headers):
assert all(isinstance(x, int) for x in formations_ids)
# formations_by_id
def test_formations_by_id(api_headers):
"""
Test 'formations_by_id'
Routes :
- /formations/<int:formation_id>
Route: /formation/<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(
API_URL + "/formations/1",
API_URL + "/formation/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
formation = r.json()
fields_ok = verify_fields(formation, fields)
assert fields_ok is True
assert verify_fields(formation, FORMATION_FIELDS) is True
# TODO tester le contenu de certains champs
def test_formation_export(api_headers):
"""
Test 'formation_export_by_formation_id'
Routes :
- /formations/formation_export/<int:formation_id>
- /formations/formation_export/<int:formation_id>/with_ids
Route: /formation/formation_export/<int:formation_id>
"""
fields = [
"id",
"acronyme",
"titre_officiel",
"formation_code",
"code_specialite",
"dept_id",
"titre",
"version",
"type_parcours",
"referentiel_competence_id",
"formation_id",
"ue",
]
r = requests.get(
API_URL + "/formations/formation_export/1",
API_URL + "/formation/formation_export/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
export_formation = r.json()
fields_ok = verify_fields(export_formation, fields)
assert fields_ok is True
assert verify_fields(export_formation, FORMATION_FIELDS) is True
# 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):
"""
Test 'moduleimpl'
Route :
- /formations/moduleimpl/<int:moduleimpl_id>
Route: /formation/moduleimpl/<int:moduleimpl_id>
"""
fields = [
"id",
"formsemestre_id",
"computation_expr",
"module_id",
"responsable_id",
"moduleimpl_id",
"ens",
"module",
]
r = requests.get(
API_URL + "/formations/moduleimpl/1",
API_URL + "/formation/moduleimpl/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
moduleimpl = r.json()
fields_ok = verify_fields(moduleimpl, fields)
assert fields_ok is True
assert verify_fields(moduleimpl, MODIMPL_FIELDS) is True
# 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):
"""
Test 'referentiel_competences'
Route :
- /formations/<int:formation_id>/referentiel_competences
Route: "/formation/<int:formation_id>/referentiel_competences",
"""
r = requests.get(
API_URL + "/formations/1/referentiel_competences",
API_URL + "/formation/1/referentiel_competences",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)

View File

@ -18,17 +18,16 @@ Utilisation :
"""
import requests
from app.api.formsemestres import formsemestre
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):
"""
Test 'formsemestre'
Route :
- /formsemestre/<int:formsemestre_id>
Route: /formsemestre/<id>
"""
r = requests.get(
API_URL + "/formsemestre/1",
@ -36,64 +35,48 @@ def test_formsemestre(api_headers):
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
formsemestre = r.json()
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
assert verify_fields(formsemestre, FSEM_FIELDS)
# TODO
# def test_formsemestre_apo(api_headers):
# """
# Test 'formsemestre_apo'
#
# Route :
# - /formsemestre/apo/<string:etape_apo>
# """
# r = requests.get(
# API_URL + "/formations/apo/<string:etape_apo>",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
def test_etudiant_bulletin(api_headers):
"""
Route:
"""
formsemestre_id = 1
r = requests.get(
f"{API_URL}/etudiant/etudid/1/formsemestre/{formsemestre_id}/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
bull_a = r.json()
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):
"""
Test 'bulletins'
Route :
- /formsemestre/<int:formsemestre_id>/bulletins
Route:
"""
r = requests.get(
API_URL + "/formsemestre/1/bulletins",
@ -105,12 +88,6 @@ def test_bulletins(api_headers):
# # jury
# def test_jury():
# """
# Test 'jury'
#
# Route :
# - /formsemestre/<int:formsemestre_id>/jury
# """
# r = requests.get(
# API_URL + "/formsemestre/1/jury",
# headers=api_headers,
@ -118,70 +95,11 @@ def test_bulletins(api_headers):
# )
# assert r.status_code == 200
# TODO A revoir
def test_programme(api_headers):
def test_formsemestre_programme(api_headers):
"""
Test 'programme'
Route :
- /formsemestre/<int:formsemestre_id>/programme
Route: /formsemestre/1/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(
API_URL + "/formsemestre/1/programme",
@ -189,16 +107,22 @@ def test_programme(api_headers):
verify=CHECK_CERTIFICATE,
)
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]
ressource = r.json()["ressources"][0]
sae = r.json()["saes"][0]
fields_ue_OK = verify_fields(ue, ue_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
assert verify_fields(ue, UE_FIELDS)
if len(modules) > 1:
assert verify_fields(modules[0], MODIMPL_FIELDS)
assert verify_fields(ressource, MODIMPL_FIELDS)
assert verify_fields(sae, MODIMPL_FIELDS)

View File

@ -43,6 +43,8 @@ def test_permissions(api_headers):
# "date_debut":
# "date_fin":
"dept": "TAPI",
"dept_ident": "TAPI",
"dept_id": 1,
"etape_apo": "???",
"etat": "I",
"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
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
"""
for field in json_response:
if field not in fields:
return False
return True
return all(field in json_response for field in expected_fields)
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>
</table>
"""
assert xmls_compare(table_xml, expected_result)
assert xmls_compare(table_xml, expected_result)