1
0
forked from ScoDoc/ScoDoc

API: /formsemestre/<int:formsemestre_id>/decisions_jury

This commit is contained in:
Emmanuel Viennet 2022-08-03 13:32:59 +02:00
parent cdf17873b0
commit 58d84da254
3 changed files with 127 additions and 57 deletions

View File

@ -1,40 +1,35 @@
#################################################### Jury #############################################################
# from flask import jsonify
##############################################################################
# ScoDoc
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
# See LICENSE
##############################################################################
# from app import models
# from app.api import api_bp as bp
# from app.api.errors import error_response
# from app.scodoc.sco_prepajury import feuille_preparation_jury
# from app.scodoc.sco_pvjury import formsemestre_pvjury
"""
ScoDoc 9 API : jury
"""
from flask import g, jsonify, request
from flask_login import login_required
import app
from app import db, log
from app.api import api_bp as bp, api_web_bp
from app.decorators import scodoc, permission_required
from app.api.errors import error_response
from app.but import jury_but_recap
from app.models import FormSemestre, FormSemestreInscription, Identite
from app.scodoc.sco_permissions import Permission
# # @bp.route("/jury/formsemestre/<int:formsemestre_id>/preparation_jury", methods=["GET"])
# # @token_permission_required(Permission.?)
# def jury_preparation(formsemestre_id: int):
# """
# Retourne la feuille de préparation du jury
# formsemestre_id : l'id d'un formsemestre
# """
# # Fonction utilisée : app.scodoc.sco_prepajury.feuille_preparation_jury()
# # Utilisation de la fonction feuille_preparation_jury
# prepa_jury = feuille_preparation_jury(formsemestre_id)
# return error_response(501, message="Not implemented")
# # @bp.route("/jury/formsemestre/<int:formsemestre_id>/decisions_jury", methods=["GET"])
# # @token_permission_required(Permission.?)
# def jury_decisions(formsemestre_id: int):
# """
# Retourne les décisions du jury suivant un formsemestre donné
# formsemestre_id : l'id d'un formsemestre
# """
# # Fonction utilisée : app.scodoc.sco_pvjury.formsemestre_pvjury()
# # Utilisation de la fonction formsemestre_pvjury
# decision_jury = formsemestre_pvjury(formsemestre_id)
# return error_response(501, message="Not implemented")
@bp.route("/formsemestre/<int:formsemestre_id>/decisions_jury")
@api_web_bp.route("/formsemestre/<int:formsemestre_id>/decisions_jury")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def decisions_jury(formsemestre_id: int):
"""Décisions du jury des étudiants du formsemestre."""
# APC, pair:
formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
app.set_sco_dept(formsemestre.departement.acronym)
rows = jury_but_recap.get_jury_but_results(formsemestre)
return jsonify(rows)

View File

