Compare commits

...

4 Commits

14 changed files with 970 additions and 360 deletions

View File

@ -1,20 +1,14 @@
#################################################### Absences #########################################################
from datetime import datetime
from flask import jsonify
from app import models
from app.api import bp
from app.api.errors import error_response
from app.api.auth import token_permission_required
from app.api.tools import get_etu_from_etudid_or_nip_or_ine
from app.scodoc.sco_abs import (
add_absence,
add_justif,
annule_absence,
annule_justif,
list_abs_date,
)
from app.scodoc import notesdb as ndb
from app.scodoc import sco_abs
from app.scodoc.sco_groups import get_group_members
from app.scodoc.sco_permissions import Permission
@ -30,35 +24,51 @@ def absences(etudid: int = None, nip: int = None, ine: int = None):
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
Exemple de résultat:
[
{
"jour": "2022-04-15",
"matin": true,
"estabs": true,
"estjust": true,
"description": "",
"begin": "2022-04-15 08:00:00",
"end": "2022-04-15 11:59:59"
},
{
"jour": "2022-04-15",
"matin": false,
"estabs": true,
"estjust": false,
"description": "",
"begin": "2022-04-15 12:00:00",
"end": "2022-04-15 17:59:59"
}
]
"""
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_etu_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 "
"Veilliez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
)
etudid = etud.etudid
# Récupération des absences de l'étudiant
abs = models.Absence.query.filter_by(etudid=etudid)
# Si l'étudiant a au minimum une absence
if len(abs) > 0:
# Mise en forme des données
data = [d.to_dict() for d in abs]
return jsonify(data)
return error_response(200, message="Aucune absence trouvé pour cet étudiant")
ndb.open_db_connection()
absences = sco_abs.list_abs_date(etudid)
for absence in absences:
absence["jour"] = absence["jour"].isoformat()
return jsonify(absences)
@bp.route("/absences/etudid/<int:etudid>/abs_just_only", methods=["GET"])
@bp.route("/absences/nip/<int:nip>/abs_just_only", methods=["GET"])
@bp.route("/absences/ine/<int:ine>/abs_just_only", methods=["GET"])
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
@bp.route("/absences/nip/<int:nip>/just", methods=["GET"])
@bp.route("/absences/ine/<int:ine>/just", methods=["GET"])
@token_permission_required(Permission.APIView)
def absences_justify(etudid: int = None, nip: int = None, ine: int = None):
"""
@ -67,6 +77,28 @@ def absences_justify(etudid: int = None, nip: int = None, ine: int = None):
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
Exemple de résultat :
[
{
"jour": "2022-04-15",
"matin": true,
"estabs": true,
"estjust": true,
"description": "",
"begin": "2022-04-15 08:00:00",
"end": "2022-04-15 11:59:59"
},
{
"jour": "Fri, 15 Apr 2022 00:00:00 GMT",
"matin": false,
"estabs": true,
"estjust": false,
"description": "",
"begin": "2022-04-15 12:00:00",
"end": "2022-04-15 17:59:59"
}
]
"""
if etudid is None:
# Récupération de l'étudiant
@ -77,125 +109,14 @@ def absences_justify(etudid: int = None, nip: int = None, ine: int = None):
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veilliez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
"Veuillez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
)
# Récupération des absences justifiées de l'étudiant
abs = models.Absence.query.filter_by(etudid=etudid, estjust=True)
# Si l'étudiant a au minimum une absence justifiées
if len(abs) > 0:
# Mise en forme des données
data = [d.to_dict() for d in abs]
return jsonify(data)
return error_response(
200, message="Aucune absence justifié trouvé pour cet étudiant"
)
@bp.route(
"/absences/abs_annule?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>",
methods=["POST"],
)
@bp.route(
"/absences/abs_annule?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>",
methods=["POST"],
)
@bp.route(
"/absences/abs_annule?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>",
methods=["POST"],
)
@token_permission_required(Permission.APIAbsChange)
def abs_annule(
jour: datetime, matin: str, etudid: int = None, nip: int = None, ine: int = None
):
"""
Retourne un html
jour : la date de l'absence a annulé
matin : True ou False
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_abs.annule_absence()
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:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veilliez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
)
try:
# Utilisation de la fonction annule_absence
annule_absence(etudid, jour, matin)
except AttributeError:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veilliez vérifier que le 'jour' et le 'matin' sont valides",
)
return error_response(200, message="OK")
@bp.route(
"/absences/abs_annule_justif?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>",
methods=["POST"],
)
@bp.route(
"/absences/abs_annule_justif?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>",
methods=["POST"],
)
@bp.route(
"/absences/abs_annule_justif?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>",
methods=["POST"],
)
@token_permission_required(Permission.APIAbsChange)
def abs_annule_justif(
jour: datetime, matin: str, etudid: int = None, nip: int = None, ine: int = None
):
"""
Retourne un html
jour : la date de l'absence a annulé
matin : True ou False
etudid : l'etudid d'un étudiant
nip: le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_abs.annule_justif()
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:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veilliez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
)
try:
# Utilisation de la fonction annule_justif
annule_justif(etudid, jour, matin)
except ValueError:
return error_response(
409,
message="La requête ne peut être traitée en létat actuel.\n "
"Veilliez vérifier que le 'jour' et le 'matin' sont valides",
)
return error_response(200, message="OK")
absences = sco_abs.list_abs_date(etudid)
for absence in [absence for absence in absences if absence["estjust"]]:
absence["jour"] = absence["jour"].isoformat()
return jsonify(absences)
@bp.route(
@ -203,7 +124,7 @@ def abs_annule_justif(
methods=["GET"],
)
@token_permission_required(Permission.APIView)
def abs_groupe_etat(
def abs_groupe_etat( # XXX A REVOIR XXX
group_id: int, date_debut, date_fin, with_boursier=True, format="html"
):
"""
@ -222,7 +143,7 @@ def abs_groupe_etat(
data = []
# Filtre entre les deux dates renseignées
for member in members:
abs = list_abs_date(member.id, date_debut, date_fin)
abs = sco_abs.list_abs_date(member.id, date_debut, date_fin)
data.append(abs)
# return jsonify(data) # XXX TODO faire en sorte de pouvoir renvoyer sa (ex to_dict() dans absences)

View File

@ -178,6 +178,77 @@ def referenciel_competences(dept: str, formation_id: int):
def semestre_index(dept: str, formsemestre_id: int):
"""
Retourne la liste des Ues, ressources et SAE d'un semestre
dept : l'acronym d'un département
formsemestre_id : l'id d'un formesemestre
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
},
...
]
}
"""
app.set_sco_dept(dept)

View File

@ -12,6 +12,7 @@ from app.models import FormSemestreInscription, FormSemestre, Identite
from app.scodoc import sco_bulletins
from app.scodoc import sco_groups
from app.scodoc.sco_permissions import Permission
from app.scodoc import notesdb as ndb
@bp.route("/etudiants/courant", methods=["GET"])
@ -86,10 +87,10 @@ def etudiant(etudid: int = None, nip: int = None, ine: int = None):
}
"""
# Récupération de l'étudiant
etu = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
etud = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
# Mise en forme des données
data = etu.to_dict_bul(include_urls=False)
data = etud.to_dict_bul(include_urls=False)
return jsonify(data)
@ -174,6 +175,174 @@ def etudiant_bulletin_semestre(
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
Exemple de résultat :
{
"version": "0",
"type": "BUT",
"date": "2022-04-27T07:18:16.450634Z",
"publie": true,
"etudiant": {
"civilite": "X",
"code_ine": "1",
"code_nip": "1",
"date_naissance": "",
"email": "SACHA.COSTA@example.com",
"emailperso": "",
"etudid": 1,
"nom": "COSTA",
"prenom": "SACHA",
"nomprenom": "Sacha COSTA",
"lieu_naissance": "",
"dept_naissance": "",
"nationalite": "",
"boursier": "",
"fiche_url": "/ScoDoc/TAPI/Scolarite/ficheEtud?etudid=1",
"photo_url": "/ScoDoc/TAPI/Scolarite/get_photo_image?etudid=1&size=small",
"id": 1,
"codepostaldomicile": "",
"paysdomicile": "",
"telephonemobile": "",
"typeadresse": "domicile",
"domicile": "",
"villedomicile": "",
"telephone": "",
"fax": "",
"description": ""
},
"formation": {
"id": 1,
"acronyme": "BUT R&amp;T",
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
"titre": "BUT R&amp;T"
},
"formsemestre_id": 1,
"etat_inscription": "I",
"options": {
"show_abs": true,
"show_abs_modules": false,
"show_ects": true,
"show_codemodules": false,
"show_matieres": false,
"show_rangs": true,
"show_ue_rangs": true,
"show_mod_rangs": true,
"show_moypromo": false,
"show_minmax": false,
"show_minmax_mod": false,
"show_minmax_eval": false,
"show_coef": true,
"show_ue_cap_details": false,
"show_ue_cap_current": true,
"show_temporary": true,
"temporary_txt": "Provisoire",
"show_uevalid": true,
"show_date_inscr": true
},
"ressources": {
"R101": {
"id": 1,
"titre": "Initiation aux r\u00e9seaux informatiques",
"code_apogee": null,
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=1",
"moyenne": {},
"evaluations": [
{
"id": 1,
"description": "eval1",
"date": "2022-04-20",
"heure_debut": "08:00",
"heure_fin": "09:00",
"coef": "01.00",
"poids": {
"RT1.1": 1.0,
},
"note": {
"value": "12.00",
"min": "00.00",
"max": "18.00",
"moy": "10.88"
},
"url": "/ScoDoc/TAPI/Scolarite/Notes/evaluation_listenotes?evaluation_id=1"
}
]
},
},
"saes": {
"SAE11": {
"id": 2,
"titre": "Se sensibiliser \u00e0 l&apos;hygi\u00e8ne informatique et \u00e0 la cybers\u00e9curit\u00e9",
"code_apogee": null,
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=2",
"moyenne": {},
"evaluations": []
},
},
"ues": {
"RT1.1": {
"id": 1,
"titre": "Administrer les r\u00e9seaux et l\u2019Internet",
"numero": 1,
"type": 0,
"color": "#B80004",
"competence": null,
"moyenne": {
"value": "08.50",
"min": "06.00",
"max": "16.50",
"moy": "11.31",
"rang": "12",
"total": 16
},
"bonus": "00.00",
"malus": "00.00",
"capitalise": null,
"ressources": {
"R101": {
"id": 1,
"coef": 12.0,
"moyenne": "12.00"
},
},
"saes": {
"SAE11": {
"id": 2,
"coef": 16.0,
"moyenne": "~"
},
},
"ECTS": {
"acquis": 0.0,
"total": 12.0
}
},
"semestre": {
"etapes": [],
"date_debut": "2021-09-01",
"date_fin": "2022-08-31",
"annee_universitaire": "2021 - 2022",
"numero": 1,
"inscription": "",
"groupes": [],
"absences": {
"injustifie": 1,
"total": 2
},
"ECTS": {
"acquis": 0,
"total": 30.0
},
"notes": {
"value": "10.60",
"min": "02.40",
"moy": "11.05",
"max": "17.40"
},
"rang": {
"value": "10",
"total": 16
}
}
}
"""
# Fonction utilisée : app.scodoc.sco_bulletins_json.make_json_formsemestre_bulletinetud()
@ -247,27 +416,19 @@ def etudiant_groups(
]
"""
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_etu_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",
)
etudid = etud.etudid
# Récupération du formsemestre
sem = models.FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
try:
dept = models.Departement.query.get(sem.dept_id)
app.set_sco_dept(dept.acronym)
data = sco_groups.get_etud_groups(etudid, sem.id)
except AttributeError:
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"
" et le formsemestre_id sont valides",
)
return jsonify(data)

View File

@ -22,18 +22,18 @@ def evaluations(moduleimpl_id: int):
Exemple de résultat :
[
{
"jour": "20/04/2022",
"id": 1,
"heure_fin": "09h00",
"note_max": 20.0,
"visibulletin": true,
"evaluation_type": 0,
"moduleimpl_id": 1,
"jour": "20/04/2022",
"heure_debut": "08h00",
"description": "eval1",
"coefficient": 1.0,
"publish_incomplete": false,
"numero": 0,
"id": 1,
"heure_fin": "09h00",
"note_max": 20.0,
"visibulletin": true,
"evaluation_type": 0,
"evaluation_id": 1,
"jouriso": "2022-04-20",
"duree": "1h",

View File

@ -14,6 +14,25 @@ from app.scodoc.sco_permissions import Permission
def formations():
"""
Retourne la liste des formations
Exemple de résultat :
[
{
"id": 1,
"acronyme": "BUT R&amp;T",
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
"formation_code": "V1RET",
"code_specialite": null,
"dept_id": 1,
"titre": "BUT R&amp;T",
"version": 1,
"type_parcours": 700,
"referentiel_competence_id": null,
"formation_id": 1
},
...
]
"""
# Récupération de toutes les formations
list_formations = models.Formation.query.all()
@ -31,12 +50,27 @@ def formations_by_id(formation_id: int):
Retourne une formation en fonction d'un id donné
formation_id : l'id d'une formation
Exemple de résultat :
{
"id": 1,
"acronyme": "BUT R&amp;T",
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
"formation_code": "V1RET",
"code_specialite": null,
"dept_id": 1,
"titre": "BUT R&amp;T",
"version": 1,
"type_parcours": 700,
"referentiel_competence_id": null,
"formation_id": 1
}
"""
# Récupération de la formation
forma = models.Formation.query.filter_by(id=formation_id).first_or_404()
# Mise en forme des données
data = [d.to_dict() for d in forma]
data = forma.to_dict()
return jsonify(data)
@ -46,6 +80,98 @@ def formations_by_id(formation_id: int):
def formation_export_by_formation_id(formation_id: int, export_ids=False):
"""
Retourne la formation, avec UE, matières, modules
formation_id : l'id d'une formation
Exemple de résultat :
{
"id": 1,
"acronyme": "BUT R&amp;T",
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
"formation_code": "V1RET",
"code_specialite": null,
"dept_id": 1,
"titre": "BUT R&amp;T",
"version": 1,
"type_parcours": 700,
"referentiel_competence_id": null,
"formation_id": 1,
"ue": [
{
"acronyme": "RT1.1",
"numero": 1,
"titre": "Administrer les r\u00e9seaux et l\u2019Internet",
"type": 0,
"ue_code": "UCOD11",
"ects": 12.0,
"is_external": false,
"code_apogee": "",
"coefficient": 0.0,
"semestre_idx": 1,
"color": "#B80004",
"reference": 1,
"matiere": [
{
"titre": "Administrer les r\u00e9seaux et l\u2019Internet",
"numero": 1,
"module": [
{
"titre": "Initiation aux r\u00e9seaux informatiques",
"abbrev": "Init aux r\u00e9seaux informatiques",
"code": "R101",
"heures_cours": 0.0,
"heures_td": 0.0,
"heures_tp": 0.0,
"coefficient": 1.0,
"ects": "",
"semestre_id": 1,
"numero": 10,
"code_apogee": "",
"module_type": 2,
"coefficients": [
{
"ue_reference": "1",
"coef": "12.0"
},
{
"ue_reference": "2",
"coef": "4.0"
},
{
"ue_reference": "3",
"coef": "4.0"
}
]
},
{
"titre": "Se sensibiliser \u00e0 l&apos;hygi\u00e8ne informatique et \u00e0 la cybers\u00e9curit\u00e9",
"abbrev": "Hygi\u00e8ne informatique",
"code": "SAE11",
"heures_cours": 0.0,
"heures_td": 0.0,
"heures_tp": 0.0,
"coefficient": 1.0,
"ects": "",
"semestre_id": 1,
"numero": 10,
"code_apogee": "",
"module_type": 3,
"coefficients": [
{
"ue_reference": "1",
"coef": "16.0"
}
]
},
...
]
},
...
]
},
]
}
"""
# Fonction utilité : app.scodoc.sco_formations.formation_export()
@ -111,8 +237,40 @@ def moduleimpls_sem(formsemestre_id: int):
"""
Retourne la liste des moduleimpl d'un semestre
moduleimpl_id : l'id d'un moduleimpl
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

View File

@ -21,6 +21,35 @@ def formsemestre(formsemestre_id: int):
formsemestre_id : l'id d'un 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": []
}
"""
# Récupération de tous les formsemestres
formsemetre = models.FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
@ -47,11 +76,10 @@ def formsemestre(formsemestre_id: int):
def etudiant_bulletin(
formsemestre_id,
dept,
format="json",
etudid: int = None,
nip: int = None,
ine: int = None,
): # *args, size
):
"""
Retourne le bulletin de note d'un étudiant
@ -59,10 +87,112 @@ def etudiant_bulletin(
etudid : l'etudid d'un étudiant
nip : le code nip d'un étudiant
ine : le code ine d'un étudiant
"""
# Fonction utilisée : app.scodoc.sco_bulletins.formsemestre_billetinetud_dict()
# make_json_formsemestre_bulletinetud
Exemple de résultat :
{
"etudid":1,
"formsemestre_id":1,
"date":"2022-04-27T10:44:47.448094",
"publie":true,
"etapes":[
],
"etudiant":{
"etudid":1,
"code_nip":"1",
"code_ine":"1",
"nom":"COSTA",
"prenom":"Sacha",
"civilite":"",
"photo_url":"/ScoDoc/TAPI/Scolarite/get_photo_image?etudid=1&amp;size=small",
"email":"SACHA.COSTA@example.com",
"emailperso":"",
"sexe":""
},
"note":{
"value":"10.60",
"min":"-",
"max":"-",
"moy":"-"
},
"rang":{
"value":"10",
"ninscrits":16
},
"rang_group":[
{
"group_type":"TD",
"group_name":"",
"value":"",
"ninscrits":""
}
],
"note_max":{
"value":20
},
"bonus_sport_culture":{
"value":0.0
},
"ue":[
{
"id":1,
"numero":"1",
"acronyme":"RT1.1",
"titre":"Administrer les r\u00e9seaux et l\u2019Internet",
"note":{
"value":"08.50",
"min":"06.00",
"max":"16.50",
"moy":"11.31"
},
"rang":"12",
"effectif":16,
"ects":"12",
"code_apogee":"",
"module":[
{
"id":1,
"code":"R101",
"coefficient":1.0,
"numero":10,
"titre":"Initiation aux r\u00e9seaux informatiques",
"abbrev":"Init aux r\u00e9seaux informatiques",
"note":{
"value":"12.00",
"moy":"-",
"max":"-",
"min":"-",
"nb_notes":"-",
"nb_missing":"-",
"nb_valid_evals":"-"
},
"code_apogee":"",
"evaluation":[
{
"jour":"2022-04-20",
"heure_debut":"08:00:00",
"heure_fin":"09:00:00",
"coefficient":1.0,
"evaluation_type":0,
"evaluation_id":1,
"description":"eval1",
"note":"12.00"
}
]
},
...
]
}
],
"ue_capitalisee":[],
"absences":{
"nbabs":2,
"nbabsjust":1
},
"appreciation":[]
}
"""
# Fonction utilisée : app.scodoc.sco_bulletins_json.make_json_formsemestre_bulletinetud()
try:
app.set_sco_dept(dept)
@ -88,17 +218,6 @@ def etudiant_bulletin(
return data
# if args[0] == "short":
# data = formsemestre_bulletinetud_dict(formsemestre_id, etudid, version=args[0])
# elif args[0] == "selectevals":
# data = formsemestre_bulletinetud_dict(formsemestre_id, etudid, version=args[0])
# elif args[0] == "long":
# data = formsemestre_bulletinetud_dict(formsemestre_id, etudid)
# else:
# return error_response(409, message="La requête ne peut être traitée en létat actuel")
#
# return jsonify(data)
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
@token_permission_required(Permission.APIView)
@ -107,6 +226,178 @@ def bulletins(formsemestre_id: int):
Retourne les bulletins d'un formsemestre donné
formsemestre_id : l'id d'un formesemestre
Exemple de résultat :
[
{
"version": "0",
"type": "BUT",
"date": "2022-04-27T07:18:16.450634Z",
"publie": true,
"etudiant": {
"civilite": "X",
"code_ine": "1",
"code_nip": "1",
"date_naissance": "",
"email": "SACHA.COSTA@example.com",
"emailperso": "",
"etudid": 1,
"nom": "COSTA",
"prenom": "SACHA",
"nomprenom": "Sacha COSTA",
"lieu_naissance": "",
"dept_naissance": "",
"nationalite": "",
"boursier": "",
"fiche_url": "/ScoDoc/TAPI/Scolarite/ficheEtud?etudid=1",
"photo_url": "/ScoDoc/TAPI/Scolarite/get_photo_image?etudid=1&size=small",
"id": 1,
"codepostaldomicile": "",
"paysdomicile": "",
"telephonemobile": "",
"typeadresse": "domicile",
"domicile": "",
"villedomicile": "",
"telephone": "",
"fax": "",
"description": ""
},
"formation": {
"id": 1,
"acronyme": "BUT R&amp;T",
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
"titre": "BUT R&amp;T"
},
"formsemestre_id": 1,
"etat_inscription": "I",
"options": {
"show_abs": true,
"show_abs_modules": false,
"show_ects": true,
"show_codemodules": false,
"show_matieres": false,
"show_rangs": true,
"show_ue_rangs": true,
"show_mod_rangs": true,
"show_moypromo": false,
"show_minmax": false,
"show_minmax_mod": false,
"show_minmax_eval": false,
"show_coef": true,
"show_ue_cap_details": false,
"show_ue_cap_current": true,
"show_temporary": true,
"temporary_txt": "Provisoire",
"show_uevalid": true,
"show_date_inscr": true
},
"ressources": {
"R101": {
"id": 1,
"titre": "Initiation aux r\u00e9seaux informatiques",
"code_apogee": null,
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=1",
"moyenne": {},
"evaluations": [
{
"id": 1,
"description": "eval1",
"date": "2022-04-20",
"heure_debut": "08:00",
"heure_fin": "09:00",
"coef": "01.00",
"poids": {
"RT1.1": 1.0,
},
"note": {
"value": "12.00",
"min": "00.00",
"max": "18.00",
"moy": "10.88"
},
"url": "/ScoDoc/TAPI/Scolarite/Notes/evaluation_listenotes?evaluation_id=1"
}
]
},
},
"saes": {
"SAE11": {
"id": 2,
"titre": "Se sensibiliser \u00e0 l&apos;hygi\u00e8ne informatique et \u00e0 la cybers\u00e9curit\u00e9",
"code_apogee": null,
"url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=2",
"moyenne": {},
"evaluations": []
},
},
"ues": {
"RT1.1": {
"id": 1,
"titre": "Administrer les r\u00e9seaux et l\u2019Internet",
"numero": 1,
"type": 0,
"color": "#B80004",
"competence": null,
"moyenne": {
"value": "08.50",
"min": "06.00",
"max": "16.50",
"moy": "11.31",
"rang": "12",
"total": 16
},
"bonus": "00.00",
"malus": "00.00",
"capitalise": null,
"ressources": {
"R101": {
"id": 1,
"coef": 12.0,
"moyenne": "12.00"
},
},
"saes": {
"SAE11": {
"id": 2,
"coef": 16.0,
"moyenne": "~"
},
},
"ECTS": {
"acquis": 0.0,
"total": 12.0
}
},
"semestre": {
"etapes": [],
"date_debut": "2021-09-01",
"date_fin": "2022-08-31",
"annee_universitaire": "2021 - 2022",
"numero": 1,
"inscription": "",
"groupes": [],
"absences": {
"injustifie": 1,
"total": 2
},
"ECTS": {
"acquis": 0,
"total": 30.0
},
"notes": {
"value": "10.60",
"min": "02.40",
"moy": "11.05",
"max": "17.40"
},
"rang": {
"value": "10",
"total": 16
}
}
},
...
]
"""
# Fonction utilisée : app.scodoc.sco_bulletins.get_formsemestre_bulletin_etud_json()
@ -135,6 +426,9 @@ def jury(formsemestre_id: int):
Retourne le récapitulatif des décisions jury
formsemestre_id : l'id d'un formsemestre
Exemple de résultat :
"""
# Fonction utilisée : app.scodoc.sco_pvjury.formsemestre_pvjury()

View File

@ -6,7 +6,7 @@ from app.api import bp
from app.api.errors import error_response
from app.api.auth import token_permission_required
from app.scodoc.sco_groups import get_group_members, setGroups
from app.scodoc.sco_groups import get_group_members, setGroups, get_partitions_list
from app.scodoc.sco_permissions import Permission
@ -17,15 +17,38 @@ def partition(formsemestre_id: int):
Retourne la liste de toutes les partitions d'un formsemestre
formsemestre_id : l'id d'un formsemestre
"""
# Récupération de toutes les partitions
partitions = models.Partition.query.filter_by(id=formsemestre_id)
# Mise en forme des données
data = [d.to_dict() for d in partitions]
Exemple de résultat :
[
{
"partition_id": 2,
"id": 2,
"formsemestre_id": 1,
"partition_name": "TD",
"numero": 1,
"bul_show_rank": false,
"show_in_lists": true
},
{
"partition_id": 1,
"id": 1,
"formsemestre_id": 1,
"partition_name": null,
"numero": 0,
"bul_show_rank": false,
"show_in_lists": true
}
]
"""
# # Récupération de toutes les partitions
# partitions = models.Partition.query.filter_by(id=formsemestre_id)
#
# # Mise en forme des données
# data = [partition.to_dict() for partition in partitions]
data = get_partitions_list(formsemestre_id)
return jsonify(data)
# return error_response(501, message="Not implemented")
@bp.route("/partitions/groups/<int:group_id>", methods=["GET"])
@ -36,7 +59,49 @@ def etud_in_group(group_id: int, etat=None):
Retourne la liste des étudiants dans un groupe
group_id : l'id d'un groupe
etat :
etat : état de l'inscription
Exemple de résultat :
[
{
"etudid": 10,
"id": 10,
"dept_id": 1,
"nom": "BOUTET",
"prenom": "Marguerite",
"nom_usuel": "",
"civilite": "F",
"date_naissance": null,
"lieu_naissance": null,
"dept_naissance": null,
"nationalite": null,
"statut": null,
"boursier": null,
"photo_filename": null,
"code_nip": "10",
"code_ine": "10",
"scodoc7_id": null,
"email": "MARGUERITE.BOUTET@example.com",
"emailperso": null,
"domicile": null,
"codepostaldomicile": null,
"villedomicile": null,
"paysdomicile": null,
"telephone": null,
"telephonemobile": null,
"fax": null,
"typeadresse": "domicile",
"description": null,
"group_id": 1,
"etat": "I",
"civilite_str": "Mme",
"nom_disp": "BOUTET",
"nomprenom": "Mme Marguerite BOUTET",
"ne": "e",
"email_default": "MARGUERITE.BOUTET@example.com"
},
...
]
"""
# Fonction utilisée : app.scodoc.sco_groups.get_group_members()
@ -68,7 +133,7 @@ def set_groups(
Set les groups
partition_id : l'id d'une partition
groups_lists :
groups_lists : membres de chaque groupe existant
groups_ti_delete : les groupes à supprimer
groups_to_create : les groupes à créer
"""

View File

@ -137,3 +137,52 @@
# return error_response(
# 409, message="La requête ne peut être traitée en létat actuel"
# )
# @bp.route(
# "/absences/abs_annule_justif?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>",
# methods=["POST"],
# )
# @bp.route(
# "/absences/abs_annule_justif?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>",
# methods=["POST"],
# )
# @bp.route(
# "/absences/abs_annule_justif?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>",
# methods=["POST"],
# )
# @token_permission_required(Permission.APIAbsChange)
# def abs_annule_justif(
# jour: datetime, matin: str, etudid: int = None, nip: int = None, ine: int = None
# ):
# """
# Retourne un html
# jour : la date de l'absence a annulé
# matin : True ou False
# etudid : l'etudid d'un étudiant
# nip: le code nip d'un étudiant
# ine : le code ine d'un étudiant
# """
# # Fonction utilisée : app.scodoc.sco_abs.annule_justif()
# 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:
# return error_response(
# 409,
# message="La requête ne peut être traitée en létat actuel.\n "
# "Veilliez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
# )
# try:
# # Utilisation de la fonction annule_justif
# annule_justif(etudid, jour, matin)
# except ValueError:
# return error_response(
# 409,
# message="La requête ne peut être traitée en létat actuel.\n "
# "Veilliez vérifier que le 'jour' et le 'matin' sont valides",
# )
# return error_response(200, message="OK")

View File

@ -303,12 +303,14 @@ def YearTable(
return "\n".join(T)
def list_abs_in_range(etudid, debut, fin, matin=None, moduleimpl_id=None, cursor=None):
def list_abs_in_range(
etudid, debut=None, fin=None, matin=None, moduleimpl_id=None, cursor=None
):
"""Liste des absences entre deux dates.
Args:
etudid:
debut: string iso date ("2020-03-12")
debut: string iso date ("2020-03-12") ou None
end: string iso date ("2020-03-12")
matin: None, True, False
moduleimpl_id: restreint le comptage aux absences dans ce module
@ -335,9 +337,13 @@ def list_abs_in_range(etudid, debut, fin, matin=None, moduleimpl_id=None, cursor
AND A.ESTABS"""
+ ismatin
+ modul
+ """
+ (
""
if debut is None
else """
AND A.JOUR BETWEEN %(debut)s AND %(fin)s
""",
"""
),
{
"etudid": etudid,
"debut": debut,
@ -412,22 +418,27 @@ WHERE A.ETUDID = %(etudid)s
return res
def list_abs_date(etudid, beg_date, end_date):
def list_abs_date(etudid, beg_date=None, end_date=None):
"""Liste des absences et justifs entre deux dates (inclues)."""
cnx = ndb.GetDBConnexion()
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
cursor.execute(
"""SELECT jour, matin, estabs, estjust, description FROM ABSENCES A
WHERE A.ETUDID = %(etudid)s
WHERE A.ETUDID = %(etudid)s"""
+ (
""
if beg_date is None
else """
AND A.jour >= %(beg_date)s
AND A.jour <= %(end_date)s
""",
vars(),
)
Abs = cursor.dictfetchall()
)
absences = cursor.dictfetchall()
# remove duplicates
A = {} # { (jour, matin) : abs }
for a in Abs:
for a in absences:
jour, matin = a["jour"], a["matin"]
if (jour, matin) in A:
# garde toujours la description

View File

@ -48,114 +48,21 @@ def test_absences():
# absences_justify
def test_absences_justify():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/etudid/<int:etudid>/abs_just_only",
SCODOC_URL + "/ScoDoc/api/absences/etudid/1/just",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/nip/<int:nip>/abs_just_only",
SCODOC_URL + "/ScoDoc/api/absences/nip/1/just",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/ine/<int:ine>/abs_just_only",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# abs_signale
def test_abs_signale():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_signale?etudid=<int:etudid>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_signale?nip=<int:nip>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_signale?ine=<int:ine>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_signale?ine=<int:ine>&date=<string:date>&matin=<string:matin>&justif=<string:justif>"
"&description=<string:description>&moduleimpl_id=<int:moduleimpl_id>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# abs_annule
def test_abs_annule():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_annule?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_annule?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_annule?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# abs_annule_justif
def test_abs_annule_justif():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_annule_justif?etudid=<int:etudid>&jour=<string:jour>&matin=<string:matin>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_annule_justif?nip=<int:nip>&jour=<string:jour>&matin=<string:matin>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/absences/abs_annule_justif?ine=<int:ine>&jour=<string:jour>&matin=<string:matin>",
SCODOC_URL + "/ScoDoc/api/absences/ine/1/just",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)

View File

@ -24,7 +24,7 @@ from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
# evaluations
def test_evaluations():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/evaluations/<int:moduleimpl_id>",
SCODOC_URL + "/ScoDoc/api/evaluations/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
@ -34,34 +34,7 @@ def test_evaluations():
# evaluation_notes
def test_evaluation_notes():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/evaluations/eval_notes/<int:evaluation_id>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# evaluation_set_notes
def test_evaluation_set_notes():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/evaluations/eval_set_notes?eval_id=<int:eval_id>&etudid=<int:etudid>&note=<float:note>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/evaluations/eval_set_notes?eval_id=<int:eval_id>&nip=<int:nip>&note=<float:note>",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/evaluations/eval_set_notes?eval_id=<int:eval_id>&ine=<int:ine>&note=<float:note>",
SCODOC_URL + "/ScoDoc/api/evaluations/eval_notes/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)

View File

@ -34,7 +34,7 @@ def test_formations():
# formations_by_id
def test_formations_by_id():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations/<int:formation_id>",
SCODOC_URL + "/ScoDoc/api/formations/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
@ -44,7 +44,7 @@ def test_formations_by_id():
# formation_export_by_formation_id
def test_formation_export_by_formation_id():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations/formation_export/<int:formation_id>",
SCODOC_URL + "/ScoDoc/api/formations/formation_export/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
@ -75,7 +75,7 @@ def test_moduleimpls():
def test_moduleimpls_sem():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/formations/moduleimpl/<int:moduleimpl_id>/formsemestre/<int:formsemestre_id>",
+ "/ScoDoc/api/formations/moduleimpl/formsemestre/1/liste",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)

View File

@ -97,16 +97,16 @@ def test_etudiant_bulletin(): #XXX TODO pour Seb
assert r.status_code == 200
# # bulletins
# def test_bulletins():
# r = requests.get(
# SCODOC_URL + "/ScoDoc/api/formsemestre/1/bulletins",
# headers=HEADERS,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
#
#
# bulletins
def test_bulletins():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1/bulletins",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# # jury
# def test_jury():
# r = requests.get(

View File

@ -24,7 +24,7 @@ from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
# partition
def test_partition():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/partitions/<int:formsemestre_id>",
SCODOC_URL + "/ScoDoc/api/partitions/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
@ -34,7 +34,7 @@ def test_partition():
# etud_in_group
def test_etud_in_group():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/partitions/groups/<int:group_id>",
SCODOC_URL + "/ScoDoc/api/partitions/groups/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)