forked from ScoDoc/ScoDoc
WIP: new API revue et corrigée (en cours)
This commit is contained in:
parent
455ce295d8
commit
ca1fe679db
@ -31,4 +31,3 @@ from app.api import evaluations
|
|||||||
from app.api import jury
|
from app.api import jury
|
||||||
from app.api import absences
|
from app.api import absences
|
||||||
from app.api import logos
|
from app.api import logos
|
||||||
from app.api import debug
|
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
#################################################### Absences #########################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
"""ScoDoc 9 API : Absences
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.models import Identite, FormSemestre
|
from app.models import Identite
|
||||||
|
|
||||||
from app.scodoc import notesdb as ndb
|
from app.scodoc import notesdb as ndb
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_abs
|
||||||
from app.scodoc.sco_abs import list_abs_date, annule_absence, annule_justif, add_abslist
|
|
||||||
|
# from app.scodoc.sco_abs import annule_absence, annule_justif, add_abslist
|
||||||
from app.scodoc.sco_groups import get_group_members
|
from app.scodoc.sco_groups import get_group_members
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
@ -53,10 +60,10 @@ def absences(etudid: int = None):
|
|||||||
)
|
)
|
||||||
# Absences de l'étudiant
|
# Absences de l'étudiant
|
||||||
ndb.open_db_connection()
|
ndb.open_db_connection()
|
||||||
absences = sco_abs.list_abs_date(etud.id)
|
abs_list = sco_abs.list_abs_date(etud.id)
|
||||||
for absence in absences:
|
for absence in abs_list:
|
||||||
absence["jour"] = absence["jour"].isoformat()
|
absence["jour"] = absence["jour"].isoformat()
|
||||||
return jsonify(absences)
|
return jsonify(abs_list)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
||||||
@ -158,9 +165,6 @@ def abs_groupe_etat(group_id: int, date_debut=None, date_fin=None):
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
# Fonction utilisée : app.scodoc.sco_groups.get_group_members() et app.scodoc.sco_abs.list_abs_date()
|
|
||||||
|
|
||||||
# Utilisation de la fonction get_group_members
|
|
||||||
members = get_group_members(group_id)
|
members = get_group_members(group_id)
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
@ -175,88 +179,89 @@ def abs_groupe_etat(group_id: int, date_debut=None, date_fin=None):
|
|||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
# XXX TODO EV: A REVOIR (data json dans le POST + modifier les routes)
|
||||||
"/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs",
|
# @bp.route(
|
||||||
methods=["POST"],
|
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs",
|
||||||
defaults={"just_or_not": 0},
|
# methods=["POST"],
|
||||||
)
|
# defaults={"just_or_not": 0},
|
||||||
@bp.route(
|
# )
|
||||||
"/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_not_just",
|
# @bp.route(
|
||||||
methods=["POST"],
|
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_not_just",
|
||||||
defaults={"just_or_not": 1},
|
# methods=["POST"],
|
||||||
)
|
# defaults={"just_or_not": 1},
|
||||||
@bp.route(
|
# )
|
||||||
"/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_just",
|
# @bp.route(
|
||||||
methods=["POST"],
|
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_just",
|
||||||
defaults={"just_or_not": 2},
|
# methods=["POST"],
|
||||||
)
|
# defaults={"just_or_not": 2},
|
||||||
@token_auth.login_required
|
# )
|
||||||
@token_permission_required(Permission.APIAbsChange)
|
# @token_auth.login_required
|
||||||
def reset_etud_abs(etudid: int, list_abs, just_or_not: int = 0):
|
# @token_permission_required(Permission.APIAbsChange)
|
||||||
"""
|
# def reset_etud_abs(etudid: int, list_abs: str, just_or_not: int = 0):
|
||||||
Set la liste des absences d'un étudiant sur tout un semestre.
|
# """
|
||||||
(les absences existant pour cet étudiant sur cette période sont effacées)
|
# Set la liste des absences d'un étudiant sur tout un semestre.
|
||||||
|
# (les absences existant pour cet étudiant sur cette période sont effacées)
|
||||||
|
|
||||||
etudid : l'id d'un étudiant
|
# etudid : l'id d'un étudiant
|
||||||
list_abs : json d'absences
|
# list_abs : json d'absences
|
||||||
just_or_not : 0 (pour les absences justifiées et non justifiées),
|
# just_or_not : 0 (pour les absences justifiées et non justifiées),
|
||||||
1 (pour les absences justifiées),
|
# 1 (pour les absences justifiées),
|
||||||
2 (pour les absences non justifiées)
|
# 2 (pour les absences non justifiées)
|
||||||
"""
|
# """
|
||||||
# Toutes les absences
|
# # Toutes les absences
|
||||||
if just_or_not == 0:
|
# if just_or_not == 0:
|
||||||
# suppression des absences et justificatif déjà existant pour éviter les doublons
|
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
||||||
for abs in list_abs:
|
# for abs in list_abs:
|
||||||
# Récupération de la date au format iso
|
# # Récupération de la date au format iso
|
||||||
jour = abs["jour"].isoformat()
|
# jour = abs["jour"].isoformat()
|
||||||
if abs["matin"] is True:
|
# if abs["matin"] is True:
|
||||||
annule_absence(etudid, jour, True)
|
# annule_absence(etudid, jour, True)
|
||||||
annule_justif(etudid, jour, True)
|
# annule_justif(etudid, jour, True)
|
||||||
else:
|
# else:
|
||||||
annule_absence(etudid, jour, False)
|
# annule_absence(etudid, jour, False)
|
||||||
annule_justif(etudid, jour, False)
|
# annule_justif(etudid, jour, False)
|
||||||
|
|
||||||
# Ajout de la liste d'absences en base
|
# # Ajout de la liste d'absences en base
|
||||||
add_abslist(list_abs)
|
# add_abslist(list_abs)
|
||||||
|
|
||||||
# Uniquement les absences justifiées
|
# # Uniquement les absences justifiées
|
||||||
elif just_or_not == 1:
|
# elif just_or_not == 1:
|
||||||
list_abs_not_just = []
|
# list_abs_not_just = []
|
||||||
# Trie des absences justifiées
|
# # Trie des absences justifiées
|
||||||
for abs in list_abs:
|
# for abs in list_abs:
|
||||||
if abs["estjust"] is False:
|
# if abs["estjust"] is False:
|
||||||
list_abs_not_just.append(abs)
|
# list_abs_not_just.append(abs)
|
||||||
# suppression des absences et justificatif déjà existant pour éviter les doublons
|
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
||||||
for abs in list_abs:
|
# for abs in list_abs:
|
||||||
# Récupération de la date au format iso
|
# # Récupération de la date au format iso
|
||||||
jour = abs["jour"].isoformat()
|
# jour = abs["jour"].isoformat()
|
||||||
if abs["matin"] is True:
|
# if abs["matin"] is True:
|
||||||
annule_absence(etudid, jour, True)
|
# annule_absence(etudid, jour, True)
|
||||||
annule_justif(etudid, jour, True)
|
# annule_justif(etudid, jour, True)
|
||||||
else:
|
# else:
|
||||||
annule_absence(etudid, jour, False)
|
# annule_absence(etudid, jour, False)
|
||||||
annule_justif(etudid, jour, False)
|
# annule_justif(etudid, jour, False)
|
||||||
|
|
||||||
# Ajout de la liste d'absences en base
|
# # Ajout de la liste d'absences en base
|
||||||
add_abslist(list_abs_not_just)
|
# add_abslist(list_abs_not_just)
|
||||||
|
|
||||||
# Uniquement les absences non justifiées
|
# # Uniquement les absences non justifiées
|
||||||
elif just_or_not == 2:
|
# elif just_or_not == 2:
|
||||||
list_abs_just = []
|
# list_abs_just = []
|
||||||
# Trie des absences non justifiées
|
# # Trie des absences non justifiées
|
||||||
for abs in list_abs:
|
# for abs in list_abs:
|
||||||
if abs["estjust"] is True:
|
# if abs["estjust"] is True:
|
||||||
list_abs_just.append(abs)
|
# list_abs_just.append(abs)
|
||||||
# suppression des absences et justificatif déjà existant pour éviter les doublons
|
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
||||||
for abs in list_abs:
|
# for abs in list_abs:
|
||||||
# Récupération de la date au format iso
|
# # Récupération de la date au format iso
|
||||||
jour = abs["jour"].isoformat()
|
# jour = abs["jour"].isoformat()
|
||||||
if abs["matin"] is True:
|
# if abs["matin"] is True:
|
||||||
annule_absence(etudid, jour, True)
|
# annule_absence(etudid, jour, True)
|
||||||
annule_justif(etudid, jour, True)
|
# annule_justif(etudid, jour, True)
|
||||||
else:
|
# else:
|
||||||
annule_absence(etudid, jour, False)
|
# annule_absence(etudid, jour, False)
|
||||||
annule_justif(etudid, jour, False)
|
# annule_justif(etudid, jour, False)
|
||||||
|
|
||||||
# Ajout de la liste d'absences en base
|
# # Ajout de la liste d'absences en base
|
||||||
add_abslist(list_abs_just)
|
# add_abslist(list_abs_just)
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
# -*- mode: python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# Gestion scolarite IUT
|
|
||||||
#
|
|
||||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
"""
|
|
||||||
!!! ATTENTION !!!
|
|
||||||
Fichier a utilisé uniquement à des fins de debug
|
|
||||||
"""
|
|
@ -14,12 +14,13 @@ import app
|
|||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.api.tools import get_last_instance_etud_from_etudid_or_nip_or_ine
|
from app.api import tools
|
||||||
from app.models import Departement, FormSemestreInscription, FormSemestre, Identite
|
from app.models import Departement, FormSemestreInscription, FormSemestre, Identite
|
||||||
from app.scodoc import sco_bulletins
|
from app.scodoc import sco_bulletins
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc.sco_bulletins import do_formsemestre_bulletinetud
|
from app.scodoc.sco_bulletins import do_formsemestre_bulletinetud
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/etudiants/courants", defaults={"long": False})
|
@bp.route("/etudiants/courants", defaults={"long": False})
|
||||||
@ -106,7 +107,7 @@ def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
|||||||
"description": ""
|
"description": ""
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
etud = get_last_instance_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
|
etud = tools.get_etud(etudid, nip, ine)
|
||||||
|
|
||||||
if etud is None:
|
if etud is None:
|
||||||
return error_response(
|
return error_response(
|
||||||
@ -153,36 +154,39 @@ def etudiants(etudid: int = None, nip: str = None, ine: str = None):
|
|||||||
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
|
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
|
||||||
"""
|
"""
|
||||||
Liste des semestres qu'un étudiant a suivi, triés par ordre chronologique.
|
Liste des semestres qu'un étudiant a suivi, triés par ordre chronologique.
|
||||||
|
Attention, si accès via NIP ou INE, les semestres peuvent être de départements différents
|
||||||
|
(si l'étudiant a changé de département). L'id du département est `dept_id`.
|
||||||
|
|
||||||
Accès par etudid, nip ou ine
|
Accès par etudid, nip ou ine
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"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",
|
"date_fin": "31/08/2022",
|
||||||
"resp_can_edit": false,
|
|
||||||
"dept_id": 1,
|
"dept_id": 1,
|
||||||
|
"elt_annee_apo": null,
|
||||||
|
"elt_sem_apo": null,
|
||||||
|
"ens_can_edit_eval": false,
|
||||||
"etat": true,
|
"etat": true,
|
||||||
"resp_can_change_ens": true,
|
"formation_id": 1,
|
||||||
|
"formsemestre_id": 1,
|
||||||
|
"gestion_compensation": false,
|
||||||
|
"gestion_semestrielle": false,
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"modalite": "FI",
|
"modalite": "FI",
|
||||||
"ens_can_edit_eval": false,
|
"resp_can_change_ens": true,
|
||||||
"formation_id": 1,
|
"resp_can_edit": false,
|
||||||
"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": []
|
"responsables": []
|
||||||
|
"scodoc7_id": null,
|
||||||
|
"semestre_id": 1,
|
||||||
|
"titre_num": "Semestre test semestre 1",
|
||||||
|
"titre": "Semestre test",
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
@ -263,22 +267,21 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
|
|||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"version": "short", "pdf": False},
|
defaults={"version": "short", "pdf": False},
|
||||||
)
|
)
|
||||||
# Version PDF non fonctionnelle
|
@bp.route(
|
||||||
# @bp.route(
|
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
||||||
# "/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
methods=["GET"],
|
||||||
# methods=["GET"],
|
defaults={"version": "short", "pdf": True},
|
||||||
# defaults={"version": "short", "pdf": True},
|
)
|
||||||
# )
|
@bp.route(
|
||||||
# @bp.route(
|
"/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
||||||
# "/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
methods=["GET"],
|
||||||
# methods=["GET"],
|
defaults={"version": "short", "pdf": True},
|
||||||
# defaults={"version": "short", "pdf": True},
|
)
|
||||||
# )
|
@bp.route(
|
||||||
# @bp.route(
|
"/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
||||||
# "/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short/pdf",
|
methods=["GET"],
|
||||||
# methods=["GET"],
|
defaults={"version": "short", "pdf": True},
|
||||||
# defaults={"version": "short", "pdf": True},
|
)
|
||||||
# )
|
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def etudiant_bulletin_semestre( # XXX TODO Ajouter la possibilité de retourner en version pdf
|
def etudiant_bulletin_semestre( # XXX TODO Ajouter la possibilité de retourner en version pdf
|
||||||
@ -296,150 +299,8 @@ def etudiant_bulletin_semestre( # XXX TODO Ajouter la possibilité de retourner
|
|||||||
etudid : l'etudid d'un étudiant
|
etudid : l'etudid d'un étudiant
|
||||||
nip : le code nip d'un étudiant
|
nip : le code nip d'un étudiant
|
||||||
ine : le code ine d'un étudiant
|
ine : le code ine d'un étudiant
|
||||||
Exemple de résultat :
|
Exemple de résultat : voir https://scodoc.org/ScoDoc9API/#bulletin
|
||||||
{
|
|
||||||
"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&T",
|
|
||||||
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
|
|
||||||
"titre": "BUT R&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'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},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
|
||||||
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
||||||
@ -466,11 +327,10 @@ def etudiant_bulletin_semestre( # XXX TODO Ajouter la possibilité de retourner
|
|||||||
app.set_sco_dept(dept.acronym)
|
app.set_sco_dept(dept.acronym)
|
||||||
|
|
||||||
if pdf:
|
if pdf:
|
||||||
response = make_response(
|
pdf_response, _ = do_formsemestre_bulletinetud(
|
||||||
do_formsemestre_bulletinetud(formsemestre, etudid, version, "pdf")
|
formsemestre, etudid, version=version, format="pdf"
|
||||||
)
|
)
|
||||||
response.headers["Content-Type"] = "application/json"
|
return pdf_response
|
||||||
return response
|
|
||||||
|
|
||||||
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
return sco_bulletins.get_formsemestre_bulletin_etud_json(
|
||||||
formsemestre, etud, version=version
|
formsemestre, etud, version=version
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
############################################### Evaluations ###########################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : accès aux évaluations
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
import app
|
import app
|
||||||
|
|
||||||
from app import models
|
from app import models
|
||||||
from app.models import Evaluation
|
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
@ -18,7 +26,7 @@ from app.scodoc.sco_permissions import Permission
|
|||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def evaluations(moduleimpl_id: int):
|
def evaluations(moduleimpl_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des évaluations à partir de l'id d'un moduleimpl
|
Retourne la liste des évaluations d'un moduleimpl
|
||||||
|
|
||||||
moduleimpl_id : l'id d'un moduleimpl
|
moduleimpl_id : l'id d'un moduleimpl
|
||||||
|
|
||||||
@ -40,7 +48,7 @@ def evaluations(moduleimpl_id: int):
|
|||||||
"evaluation_id": 1,
|
"evaluation_id": 1,
|
||||||
"jouriso": "2022-04-20",
|
"jouriso": "2022-04-20",
|
||||||
"duree": "1h",
|
"duree": "1h",
|
||||||
"descrheure": " de 08h00 \u00e0 09h00",
|
"descrheure": " de 08h00 à 09h00",
|
||||||
"matin": 1,
|
"matin": 1,
|
||||||
"apresmidi": 0
|
"apresmidi": 0
|
||||||
},
|
},
|
||||||
@ -88,16 +96,11 @@ def evaluation_notes(evaluation_id: int):
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# Fonction utilisée : app.scodoc.sco_evaluation_db.do_evaluation_get_all_notes()
|
|
||||||
|
|
||||||
evaluation = models.Evaluation.query.filter_by(id=evaluation_id).first_or_404()
|
evaluation = models.Evaluation.query.filter_by(id=evaluation_id).first_or_404()
|
||||||
dept = models.Departement.query.filter_by(
|
dept = evaluation.moduleimpl.formsemestre.departement
|
||||||
id=evaluation.moduleimpl.formsemestre.dept_id
|
|
||||||
).first()
|
|
||||||
app.set_sco_dept(dept.acronym)
|
app.set_sco_dept(dept.acronym)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Utilisation de la fonction do_evaluation_get_all_notes
|
|
||||||
data = do_evaluation_get_all_notes(evaluation_id)
|
data = do_evaluation_get_all_notes(evaluation_id)
|
||||||
except AttributeError: # ???
|
except AttributeError: # ???
|
||||||
return error_response(
|
return error_response(
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
##############################################" Formations ############################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : accès aux formations
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
import app
|
import app
|
||||||
@ -10,6 +19,7 @@ from app.models.formations import Formation
|
|||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formations", methods=["GET"])
|
@bp.route("/formations", methods=["GET"])
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
@ -17,16 +27,11 @@ def formations():
|
|||||||
"""
|
"""
|
||||||
Retourne la liste de toutes les formations (tous départements)
|
Retourne la liste de toutes les formations (tous départements)
|
||||||
|
|
||||||
Exemple de résultat :
|
|
||||||
"""
|
"""
|
||||||
# Récupération de toutes les formations
|
data = [d.to_dict() for d in models.Formation.query]
|
||||||
list_formations = models.Formation.query.all()
|
|
||||||
|
|
||||||
# Mise en forme des données
|
|
||||||
data = [d.to_dict() for d in list_formations]
|
|
||||||
|
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formations_ids", methods=["GET"])
|
@bp.route("/formations_ids", methods=["GET"])
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
@ -36,12 +41,7 @@ def formations_ids():
|
|||||||
|
|
||||||
Exemple de résultat : [ 17, 99, 32 ]
|
Exemple de résultat : [ 17, 99, 32 ]
|
||||||
"""
|
"""
|
||||||
# Récupération de toutes les formations
|
data = [d.id for d in models.Formation.query]
|
||||||
list_formations = models.Formation.query.all()
|
|
||||||
|
|
||||||
# Mise en forme des données
|
|
||||||
data = [d.id for d in list_formations]
|
|
||||||
|
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ def formations_ids():
|
|||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def formation_by_id(formation_id: int):
|
def formation_by_id(formation_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne une formation en fonction d'un id donné
|
La formation d'id donné
|
||||||
|
|
||||||
formation_id : l'id d'une formation
|
formation_id : l'id d'une formation
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ def formation_by_id(formation_id: int):
|
|||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"acronyme": "BUT R&T",
|
"acronyme": "BUT R&T",
|
||||||
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
|
"titre_officiel": "Bachelor technologique réseaux et télécommunications",
|
||||||
"formation_code": "V1RET",
|
"formation_code": "V1RET",
|
||||||
"code_specialite": null,
|
"code_specialite": null,
|
||||||
"dept_id": 1,
|
"dept_id": 1,
|
||||||
@ -69,13 +69,8 @@ def formation_by_id(formation_id: int):
|
|||||||
"formation_id": 1
|
"formation_id": 1
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# Récupération de la formation
|
formation = models.Formation.query.get_or_404(formation_id)
|
||||||
formation = models.Formation.query.filter_by(id=formation_id).first_or_404()
|
return jsonify(formation.to_dict())
|
||||||
|
|
||||||
# Mise en forme des données
|
|
||||||
data = formation.to_dict()
|
|
||||||
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
@ -187,10 +182,8 @@ def formation_export_by_formation_id(formation_id: int, export_ids=False):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
formation = Formation.query.get_or_404(formation_id)
|
formation = Formation.query.get_or_404(formation_id)
|
||||||
dept = models.Departement.query.filter_by(id=formation.dept_id).first()
|
app.set_sco_dept(formation.departement.acronym)
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
try:
|
try:
|
||||||
# Utilisation de la fonction formation_export
|
|
||||||
data = sco_formations.formation_export(formation_id, export_ids)
|
data = sco_formations.formation_export(formation_id, export_ids)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return error_response(500, message="Erreur inconnue")
|
return error_response(500, message="Erreur inconnue")
|
||||||
@ -236,9 +229,8 @@ def moduleimpl(moduleimpl_id: int):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
modimpl = models.ModuleImpl.query.filter_by(id=moduleimpl_id).first_or_404()
|
modimpl = models.ModuleImpl.query.get_or_404(moduleimpl_id)
|
||||||
data = modimpl.to_dict()
|
return jsonify(modimpl.to_dict())
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
@ -253,10 +245,9 @@ def referentiel_competences(formation_id: int):
|
|||||||
|
|
||||||
formation_id : l'id d'une formation
|
formation_id : l'id d'une formation
|
||||||
|
|
||||||
return json, ou null si pas de référentiel associé.
|
return null si pas de référentiel associé.
|
||||||
"""
|
"""
|
||||||
formation = models.Formation.query.filter_by(id=formation_id).first_or_404()
|
formation = models.Formation.query.get_or_404(formation_id)
|
||||||
|
|
||||||
if formation.referentiel_competence is None:
|
if formation.referentiel_competence is None:
|
||||||
return jsonify(None)
|
return jsonify(None)
|
||||||
return jsonify(formation.referentiel_competence.to_dict())
|
return jsonify(formation.referentiel_competence.to_dict())
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
########################################## Formsemestres ##############################################################
|
##############################################################################
|
||||||
import statistics
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : accès aux formsemestres
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
@ -7,11 +14,10 @@ import app
|
|||||||
from app import models
|
from app import models
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.api.errors import error_response
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.moy_mod import ModuleImplResults
|
from app.comp.moy_mod import ModuleImplResults
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import Departement, FormSemestre, FormSemestreEtape, ModuleImpl
|
from app.models import Evaluation, FormSemestre, FormSemestreEtape, ModuleImpl
|
||||||
from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json
|
from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json
|
||||||
from app.scodoc.sco_groups import get_etud_groups
|
from app.scodoc.sco_groups import get_etud_groups
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
@ -22,7 +28,7 @@ import app.scodoc.sco_utils as scu
|
|||||||
@bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"])
|
@bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"])
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def formsemestre(formsemestre_id: int):
|
def formsemestre_infos(formsemestre_id: int):
|
||||||
"""
|
"""
|
||||||
Information sur le formsemestre indiqué.
|
Information sur le formsemestre indiqué.
|
||||||
|
|
||||||
@ -59,17 +65,8 @@ def formsemestre(formsemestre_id: int):
|
|||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
|
formsemestre: FormSemestre = models.FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
id=formsemestre_id
|
return jsonify(formsemestre.to_dict_api())
|
||||||
).first_or_404()
|
|
||||||
data = formsemestre.to_dict(convert_parcours=True)
|
|
||||||
# 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["annee_scolaire"] = formsemestre.annee_scolaire_str()
|
|
||||||
data["session_id"] = formsemestre.session_id()
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/apo/<string:etape_apo>", methods=["GET"])
|
@bp.route("/formsemestre/apo/<string:etape_apo>", methods=["GET"])
|
||||||
@ -92,9 +89,7 @@ def formsemestre_apo(etape_apo: str):
|
|||||||
FormSemestreEtape.formsemestre_id == FormSemestre.id,
|
FormSemestreEtape.formsemestre_id == FormSemestre.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify([formsemestre.to_dict_api() for formsemestre in formsemestres])
|
||||||
[formsemestre.to_dict(convert_parcours=True) for formsemestre in formsemestres]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
|
@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
|
||||||
@ -106,183 +101,10 @@ def bulletins(formsemestre_id: int):
|
|||||||
|
|
||||||
formsemestre_id : l'id d'un formesemestre
|
formsemestre_id : l'id d'un formesemestre
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat : liste, voir https://scodoc.org/ScoDoc9API/#bulletin
|
||||||
[
|
|
||||||
{
|
|
||||||
"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&T",
|
|
||||||
"titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
|
|
||||||
"titre": "BUT R&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'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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"""
|
"""
|
||||||
formsemestre = models.FormSemestre.query.filter_by(
|
formsemestre = models.FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
id=formsemestre_id
|
app.set_sco_dept(formsemestre.departement.acronym)
|
||||||
).first_or_404()
|
|
||||||
dept = models.Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for etu in formsemestre.etuds:
|
for etu in formsemestre.etuds:
|
||||||
@ -292,44 +114,6 @@ def bulletins(formsemestre_id: int):
|
|||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
# XXX Attendre ScoDoc 9.3
|
|
||||||
# @bp.route("/formsemestre/<int:formsemestre_id>/jury", methods=["GET"])
|
|
||||||
# @token_auth.login_required
|
|
||||||
# @token_permission_required(Permission.APIView)
|
|
||||||
# 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()
|
|
||||||
|
|
||||||
# formsemestre = models.FormSemestre.query.filter_by(
|
|
||||||
# id=formsemestre_id
|
|
||||||
# ).first_or_404()
|
|
||||||
|
|
||||||
# dept = models.Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
|
|
||||||
|
|
||||||
# app.set_sco_dept(dept.acronym)
|
|
||||||
|
|
||||||
# data = formsemestre_pvjury(formsemestre_id)
|
|
||||||
|
|
||||||
# # try:
|
|
||||||
# # # Utilisation de la fonction formsemestre_pvjury
|
|
||||||
# # data = formsemestre_pvjury(formsemestre_id)
|
|
||||||
# # except AttributeError:
|
|
||||||
# # 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 jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formsemestre/<int:formsemestre_id>/programme",
|
"/formsemestre/<int:formsemestre_id>/programme",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
@ -401,10 +185,7 @@ def formsemestre_programme(formsemestre_id: int):
|
|||||||
"modules" : [ ... les modules qui ne sont ni des SAEs ni des ressources ... ]
|
"modules" : [ ... les modules qui ne sont ni des SAEs ni des ressources ... ]
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
|
formsemestre: FormSemestre = models.FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
id=formsemestre_id
|
|
||||||
).first_or_404()
|
|
||||||
|
|
||||||
ues = formsemestre.query_ues()
|
ues = formsemestre.query_ues()
|
||||||
m_list = {
|
m_list = {
|
||||||
ModuleType.RESSOURCE: [],
|
ModuleType.RESSOURCE: [],
|
||||||
@ -428,48 +209,37 @@ def formsemestre_programme(formsemestre_id: int):
|
|||||||
@bp.route(
|
@bp.route(
|
||||||
"/formsemestre/<int:formsemestre_id>/etudiants",
|
"/formsemestre/<int:formsemestre_id>/etudiants",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"etat": "I"},
|
defaults={"etat": scu.INSCRIT},
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formsemestre/<int:formsemestre_id>/etudiants/demissionnaires",
|
"/formsemestre/<int:formsemestre_id>/etudiants/demissionnaires",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"etat": "D"},
|
defaults={"etat": scu.DEMISSION},
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formsemestre/<int:formsemestre_id>/etudiants/defaillants",
|
"/formsemestre/<int:formsemestre_id>/etudiants/defaillants",
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
defaults={"etat": "DEF"},
|
defaults={"etat": scu.DEF},
|
||||||
)
|
)
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def formsemestre_etudiants(formsemestre_id: int, etat: str):
|
def formsemestre_etudiants(formsemestre_id: int, etat: str):
|
||||||
"""
|
"""
|
||||||
Retourne la liste des étudiants d'un semestre
|
Retourne la liste des étudiants d'un formsemestre
|
||||||
|
|
||||||
formsemestre_id : l'id d'un semestre
|
formsemestre_id : l'id d'un formsemestre
|
||||||
"""
|
"""
|
||||||
# fonction to use : sco_groups.get_etud_groups
|
formsemestre: FormSemestre = models.FormSemestre.query.filter_by(
|
||||||
|
|
||||||
formsemestre = models.FormSemestre.query.filter_by(
|
|
||||||
id=formsemestre_id
|
id=formsemestre_id
|
||||||
).first_or_404()
|
).first_or_404()
|
||||||
|
|
||||||
# Récupération des étudiants du formsemestre
|
inscriptions = [ins for ins in formsemestre.inscriptions if ins.etat == etat]
|
||||||
etuds = [etu.to_dict_short() for etu in formsemestre.etuds]
|
etuds = [ins.etud.to_dict_short() for ins in inscriptions]
|
||||||
|
# Ajout des groupes de chaque étudiants
|
||||||
|
for etud in etuds:
|
||||||
|
etud["groups"] = get_etud_groups(etud["id"], formsemestre_id)
|
||||||
|
|
||||||
res = []
|
return jsonify(etuds)
|
||||||
# Trie des étudiants suivant leur état d'inscription voulu
|
|
||||||
for etu in etuds:
|
|
||||||
formsemestre_inscription = models.FormSemestreInscription.query.filter_by(
|
|
||||||
formsemestre_id=formsemestre_id, etudid=etu["id"]
|
|
||||||
).first_or_404()
|
|
||||||
if formsemestre_inscription.etat == etat:
|
|
||||||
res.append(etu)
|
|
||||||
# Ajout des groups de chaques étudiants
|
|
||||||
for etu in res:
|
|
||||||
etu["groups"] = get_etud_groups(etu["id"], formsemestre_id)
|
|
||||||
|
|
||||||
return jsonify(res)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/<int:formsemestre_id>/etat_evals", methods=["GET"])
|
@bp.route("/formsemestre/<int:formsemestre_id>/etat_evals", methods=["GET"])
|
||||||
@ -477,154 +247,103 @@ def formsemestre_etudiants(formsemestre_id: int, etat: str):
|
|||||||
@token_permission_required(Permission.APIView)
|
@token_permission_required(Permission.APIView)
|
||||||
def etat_evals(formsemestre_id: int):
|
def etat_evals(formsemestre_id: int):
|
||||||
"""
|
"""
|
||||||
Retourne les informations sur l'état des évaluations d'un semestre donnée
|
Informations sur l'état des évaluations d'un formsemestre.
|
||||||
|
|
||||||
formsemestre_id : l'id d'un semestre
|
formsemestre_id : l'id d'un semestre
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
{
|
[
|
||||||
"RT1.1": [
|
{
|
||||||
{
|
"id": 1, // moduleimpl_id
|
||||||
"id": 1,
|
"titre": "Initiation aux réseaux informatiques",
|
||||||
"titre": "Initiation aux réseaux informatiques",
|
"evaluations": [
|
||||||
"evaluations": [
|
{
|
||||||
{
|
"id": 1,
|
||||||
"id": 1,
|
"description": null,
|
||||||
"description": null,
|
"datetime_epreuve": null,
|
||||||
"datetime_epreuve": null,
|
"heure_fin": "09:00:00",
|
||||||
"heure_fin": "09:00:00",
|
"coefficient": "02.00"
|
||||||
"coefficient": "02.00"
|
"is_complete": true,
|
||||||
"comptee": "oui",
|
"nb_inscrits": 16,
|
||||||
"inscrits": 16,
|
"nb_manquantes": 0,
|
||||||
"manquantes": 0,
|
"ABS": 0,
|
||||||
"ABS": 0,
|
"ATT": 0,
|
||||||
"ATT": 0,
|
"EXC": 0,
|
||||||
"EXC": 0,
|
"saisie_notes": {
|
||||||
"saisie_notes": {
|
"datetime_debut": "2021-09-11T00:00:00+02:00",
|
||||||
"datetime_debut": "2021-09-11T00:00:00+02:00",
|
"datetime_fin": "2022-08-25T00:00:00+02:00",
|
||||||
"datetime_fin": "2022-08-25T00:00:00+02:00",
|
"datetime_mediane": "2022-03-19T00:00:00+01:00"
|
||||||
"datetime_mediane": "2022-03-19T00:00:00+01:00"
|
}
|
||||||
}
|
},
|
||||||
},
|
...
|
||||||
{
|
]
|
||||||
"id": 22,
|
},
|
||||||
"description": null,
|
]
|
||||||
"datetime_epreuve": "Tue, 31 May 2022 00:00:00 GMT",
|
|
||||||
"heure_fin": "08:00:00",
|
|
||||||
"comptee": "oui",
|
|
||||||
"inscrits": 16,
|
|
||||||
"manquantes": 0,
|
|
||||||
"ABS": 0,
|
|
||||||
"ATT": 0,
|
|
||||||
"EXC": 0,
|
|
||||||
"saisie_notes": {
|
|
||||||
"datetime_debut": "2021-09-11T00:00:00+02:00",
|
|
||||||
"datetime_fin": "2022-08-25T00:00:00+02:00",
|
|
||||||
"datetime_mediane": "2022-03-19T00:00:00+01:00"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
# Récupération du semestre
|
|
||||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
app.set_sco_dept(formsemestre.departement.acronym)
|
||||||
# Set du dept
|
|
||||||
dept = Departement.query.get(formsemestre.dept_id)
|
|
||||||
app.set_sco_dept(dept.acronym)
|
|
||||||
|
|
||||||
# Récupération des Ues
|
|
||||||
list_ues = formsemestre.query_ues()
|
|
||||||
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
|
||||||
ues = {}
|
result = []
|
||||||
|
for modimpl_id in nt.modimpls_results:
|
||||||
|
modimpl_results: ModuleImplResults = nt.modimpls_results[modimpl_id]
|
||||||
|
modimpl = ModuleImpl.query.get_or_404(modimpl_id)
|
||||||
|
modimpl_dict = modimpl.to_dict()
|
||||||
|
|
||||||
for ue in list_ues:
|
list_eval = []
|
||||||
modules = []
|
for evaluation_id in modimpl_results.evaluations_etat:
|
||||||
mods = ue.modules
|
eval_etat = modimpl_results.evaluations_etat[evaluation_id]
|
||||||
|
evaluation = Evaluation.query.get_or_404(evaluation_id)
|
||||||
|
eval_dict = evaluation.to_dict()
|
||||||
|
eval_dict["etat"] = eval_etat.to_dict()
|
||||||
|
|
||||||
for mod in mods:
|
eval_dict["nb_inscrits"] = modimpl_results.nb_inscrits_module
|
||||||
dict_module = {}
|
eval_dict["nb_notes_manquantes"] = len(
|
||||||
moduleimpl = ModuleImpl.query.get_or_404(mod.id)
|
modimpl_results.evals_etudids_sans_note[evaluation.id]
|
||||||
|
)
|
||||||
|
eval_dict["nb_notes_abs"] = sum(
|
||||||
|
modimpl_results.evals_notes[evaluation.id] == scu.NOTES_ABSENCE
|
||||||
|
)
|
||||||
|
eval_dict["nb_notes_att"] = eval_etat.nb_attente
|
||||||
|
eval_dict["nb_notes_exc"] = sum(
|
||||||
|
modimpl_results.evals_notes[evaluation.id] == scu.NOTES_NEUTRALISE
|
||||||
|
)
|
||||||
|
|
||||||
modimpl_results: ModuleImplResults = nt.modimpls_results[moduleimpl.id]
|
# Récupération de toutes les notes de l'évaluation
|
||||||
|
# eval["notes"] = modimpl_results.get_eval_notes_dict(evaluation_id)
|
||||||
|
|
||||||
dict_module["id"] = mod.id
|
notes = models.NotesNotes.query.filter_by(evaluation_id=evaluation.id).all()
|
||||||
dict_module["titre"] = mod.titre
|
|
||||||
|
|
||||||
list_eval = []
|
date_debut = None
|
||||||
for evaluation in moduleimpl.evaluations:
|
date_fin = None
|
||||||
eval_etat = modimpl_results.evaluations_etat[evaluation.id]
|
date_mediane = None
|
||||||
eval = {}
|
|
||||||
|
|
||||||
eval["id"] = evaluation.id
|
# Si il y a plus d'une note saisie pour l'évaluation
|
||||||
eval["description"] = evaluation.description
|
if len(notes) >= 1:
|
||||||
eval["datetime_epreuve"] = (
|
# Trie des notes en fonction de leurs dates
|
||||||
evaluation.jour.isoformat() if evaluation.jour is not None else None
|
notes_sorted = sorted(notes, key=lambda note: note.date)
|
||||||
)
|
|
||||||
eval["heure_fin"] = evaluation.heure_fin.isoformat()
|
|
||||||
eval["coefficient"] = evaluation.coefficient
|
|
||||||
eval["comptee"] = "oui" if eval_etat.is_complete else "non"
|
|
||||||
eval["inscrits"] = modimpl_results.nb_inscrits_module
|
|
||||||
eval["manquantes"] = len(
|
|
||||||
modimpl_results.evals_etudids_sans_note[evaluation.id]
|
|
||||||
)
|
|
||||||
eval["ABS"] = sum(
|
|
||||||
modimpl_results.evals_notes[evaluation.id] == scu.NOTES_ABSENCE
|
|
||||||
)
|
|
||||||
eval["ATT"] = eval_etat.nb_attente
|
|
||||||
eval["EXC"] = sum(
|
|
||||||
modimpl_results.evals_notes[evaluation.id] == scu.NOTES_NEUTRALISE
|
|
||||||
)
|
|
||||||
|
|
||||||
# Récupération de toutes les notes de l'évaluation
|
date_debut = notes_sorted[0].date
|
||||||
notes = models.NotesNotes.query.filter_by(
|
date_fin = notes_sorted[-1].date
|
||||||
evaluation_id=evaluation.id
|
|
||||||
).all()
|
|
||||||
|
|
||||||
date_debut = None
|
# Récupération de l'id de la note médiane
|
||||||
date_fin = None
|
list_id_notes_sorted = [note.id for note in notes_sorted]
|
||||||
date_mediane = None
|
id_mediane = list_id_notes_sorted[len(list_id_notes_sorted) // 2]
|
||||||
|
date_mediane = notes_sorted[id_mediane].date
|
||||||
|
|
||||||
# Si il y a plus d'une note saisie pour l'évaluation
|
eval_dict["saisie_notes"] = {
|
||||||
if len(notes) >= 1:
|
"datetime_debut": date_debut.isoformat()
|
||||||
# Trie des notes en fonction de leurs dates
|
if date_debut is not None
|
||||||
notes_sorted = sorted(notes, key=lambda note: note.date)
|
else None,
|
||||||
|
"datetime_fin": date_fin.isoformat() if date_fin is not None else None,
|
||||||
|
"datetime_mediane": date_mediane.isoformat()
|
||||||
|
if date_mediane is not None
|
||||||
|
else None,
|
||||||
|
}
|
||||||
|
|
||||||
date_debut = notes_sorted[0].date
|
list_eval.append(eval)
|
||||||
date_fin = notes_sorted[-1].date
|
|
||||||
|
|
||||||
# Récupération de l'id de la note médiane
|
modimpl_dict["evaluations"] = list_eval
|
||||||
list_id_notes_sorted = [note.id for note in notes_sorted]
|
result.append(modimpl_dict)
|
||||||
|
|
||||||
# Ici si la longueur est paire on prend, on prend le +1 car un indice ne peux pas avoir de nombre floatant
|
return jsonify(result)
|
||||||
id_mediane = list_id_notes_sorted[
|
|
||||||
int((len(list_id_notes_sorted)) / 2)
|
|
||||||
]
|
|
||||||
|
|
||||||
for n in notes_sorted:
|
|
||||||
if n.id == id_mediane:
|
|
||||||
date_mediane = n.date
|
|
||||||
|
|
||||||
eval["saisie_notes"] = {
|
|
||||||
"datetime_debut": date_debut.isoformat()
|
|
||||||
if date_debut is not None
|
|
||||||
else None,
|
|
||||||
"datetime_fin": date_fin.isoformat()
|
|
||||||
if date_fin is not None
|
|
||||||
else None,
|
|
||||||
"datetime_mediane": date_mediane.isoformat()
|
|
||||||
if date_mediane is not None
|
|
||||||
else None,
|
|
||||||
}
|
|
||||||
|
|
||||||
list_eval.append(eval)
|
|
||||||
|
|
||||||
dict_module["evaluations"] = list_eval
|
|
||||||
modules.append(dict_module)
|
|
||||||
ues[ue.acronyme] = modules
|
|
||||||
|
|
||||||
return jsonify(ues)
|
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
############################################### Partitions ############################################################
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
ScoDoc 9 API : partitions
|
||||||
|
"""
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
|
|
||||||
from app import models
|
|
||||||
from app.api import bp
|
from app.api import bp
|
||||||
|
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.api.auth import token_auth, token_permission_required
|
from app.api.auth import token_auth, token_permission_required
|
||||||
from app.scodoc.sco_groups import get_group_members, setGroups, get_partitions_list
|
from app.models import FormSemestre, FormSemestreInscription, Identite
|
||||||
|
from app.models import GroupDescr, Partition
|
||||||
|
from app.models.groups import group_membership
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
|
||||||
|
|
||||||
@ -41,15 +50,8 @@ def partition(formsemestre_id: int):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
# # Récupération de toutes les partitions
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
# partitions = models.Partition.query.filter_by(id=formsemestre_id)
|
return jsonify([partition.to_dict() for partition in formsemestre.partitions])
|
||||||
#
|
|
||||||
# # Mise en forme des données
|
|
||||||
# data = [partition.to_dict() for partition in partitions]
|
|
||||||
|
|
||||||
data = get_partitions_list(formsemestre_id)
|
|
||||||
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/partition/group/<int:group_id>", methods=["GET"])
|
@bp.route("/partition/group/<int:group_id>", methods=["GET"])
|
||||||
@ -64,58 +66,32 @@ def etud_in_group(group_id: int, etat=None):
|
|||||||
etat : état de l'inscription
|
etat : état de l'inscription
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"etudid": 10,
|
'civilite': 'M',
|
||||||
"id": 10,
|
'id': 123456,
|
||||||
"dept_id": 1,
|
'ine': None,
|
||||||
"nom": "BOUTET",
|
'nip': '987654321',
|
||||||
"prenom": "Marguerite",
|
'nom': 'MARTIN',
|
||||||
"nom_usuel": "",
|
'nom_usuel': null,
|
||||||
"civilite": "F",
|
'prenom': 'JEAN'}
|
||||||
"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()
|
# Fonction utilisée : app.scodoc.sco_groups.get_group_members()
|
||||||
|
group = GroupDescr.query.get_or_404(group_id)
|
||||||
if etat is None:
|
if etat is None:
|
||||||
data = get_group_members(group_id)
|
query = group.etuds
|
||||||
else:
|
else:
|
||||||
data = get_group_members(group_id, etat)
|
query = (
|
||||||
|
Identite.query.join(FormSemestreInscription)
|
||||||
|
.filter_by(formsemestre_id=group.partition.formsemestre_id, etat=etat)
|
||||||
|
.join(group_membership)
|
||||||
|
.filter_by(group_id=group_id)
|
||||||
|
)
|
||||||
|
|
||||||
if len(data) == 0:
|
return jsonify([etud.to_dict_short() for etud in query])
|
||||||
return error_response(404, message="group_id inconnu")
|
|
||||||
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
"""ScoDoc 9 API : outils
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
from app import models
|
from app import models
|
||||||
|
|
||||||
from app.api.errors import error_response
|
from app.api.errors import error_response
|
||||||
from app.models import Identite
|
from app.models import Identite, Admission
|
||||||
|
|
||||||
|
|
||||||
def get_last_instance_etud_from_etudid_or_nip_or_ine(
|
def get_etud(etudid=None, nip=None, ine=None) -> models.Identite:
|
||||||
etudid=None, nip=None, ine=None
|
|
||||||
) -> models.Identite:
|
|
||||||
"""
|
"""
|
||||||
Retourne l'instance de l'etudiant la plus récente en fonction de l'etudid, code nip et code ine rentré en paramètres
|
L'instance d'étudiant la plus récente en fonction de l'etudid,
|
||||||
|
ou du code nip ou code ine.
|
||||||
|
|
||||||
etudid : None ou un int etudid
|
etudid : None ou un int etudid
|
||||||
nip : None ou un int code_nip
|
nip : None ou un int code_nip
|
||||||
@ -17,26 +25,15 @@ def get_last_instance_etud_from_etudid_or_nip_or_ine(
|
|||||||
Return None si étudiant inexistant.
|
Return None si étudiant inexistant.
|
||||||
"""
|
"""
|
||||||
if etudid is not None:
|
if etudid is not None:
|
||||||
etud = Identite.query.get(etudid)
|
return Identite.query.get(etudid)
|
||||||
|
|
||||||
|
if nip is not None:
|
||||||
|
query = Identite.query.filter_by(code_nip=nip)
|
||||||
|
elif ine is not None:
|
||||||
|
query = Identite.query.filter_by(code_ine=ine)
|
||||||
else:
|
else:
|
||||||
if nip is not None:
|
return error_response(
|
||||||
query = Identite.query.filter_by(code_nip=nip)
|
404,
|
||||||
elif ine is not None:
|
message="parametre manquant",
|
||||||
query = Identite.query.filter_by(code_ine=ine)
|
)
|
||||||
else:
|
return query.join(Admission).order_by(desc(Admission.annee)).first()
|
||||||
return error_response(
|
|
||||||
404,
|
|
||||||
message="parametre manquant",
|
|
||||||
)
|
|
||||||
if query.count() > 1: # cas rare d'un étudiant présent dans plusieurs depts
|
|
||||||
etuds = []
|
|
||||||
for e in query:
|
|
||||||
admission = e.admission.first()
|
|
||||||
etuds.append((((admission.annee or 0) if admission else 0), e))
|
|
||||||
etuds.sort()
|
|
||||||
etud = etuds[-1][1]
|
|
||||||
else:
|
|
||||||
etud = query.first()
|
|
||||||
|
|
||||||
return etud
|
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ Rappel: pour éviter les confusions, on appelera *poids* les coefficients d'une
|
|||||||
évaluation dans un module, et *coefficients* ceux utilisés pour le calcul de la
|
évaluation dans un module, et *coefficients* ceux utilisés pour le calcul de la
|
||||||
moyenne générale d'une UE.
|
moyenne générale d'une UE.
|
||||||
"""
|
"""
|
||||||
|
import dataclasses
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -54,6 +55,10 @@ class EvaluationEtat:
|
|||||||
nb_attente: int
|
nb_attente: int
|
||||||
is_complete: bool
|
is_complete: bool
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"convert to dict"
|
||||||
|
return dataclasses.asdict(self)
|
||||||
|
|
||||||
|
|
||||||
class ModuleImplResults:
|
class ModuleImplResults:
|
||||||
"""Classe commune à toutes les formations (standard et APC).
|
"""Classe commune à toutes les formations (standard et APC).
|
||||||
@ -236,6 +241,16 @@ class ModuleImplResults:
|
|||||||
self.evals_notes.values > scu.NOTES_ABSENCE, self.evals_notes.values, 0.0
|
self.evals_notes.values > scu.NOTES_ABSENCE, self.evals_notes.values, 0.0
|
||||||
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
||||||
|
|
||||||
|
def get_eval_notes_dict(self, evaluation_id: int) -> dict:
|
||||||
|
"""Notes d'une évaulation, brutes, sous forme d'un dict
|
||||||
|
{ etudid : valeur }
|
||||||
|
avec les valeurs float, ou "ABS" ou EXC
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
etudid: scu.fmt_note(x, keep_numeric=True)
|
||||||
|
for (etudid, x) in self.evals_notes[evaluation_id].items()
|
||||||
|
}
|
||||||
|
|
||||||
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl):
|
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl):
|
||||||
"""L'évaluation de rattrapage de ce module, ou None s'il n'en a pas.
|
"""L'évaluation de rattrapage de ce module, ou None s'il n'en a pas.
|
||||||
Rattrapage: la moyenne du module est la meilleure note entre moyenne
|
Rattrapage: la moyenne du module est la meilleure note entre moyenne
|
||||||
|
@ -29,15 +29,6 @@ class Absence(db.Model):
|
|||||||
# XXX TODO: contrainte ajoutée: vérifier suppression du module
|
# XXX TODO: contrainte ajoutée: vérifier suppression du module
|
||||||
# (mettre à NULL sans supprimer)
|
# (mettre à NULL sans supprimer)
|
||||||
|
|
||||||
def __init__(self, id, etudid, jour, estabs, estjust, matin, description):
|
|
||||||
self.id = id
|
|
||||||
self.etudid = etudid
|
|
||||||
self.jour = jour
|
|
||||||
self.estabs = estabs
|
|
||||||
self.estjust = estjust
|
|
||||||
self.matin = matin
|
|
||||||
self.description = description
|
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
data = {
|
data = {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
|
@ -83,40 +83,6 @@ class ApcReferentielCompetences(db.Model, XMLModel):
|
|||||||
)
|
)
|
||||||
formations = db.relationship("Formation", backref="referentiel_competence")
|
formations = db.relationship("Formation", backref="referentiel_competence")
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
id,
|
|
||||||
dept_id,
|
|
||||||
annexe,
|
|
||||||
specialite,
|
|
||||||
specialite_long,
|
|
||||||
type_titre,
|
|
||||||
type_structure,
|
|
||||||
type_departement,
|
|
||||||
version_orebut,
|
|
||||||
_xml_attribs,
|
|
||||||
#scodoc_date_loaded,
|
|
||||||
scodoc_orig_filename,
|
|
||||||
# competences,
|
|
||||||
# parcours,
|
|
||||||
# formations,
|
|
||||||
):
|
|
||||||
self.id = id
|
|
||||||
self.dept_id = dept_id
|
|
||||||
self.annexe = annexe
|
|
||||||
self.specialite = specialite
|
|
||||||
self.specialite_long = specialite_long
|
|
||||||
self.type_titre = type_titre
|
|
||||||
self.type_structure = type_structure
|
|
||||||
self.type_departement = type_departement
|
|
||||||
self.version_orebut = version_orebut
|
|
||||||
self._xml_attribs = _xml_attribs
|
|
||||||
#self.scodoc_date_loaded = scodoc_date_loaded
|
|
||||||
self.scodoc_orig_filename = scodoc_orig_filename
|
|
||||||
# self.competences = competences
|
|
||||||
# self.parcours = parcours
|
|
||||||
# self.formations = formations
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<ApcReferentielCompetences {self.id} {self.specialite!r} {self.departement!r}>"
|
return f"<ApcReferentielCompetences {self.id} {self.specialite!r} {self.departement!r}>"
|
||||||
|
|
||||||
@ -225,32 +191,6 @@ class ApcCompetence(db.Model, XMLModel):
|
|||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
id,
|
|
||||||
referentiel_id,
|
|
||||||
id_orebut,
|
|
||||||
titre,
|
|
||||||
titre_long,
|
|
||||||
couleur,
|
|
||||||
numero,
|
|
||||||
_xml_attribs,
|
|
||||||
situations,
|
|
||||||
composantes_essentielles,
|
|
||||||
niveaux,
|
|
||||||
):
|
|
||||||
self.id = id
|
|
||||||
self.referentiel_id = referentiel_id
|
|
||||||
self.id_orebut = id_orebut
|
|
||||||
self.titre = titre
|
|
||||||
self.titre_long = titre_long
|
|
||||||
self.couleur = couleur
|
|
||||||
self.numero = numero
|
|
||||||
self._xml_attribs = _xml_attribs
|
|
||||||
self.situations = situations
|
|
||||||
self.composantes_essentielles = composantes_essentielles
|
|
||||||
self.niveaux = niveaux
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<ApcCompetence {self.id} {self.titre!r}>"
|
return f"<ApcCompetence {self.id} {self.titre!r}>"
|
||||||
|
|
||||||
@ -288,12 +228,6 @@ class ApcSituationPro(db.Model, XMLModel):
|
|||||||
)
|
)
|
||||||
libelle = db.Column(db.Text(), nullable=False)
|
libelle = db.Column(db.Text(), nullable=False)
|
||||||
# aucun attribut (le text devient le libellé)
|
# aucun attribut (le text devient le libellé)
|
||||||
|
|
||||||
def __init__(self, id, competence_id, libelle):
|
|
||||||
self.id = id
|
|
||||||
self.competence_id = competence_id
|
|
||||||
self.libelle = libelle
|
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {"libelle": self.libelle}
|
return {"libelle": self.libelle}
|
||||||
|
|
||||||
@ -306,11 +240,6 @@ class ApcComposanteEssentielle(db.Model, XMLModel):
|
|||||||
)
|
)
|
||||||
libelle = db.Column(db.Text(), nullable=False)
|
libelle = db.Column(db.Text(), nullable=False)
|
||||||
|
|
||||||
def __init__(self, id, competence_id, libelle):
|
|
||||||
self.id = id
|
|
||||||
self.competence_id = competence_id
|
|
||||||
self.libelle = libelle
|
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {"libelle": self.libelle}
|
return {"libelle": self.libelle}
|
||||||
|
|
||||||
@ -339,14 +268,6 @@ class ApcNiveau(db.Model, XMLModel):
|
|||||||
)
|
)
|
||||||
ues = db.relationship("UniteEns", back_populates="niveau_competence")
|
ues = db.relationship("UniteEns", back_populates="niveau_competence")
|
||||||
|
|
||||||
def __init__(self, id, competence_id, libelle, annee, ordre, app_critiques):
|
|
||||||
self.id = id
|
|
||||||
self.competence_id = competence_id
|
|
||||||
self.libelle = libelle
|
|
||||||
self.annee = annee
|
|
||||||
self.ordre = ordre
|
|
||||||
self.app_critiques = app_critiques
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"""<{self.__class__.__name__} {self.id} ordre={self.ordre!r} annee={
|
return f"""<{self.__class__.__name__} {self.id} ordre={self.ordre!r} annee={
|
||||||
self.annee!r} {self.competence!r}>"""
|
self.annee!r} {self.competence!r}>"""
|
||||||
@ -452,13 +373,6 @@ class ApcAppCritique(db.Model, XMLModel):
|
|||||||
query = query.filter(ApcNiveau.competence == competence)
|
query = query.filter(ApcNiveau.competence == competence)
|
||||||
return query
|
return query
|
||||||
|
|
||||||
def __init__(self, id, niveau_id, code, libelle, modules):
|
|
||||||
self.id = id
|
|
||||||
self.niveau_id = niveau_id
|
|
||||||
self.code = code
|
|
||||||
self.libelle = libelle
|
|
||||||
self.modules = modules
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {"libelle": self.libelle}
|
return {"libelle": self.libelle}
|
||||||
|
|
||||||
@ -517,14 +431,6 @@ class ApcParcours(db.Model, XMLModel):
|
|||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, id, referentiel_id, numero, code, libelle, annes):
|
|
||||||
self.id = id
|
|
||||||
self.referentiel_id = referentiel_id
|
|
||||||
self.numero = numero
|
|
||||||
self.code = code
|
|
||||||
self.libelle = libelle
|
|
||||||
self.annes = annes
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} {self.id} {self.code!r} ref={self.referentiel}>"
|
return f"<{self.__class__.__name__} {self.id} {self.code!r} ref={self.referentiel}>"
|
||||||
|
|
||||||
@ -545,11 +451,6 @@ class ApcAnneeParcours(db.Model, XMLModel):
|
|||||||
ordre = db.Column(db.Integer)
|
ordre = db.Column(db.Integer)
|
||||||
"numéro de l'année: 1, 2, 3"
|
"numéro de l'année: 1, 2, 3"
|
||||||
|
|
||||||
def __init__(self, id, parcours_id, ordre):
|
|
||||||
self.id = id
|
|
||||||
self.parcours_id = parcours_id
|
|
||||||
self.ordre = ordre
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} {self.id} ordre={self.ordre!r} parcours={self.parcours.code!r}>"
|
return f"<{self.__class__.__name__} {self.id} ordre={self.ordre!r} parcours={self.parcours.code!r}>"
|
||||||
|
|
||||||
|
@ -654,11 +654,6 @@ class FormSemestreEtape(db.Model):
|
|||||||
# etape_apo aurait du etre not null, mais oublié
|
# etape_apo aurait du etre not null, mais oublié
|
||||||
etape_apo = db.Column(db.String(APO_CODE_STR_LEN), index=True)
|
etape_apo = db.Column(db.String(APO_CODE_STR_LEN), index=True)
|
||||||
|
|
||||||
def __init__(self, id, formsemestre_id, etape_apo):
|
|
||||||
self.id = id
|
|
||||||
self.formsemestre_id = formsemestre_id
|
|
||||||
self.etape_apo = etape_apo
|
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
"Etape False if code empty"
|
"Etape False if code empty"
|
||||||
return self.etape_apo is not None and (len(self.etape_apo) > 0)
|
return self.etape_apo is not None and (len(self.etape_apo) > 0)
|
||||||
|
@ -58,12 +58,9 @@ class Partition(db.Model):
|
|||||||
|
|
||||||
def to_dict(self, with_groups=False) -> dict:
|
def to_dict(self, with_groups=False) -> dict:
|
||||||
"""as a dict, with or without groups"""
|
"""as a dict, with or without groups"""
|
||||||
d = {
|
d = dict(self.__dict__)
|
||||||
"id": self.id,
|
d.pop("_sa_instance_state", None)
|
||||||
"formsemestre_id": self.partition_id,
|
|
||||||
"name": self.partition_name,
|
|
||||||
"numero": self.numero,
|
|
||||||
}
|
|
||||||
if with_groups:
|
if with_groups:
|
||||||
d["groups"] = [group.to_dict(with_partition=False) for group in self.groups]
|
d["groups"] = [group.to_dict(with_partition=False) for group in self.groups]
|
||||||
return d
|
return d
|
||||||
|
@ -47,24 +47,11 @@ class NotesNotes(db.Model):
|
|||||||
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
uid = db.Column(db.Integer, db.ForeignKey("user.id"))
|
uid = db.Column(db.Integer, db.ForeignKey("user.id"))
|
||||||
|
|
||||||
def __init__(self, etudid, evaluation_id, value, comment, date, uid):
|
def to_dict(self) -> dict:
|
||||||
self.etudid = etudid
|
"dict"
|
||||||
self.evaluation_id = evaluation_id
|
d = dict(self.__dict__)
|
||||||
self.value = value
|
d.pop("_sa_instance_state", None)
|
||||||
self.comment = comment
|
return d
|
||||||
self.date = date
|
|
||||||
self.uid = uid
|
|
||||||
|
|
||||||
def to_dict(self):
|
|
||||||
return {
|
|
||||||
"id": self.id,
|
|
||||||
"etudid": self.etudid,
|
|
||||||
"evaluation_id": self.evaluation_id,
|
|
||||||
"value": self.value,
|
|
||||||
"comment": self.comment,
|
|
||||||
"date": self.date,
|
|
||||||
"uid": self.uid,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class NotesNotesLog(db.Model):
|
class NotesNotesLog(db.Model):
|
||||||
|
@ -136,7 +136,7 @@ def get_partition(partition_id):
|
|||||||
return r[0]
|
return r[0]
|
||||||
|
|
||||||
|
|
||||||
def get_partitions_list(formsemestre_id, with_default=True):
|
def get_partitions_list(formsemestre_id, with_default=True) -> list[dict]:
|
||||||
"""Liste des partitions pour ce semestre (list of dicts)"""
|
"""Liste des partitions pour ce semestre (list of dicts)"""
|
||||||
partitions = ndb.SimpleDictFetch(
|
partitions = ndb.SimpleDictFetch(
|
||||||
"""SELECT p.id AS partition_id, p.*
|
"""SELECT p.id AS partition_id, p.*
|
||||||
@ -146,9 +146,9 @@ def get_partitions_list(formsemestre_id, with_default=True):
|
|||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
)
|
)
|
||||||
# Move 'all' at end of list (for menus)
|
# Move 'all' at end of list (for menus)
|
||||||
R = [p for p in partitions if p["partition_name"] != None]
|
R = [p for p in partitions if p["partition_name"] is not None]
|
||||||
if with_default:
|
if with_default:
|
||||||
R += [p for p in partitions if p["partition_name"] == None]
|
R += [p for p in partitions if p["partition_name"] is None]
|
||||||
return R
|
return R
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user