@ -21,7 +21,7 @@ from app.comp.res_but import ResultatsSemestreBUT
from app.comp import res_sem
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre
from app.scodoc import html_sco_header
from app.scodoc.sco_codes_parcours import (
BUT_BARRE_RCUE,
BUT_BARRE_UE,
@ -29,7 +29,7 @@ from app.scodoc.sco_codes_parcours import (
BUT_RCUE_SUFFISANT,
)
from app.scodoc import sco_formsemestre_status
from app.scodoc import html_sco_header
from app.scodoc import sco_pvjury
from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import ScoValueError
@ -71,7 +71,7 @@ def formsemestre_saisie_jury_but(
"""
)
rows, titles, column_ids = get_table_jury_but(
rows, titles, column_ids = get_jury_but_table(
formsemestre2, read_only=read_only, mode=mode
)
if not rows:
@ -255,7 +255,9 @@ class RowCollector:
self.column_classes[col_id] = column_class
self.idx += 1
def add_etud_cells(self, etud: Identite, formsemestre: FormSemestre):
def add_etud_cells(
self, etud: Identite, formsemestre: FormSemestre, with_links=True
):
"Les cells code, nom, prénom etc."
# --- Codes (seront cachés, mais exportés en excel)
self.add_cell("etudid", "etudid", etud.id, "codes")
@ -266,16 +268,17 @@ class RowCollector:
self["_nom_disp_order"] = etud.sort_key
self.add_cell("prenom", "Prénom", etud.prenom, "identite_detail")
self.add_cell("nom_short", "Nom", etud.nom_short, "identite_court")
self["_nom_short_order"] = etud.sort_key
self["_nom_short_target"] = url_for(
"notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre.id,
etudid=etud.id,
)
self["_nom_short_target_attrs"] = f'class="etudinfo" id="{etud.id}"'
self["_nom_disp_target"] = self["_nom_short_target"]
self["_nom_disp_target_attrs"] = self["_nom_short_target_attrs"]
if with_links:
self["_nom_short_order"] = etud.sort_key
self["_nom_short_target"] = url_for(
"notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre.id,
etudid=etud.id,
)
self["_nom_short_target_attrs"] = f'class="etudinfo" id="{etud.id}"'
self["_nom_disp_target"] = self["_nom_short_target"]
self["_nom_disp_target_attrs"] = self["_nom_short_target_attrs"]
self.last_etud_cell_idx = self.idx
def add_ue_cells(self, dec_ue: DecisionsProposeesUE):
@ -372,8 +375,8 @@ class RowCollector:
] = f"{deca.nb_validables:04d}-00000-{deca.etud.sort_key}"
def get_table_jury_but(
formsemestre2: FormSemestre, read_only: bool = False, mode="jury"
def get_jury_but_table(
formsemestre2: FormSemestre, read_only: bool = False, mode="jury", with_links=True
) -> tuple[list[dict], list[str], list[str]]:
"""Construit la table des résultats annuels pour le jury BUT"""
res2: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre2)
@ -384,7 +387,7 @@ def get_table_jury_but(
etud: Identite = Identite.query.get(etudid)
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre2)
row = RowCollector(titles=titles, column_classes=column_classes)
row.add_etud_cells(etud, formsemestre2)
row.add_etud_cells(etud, formsemestre2, with_links=with_links)
row.idx = 100 # laisse place pour les colonnes de groupes
# --- Nombre de niveaux
row.add_nb_rcues_cell(deca)
@ -415,7 +418,7 @@ def get_table_jury_but(
"col_code_annee",
)
# --- Le lien de saisie
if mode != "recap":
if mode != "recap" and with_links:
row.add_cell(
"lien_saisie",
"",
@ -441,3 +444,75 @@ def get_table_jury_but(
column_ids.sort(key=lambda col_id: titles.get("_" + col_id + "_col_order", 1000))
rows_dict.sort(key=lambda row: row["_nom_disp_order"])
return rows_dict, titles, column_ids
def get_jury_but_results(formsemestre: FormSemestre) -> list[dict]:
"""Liste des résultats jury BUT sous forme de dict, pour API"""
dpv = sco_pvjury.dict_pvjury(formsemestre.id)
rows = []
for etudid in formsemestre.etuds_inscriptions:
rows.append(get_jury_but_etud_result(formsemestre, dpv, etudid))
return rows
def get_jury_but_etud_result(
formsemestre: FormSemestre, dpv: dict, etudid: int
) -> dict:
"""Résultats de jury d'un étudiant sur un semestre pair de BUT"""
etud: Identite = Identite.query.get(etudid)
dec_etud = dpv["decisions_dict"][etudid]
if formsemestre.formation.is_apc():
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
else:
deca = None
row = {
"etudid": etud.id,
"code_nip": etud.code_nip,
"code_ine": etud.code_ine,
"is_apc": dpv["is_apc"], # BUT ou classic ?
"etat": dec_etud["etat"], # I ou D ou DEF
"nb_competences": deca.nb_competences if deca else 0,
}
# --- Les RCUEs
rcue_list = []
if deca:
for rcue in deca.rcues_annee:
dec_rcue = deca.dec_rcue_by_ue.get(rcue.ue_1.id)
if dec_rcue is not None: # None si l'UE n'est pas associée à un niveau
dec_ue1 = deca.decisions_ues[rcue.ue_1.id]
dec_ue2 = deca.decisions_ues[rcue.ue_2.id]
rcue_dict = {
"ue_1": {
"ue_id": rcue.ue_1.id,
"moy": dec_ue1.moy_ue,
"code": dec_ue1.code_valide,
},
"ue_2": {
"ue_id": rcue.ue_2.id,
"moy": dec_ue2.moy_ue,
"code": dec_ue2.code_valide,
},
"moy": rcue.moy_rcue,
"code": dec_rcue.code_valide,
}
rcue_list.append(rcue_dict)
row["rcues"] = rcue_list
# --- Les UEs
ue_list = []
if dec_etud["decisions_ue"]:
for ue_id, ue_dec in dec_etud["decisions_ue"].items():
ue_dict = {
"ue_id": ue_id,
"code": ue_dec["code"],
"ects": ue_dec["ects"],
}
ue_list.append(ue_dict)
row["ues"] = ue_list
# --- Le semestre (pour les formations classiques)
if dec_etud["decision_sem"]:
row["semestre"] = {"code": dec_etud["decision_sem"].get("code")}
else:
row["semestre"] = {} # APC, ...
# --- Autorisations
row["autorisations"] = dec_etud["autorisations"]
return row

View File

@ -207,7 +207,7 @@ POST_JSON(f"/group/{group_1}/remove_etudiant/{etudid}")
# 6- affecte au groupe G2
partition = GET(f"/partition/{partition_id}")
assert len(partition["groups"]) == 3
group_2 = [g for g in partition["groups"].values() if g["name"] == "G2"][0]["id"]
group_2 = [g for g in partition["groups"].values() if g["group_name"] == "G2"][0]["id"]
POST_JSON(f"/group/{group_2}/set_etudiant/{etudid}")
# 7- Membres du groupe
@ -216,7 +216,7 @@ assert len(etuds_g2) == 1
assert etuds_g2[0]["id"] == etudid
# 8- Ordres des groupes
group_3 = [g for g in partition["groups"].values() if g["name"] == "G3"][0]["id"]
group_3 = [g for g in partition["groups"].values() if g["group_name"] == "G3"][0]["id"]
POST_JSON(
f"/partition/{partition_id}/groups/order",