Jury BUT: calcul auto des décisions

This commit is contained in:
Emmanuel Viennet 2022-06-25 02:59:43 +02:00
parent be3d692202
commit d364d30176
7 changed files with 149 additions and 9 deletions

View File

@ -0,0 +1,18 @@
##############################################################################
# ScoDoc
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
# See LICENSE
##############################################################################
"""ScoDoc 9.3 : Formulaires / jurys BUT
"""
from flask_wtf import FlaskForm
from wtforms import SubmitField
class FormSemestreValidationAutoBUTForm(FlaskForm):
"simple form de confirmation"
submit = SubmitField("Lancer le calcul")
cancel = SubmitField("Annuler")

View File

@ -259,7 +259,8 @@ class DecisionsProposeesAnnee(DecisionsProposees):
)
"le nb de comp. sous la barre de 8/20"
# année ADM si toutes RCUE validées (sinon PASD)
admis = self.nb_validables == self.nb_competences
self.admis = self.nb_validables == self.nb_competences
"vrai si l'année est réussie, tous niveaux validables"
self.valide_moitie_rcue = self.nb_validables > (self.nb_competences // 2)
# Peut passer si plus de la moitié validables et tous > 8
self.passage_de_droit = self.valide_moitie_rcue and (self.nb_rcues_under_8 == 0)
@ -273,7 +274,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
expl_rcues = (
f"{self.nb_validables} niveau validable(s) sur {self.nb_competences}"
)
if admis:
if self.admis:
self.codes = [sco_codes.ADM] + self.codes
self.explanation = expl_rcues
elif self.passage_de_droit:

View File

@ -18,10 +18,8 @@ from app.but.jury_but import (
)
from app.comp.res_but import ResultatsSemestreBUT
from app.comp import res_sem
from app.models.but_validations import RegroupementCoherentUE
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre
from app.models.ues import UniteEns
from app.scodoc.sco_codes_parcours import (
BUT_BARRE_RCUE,
@ -79,8 +77,21 @@ def formsemestre_saisie_jury_but(
formsemestre_id=formsemestre2.id
),
]
H.append(table_html)
H.append(html_sco_header.sco_footer())
H.append(
f"""
{table_html}
<div class="table_jury_but_links">
<p><a class="sdtlink" href="{url_for(
"notes.formsemestre_validation_auto_but",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
}">Calcul automatique des décisions du jury</a></p>
</div>
{html_sco_header.sco_footer()}
"""
)
return "\n".join(H)

View File

@ -0,0 +1,34 @@
##############################################################################
# ScoDoc
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
# See LICENSE
##############################################################################
"""Jury BUT: clacul des décisions de jury annuelles "automatiques"
"""
from flask import g, url_for
from app import db
from app.but import jury_but
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre
from app.scodoc.sco_exceptions import ScoValueError
def formsemestre_validation_auto_but(formsemestre: FormSemestre) -> int:
"""Calcul automatique des décisions de jury sur une année BUT.
Returns: nombre d'étudiants "admis"
"""
if not formsemestre.formation.is_apc():
raise ScoValueError("fonction réservée aux formations BUT")
nb_admis = 0
for etudid in formsemestre.etuds_inscriptions:
etud: Identite = Identite.query.get(etudid)
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
if deca.admis: # année réussie
deca.record_all()
nb_admis += 1
db.session.commit()
return nb_admis

View File

@ -3963,6 +3963,11 @@ table.table_recap td.evaluation.non_inscrit {
color: rgb(101, 101, 101);
}
div.table_jury_but_links {
margin-top: 16px;
margin-bottom: 16px;
}
/* ------------- Tableau etat evals ------------ */
div.evaluations_recap table.evaluations_recap {

View File

@ -0,0 +1,30 @@
{# -*- mode: jinja-html -*- #}
{% extends "sco_page.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block styles %}
{{super()}}
{% endblock %}
{% block app_content %}
<h2>Calcul automatique des décisions de jury annuelle BUT</h2>
<ul>
<li>Seuls les étudiants qui valident l'année seront affectés:
tous les niveaux de compétences (RCUE) validables
(moyenne annuelle au dessus de 10);
</li>
<li>l'assiduité n'est <b>pas</b> prise en compte;</li>
</ul>
<p class="warning">
Il est nécessaire de relire soigneusement les décisions à l'issue de cette procédure !
</p>
<div class="row">
<div class="col-md-5">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}

View File

@ -41,7 +41,8 @@ from flask import abort, flash, jsonify, redirect, render_template, url_for
from flask import current_app, g, request
from flask_login import current_user
from app.but import jury_but
from app.but import jury_but, jury_but_validation_auto
from app.but.forms import jury_but_forms
from app.comp import res_sem
from app.comp.res_but import ResultatsSemestreBUT
from app.comp.res_compat import NotesTableCompat
@ -2224,7 +2225,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
"Form. saisie décision jury semestre BUT"
if not sco_permissions_check.can_validate_sem(formsemestre_id):
return scu.confirm_dialog(
message="<p>Opération non autorisée pour %s</h2>" % current_user,
message=f"<p>Opération non autorisée pour {current_user}</h2>",
dest_url=url_for(
"notes.formsemestre_status",
scodoc_dept=g.scodoc_dept,
@ -2274,7 +2275,8 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
<div class="but_section_annee">
<div>
<b>Décision de jury pour l'année :</b> {
_gen_but_select("code_annee", deca.codes, deca.code_valide, disabled=True, klass="manual")
_gen_but_select("code_annee", deca.codes, deca.code_valide,
disabled=True, klass="manual")
}
<span>({'non ' if deca.code_valide is None else ''}enregistrée)</span>
</div>
@ -2396,6 +2398,45 @@ def _gen_but_niveau_ue(
</div>"""
@bp.route(
"/formsemestre_validation_auto_but/<int:formsemestre_id>", methods=["GET", "POST"]
)
@scodoc
@permission_required(Permission.ScoView)
def formsemestre_validation_auto_but(formsemestre_id: int = None):
"Saisie automatique des décisions de jury BUT"
if not sco_permissions_check.can_validate_sem(formsemestre_id):
return scu.confirm_dialog(
message=f"<p>Opération non autorisée pour {current_user}</h2>",
dest_url=url_for(
"notes.formsemestre_status",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
),
)
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
form = jury_but_forms.FormSemestreValidationAutoBUTForm()
if request.method == "POST":
if not form.cancel.data:
nb_admis = jury_but_validation_auto.formsemestre_validation_auto_but(
formsemestre
)
flash(f"Décisions enregistrées ({nb_admis} admis)")
return redirect(
url_for(
"notes.formsemestre_saisie_jury",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
)
)
return render_template(
"but/formsemestre_validation_auto_but.html",
form=form,
sco=ScoData(formsemestre=formsemestre),
title=f"Calcul automatique jury BUT",
)
@bp.route("/formsemestre_validate_previous_ue", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.ScoView)