Jury BUT: amélioration gestion redoublants + #547 (WIP)
This commit is contained in:
parent
c06a6e83b6
commit
c374209d22
@ -350,8 +350,9 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
)
|
||||
"vrai si l'année est réussie, tous niveaux validables ou validés par le jury"
|
||||
self.valide_moitie_rcue = self.nb_validables > (self.nb_competences // 2)
|
||||
"Peut passer si plus de la moitié validables et tous > 8"
|
||||
"Vrai si plus de la moitié des RCUE validables"
|
||||
self.passage_de_droit = self.valide_moitie_rcue and (self.nb_rcues_under_8 == 0)
|
||||
"Vrai si peut passer dans l'année BUT suivante: plus de la moitié validables et tous > 8"
|
||||
# XXX TODO ajouter condition pour passage en S5
|
||||
|
||||
# Enfin calcule les codes des UE:
|
||||
@ -752,8 +753,9 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
pour cette année: décisions d'UE, de RCUE, d'année,
|
||||
et autorisations d'inscription émises.
|
||||
Efface même si étudiant DEM ou DEF.
|
||||
Si à cheval, n'efface que pour le semestre d'origine du deca.
|
||||
"""
|
||||
if only_one_sem:
|
||||
if only_one_sem or self.a_cheval:
|
||||
# N'efface que les autorisations venant de ce semestre,
|
||||
# et les validations de ses UEs
|
||||
ScolarAutorisationInscription.delete_autorisation_etud(
|
||||
@ -906,6 +908,19 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
or dec_prop_annee.formsemestre_pair.modalite == "EXT"
|
||||
):
|
||||
self.codes.insert(0, sco_codes.ADM)
|
||||
# S'il y a une décision enregistrée: si elle est plus favorable que celle que l'on
|
||||
# proposerait, la place en tête.
|
||||
# Sinon, la place en seconde place
|
||||
if self.code_valide and self.code_valide != self.codes[0]:
|
||||
code_default = self.codes[0]
|
||||
if self.code_valide in self.codes:
|
||||
self.codes.remove(self.code_valide)
|
||||
if sco_codes.BUT_CODES_ORDERED.get(
|
||||
self.code_valide, 0
|
||||
) > sco_codes.BUT_CODES_ORDERED.get(code_default, 0):
|
||||
self.codes.insert(0, self.code_valide)
|
||||
else:
|
||||
self.codes.insert(1, self.code_valide)
|
||||
|
||||
def record(self, code: str, no_overwrite=False):
|
||||
"""Enregistre le code"""
|
||||
|
@ -41,32 +41,21 @@ def show_etud(deca: DecisionsProposeesAnnee, read_only: bool = True) -> str:
|
||||
Si pas read_only, menus sélection codes jury.
|
||||
"""
|
||||
H = []
|
||||
if deca.code_valide and not read_only:
|
||||
erase_span = f"""<a href="{
|
||||
url_for("notes.formsemestre_jury_but_erase",
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=deca.formsemestre_id,
|
||||
etudid=deca.etud.id)}" class="stdlink">effacer décisions</a>"""
|
||||
else:
|
||||
erase_span = ""
|
||||
|
||||
H.append("""<div class="but_section_annee">""")
|
||||
if deca.jury_annuel:
|
||||
H.append(
|
||||
f"""
|
||||
<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")
|
||||
}
|
||||
<span>({'non ' if deca.code_valide is None else ''}enregistrée)</span>
|
||||
<span>{erase_span}</span>
|
||||
</div>
|
||||
H.append(
|
||||
f"""
|
||||
<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")
|
||||
}
|
||||
<span>({'non ' if deca.code_valide is None else ''}enregistrée)</span>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
div_explanation = f"""<div class="but_explanation">{deca.explanation}</div>"""
|
||||
else:
|
||||
H.append("""<div><em>Pas de décision annuelle (sem. impair).</em></div>""")
|
||||
div_explanation = ""
|
||||
)
|
||||
div_explanation = f"""<div class="but_explanation">{deca.explanation}</div>"""
|
||||
|
||||
H.append("""</div>""")
|
||||
|
||||
formsemestre_1 = deca.formsemestre_impair
|
||||
@ -245,9 +234,16 @@ def _gen_but_rcue(dec_rcue: DecisionsProposeesRCUE, niveau: ApcNiveau) -> str:
|
||||
else ""
|
||||
)
|
||||
|
||||
# Déjà enregistré ?
|
||||
niveau_rcue_class = ""
|
||||
if dec_rcue.code_valide is not None and dec_rcue.codes:
|
||||
if dec_rcue.code_valide == dec_rcue.codes[0]:
|
||||
niveau_rcue_class = "recorded"
|
||||
else:
|
||||
niveau_rcue_class = "recorded_different"
|
||||
|
||||
return f"""
|
||||
<div class="but_niveau_rcue
|
||||
{'recorded' if dec_rcue.code_valide is not None else ''}
|
||||
<div class="but_niveau_rcue {niveau_rcue_class}
|
||||
">
|
||||
<div class="but_note with_scoplement">
|
||||
<div>{scu.fmt_note(dec_rcue.rcue.moy_rcue)}</div>
|
||||
@ -351,7 +347,7 @@ def jury_but_semestriel(
|
||||
warning = ""
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title="Validation BUT",
|
||||
page_title=f"Validation BUT S{formsemestre.semestre_id}",
|
||||
formsemestre_id=formsemestre.id,
|
||||
etudid=etud.id,
|
||||
cssstyles=("css/jury_but.css",),
|
||||
@ -376,21 +372,21 @@ def jury_but_semestriel(
|
||||
{warning}
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<form method="post" id="jury_but">
|
||||
""",
|
||||
]
|
||||
if (not read_only) and any([dec.code_valide for dec in decisions_ues.values()]):
|
||||
erase_span = f"""<a href="{
|
||||
url_for("notes.formsemestre_jury_but_erase",
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id,
|
||||
etudid=etud.id, only_one_sem=1)}" class="stdlink">effacer les décisions enregistrées</a>"""
|
||||
etudid=etud.id, only_one_sem=1)
|
||||
}" class="stdlink">effacer les décisions enregistrées</a>"""
|
||||
else:
|
||||
erase_span = "Cet étudiant n'a aucune décision enregistrée pour ce semestre."
|
||||
|
||||
H.append(
|
||||
f"""
|
||||
<div class="but_section_annee">
|
||||
<span>{erase_span}</span>
|
||||
</div>
|
||||
<div><b>Unités d'enseignement de S{formsemestre.semestre_id}:</b></div>
|
||||
"""
|
||||
@ -447,9 +443,10 @@ def jury_but_semestriel(
|
||||
else:
|
||||
H.append("""<div class="help">dernier semestre de la formation.</div>""")
|
||||
H.append(
|
||||
"""
|
||||
f"""
|
||||
<div class="but_buttons">
|
||||
<input type="submit" value="Enregistrer ces décisions">
|
||||
<span><input type="submit" value="Enregistrer ces décisions"></span>
|
||||
<span>{erase_span}</span>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
|
@ -180,8 +180,9 @@ class RegroupementCoherentUE:
|
||||
return self.query_validations().count() > 0
|
||||
|
||||
def est_compensable(self):
|
||||
"""Vrai si ce RCUE est validable par compensation
|
||||
c'est à dire que sa moyenne est > 10 avec une UE < 10
|
||||
"""Vrai si ce RCUE est validable (uniquement) par compensation
|
||||
c'est à dire que sa moyenne est > 10 avec une UE < 10.
|
||||
Note: si ADM, est_compensable est faux.
|
||||
"""
|
||||
return (
|
||||
(self.moy_rcue is not None)
|
||||
|
@ -205,6 +205,20 @@ BUT_CODES_PASSAGE = {
|
||||
PAS1NCI,
|
||||
ATJ,
|
||||
}
|
||||
# les codes, du plus "défavorable" à l'étudiant au plus favorable:
|
||||
# (valeur par défaut 0)
|
||||
BUT_CODES_ORDERED = {
|
||||
"NAR": 0,
|
||||
"DEF": 0,
|
||||
"AJ": 10,
|
||||
"ATJ": 20,
|
||||
"CMP": 50,
|
||||
"ADC": 50,
|
||||
"PASD": 50,
|
||||
"PAS1NCI": 60,
|
||||
"ADJ": 100,
|
||||
"ADM": 100,
|
||||
}
|
||||
|
||||
|
||||
def code_semestre_validant(code: str) -> bool:
|
||||
|
@ -22,7 +22,7 @@
|
||||
margin-left: 32px;
|
||||
display: inline-grid;
|
||||
grid-template-columns: repeat(4, auto);
|
||||
gap: 4px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.but_annee_caption {
|
||||
@ -143,8 +143,14 @@ div.but_code {
|
||||
|
||||
div.but_niveau_ue.recorded,
|
||||
div.but_niveau_rcue.recorded {
|
||||
border-color: rgb(136, 252, 136);
|
||||
border-width: 2px;
|
||||
border-color: rgb(0, 169, 0);
|
||||
border-width: 3px;
|
||||
}
|
||||
|
||||
div.but_niveau_ue.recorded_different,
|
||||
div.but_niveau_rcue.recorded_different {
|
||||
box-shadow: 0 0 0 3px red;
|
||||
outline: dashed 3px rgb(0, 169, 0);
|
||||
}
|
||||
|
||||
div.but_niveau_ue.annee_prec {
|
||||
@ -160,6 +166,7 @@ div.but_buttons {
|
||||
}
|
||||
|
||||
div.but_buttons span {
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,8 @@ $(function () {
|
||||
|
||||
// ----- Etat du formulaire jury pour éviter sortie sans enregistrer
|
||||
let FORM_STATE = "";
|
||||
let IS_SUBMITTING = false;
|
||||
|
||||
// Une chaine décrivant l'état du form
|
||||
function get_form_state() {
|
||||
let codes = [];
|
||||
@ -73,13 +75,19 @@ function get_form_state() {
|
||||
|
||||
$('document').ready(function () {
|
||||
FORM_STATE = get_form_state();
|
||||
document.querySelector("form#jury_but").addEventListener('submit', jury_form_submit);
|
||||
});
|
||||
|
||||
function is_modified() {
|
||||
return FORM_STATE != get_form_state();
|
||||
}
|
||||
|
||||
function jury_form_submit(event) {
|
||||
IS_SUBMITTING = true;
|
||||
}
|
||||
|
||||
window.addEventListener("beforeunload", function (e) {
|
||||
if (is_modified()) {
|
||||
if ((!IS_SUBMITTING) && is_modified()) {
|
||||
var confirmationMessage = 'Changements non enregistrés !';
|
||||
(e || window.event).returnValue = confirmationMessage;
|
||||
return confirmationMessage;
|
||||
|
@ -2327,17 +2327,17 @@ def formsemestre_validation_but(
|
||||
# provisoires avec NEXT et PREV
|
||||
try:
|
||||
etudid = int(etudid)
|
||||
except:
|
||||
except ValueError:
|
||||
abort(404, "invalid etudid")
|
||||
read_only = not sco_permissions_check.can_validate_sem(formsemestre_id)
|
||||
|
||||
# --- Navigation
|
||||
prev = f"""{scu.EMO_PREV_ARROW} <a href="{url_for(
|
||||
prev_lnk = f"""{scu.EMO_PREV_ARROW} <a href="{url_for(
|
||||
"notes.formsemestre_validation_but", scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id, etudid="PREV"
|
||||
)}" class="stdlink"">précédent</a>
|
||||
"""
|
||||
next = f"""<a href="{url_for(
|
||||
next_lnk = f"""<a href="{url_for(
|
||||
"notes.formsemestre_validation_but", scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id, etudid="NEXT"
|
||||
)}" class="stdlink"">suivant</a> {scu.EMO_NEXT_ARROW}
|
||||
@ -2345,7 +2345,7 @@ def formsemestre_validation_but(
|
||||
navigation_div = f"""
|
||||
<div class="but_navigation">
|
||||
<div class="prev">
|
||||
{prev}
|
||||
{prev_lnk}
|
||||
</div>
|
||||
<div class="back_list">
|
||||
<a href="{url_for(
|
||||
@ -2354,21 +2354,20 @@ def formsemestre_validation_but(
|
||||
)}" class="stdlink">retour à la liste</a>
|
||||
</div>
|
||||
<div class="next">
|
||||
{next}
|
||||
{next_lnk}
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
H = [
|
||||
html_sco_header.sco_header(
|
||||
page_title="Validation BUT",
|
||||
page_title=f"Validation BUT S{formsemestre.semestre_id}",
|
||||
formsemestre_id=formsemestre_id,
|
||||
etudid=etudid,
|
||||
cssstyles=("css/jury_but.css",),
|
||||
javascripts=("js/jury_but.js",),
|
||||
),
|
||||
f"""
|
||||
<div class="jury_but">
|
||||
"""<div class="jury_but">
|
||||
""",
|
||||
]
|
||||
|
||||
@ -2401,7 +2400,6 @@ def formsemestre_validation_but(
|
||||
|
||||
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
|
||||
if len(deca.rcues_annee) == 0:
|
||||
# raise ScoValueError("année incomplète: pas de jury BUT annuel possible")
|
||||
return jury_but_view.jury_but_semestriel(
|
||||
formsemestre, etud, read_only, navigation_div=navigation_div
|
||||
)
|
||||
@ -2421,7 +2419,7 @@ def formsemestre_validation_but(
|
||||
warning = ""
|
||||
if len(deca.niveaux_competences) != len(deca.decisions_rcue_by_niveau):
|
||||
if deca.a_cheval:
|
||||
warning += f"""<div class="warning">Attention: regroupements RCUE
|
||||
warning += """<div class="warning">Attention: regroupements RCUE
|
||||
entre années (redoublement).</div>"""
|
||||
else:
|
||||
warning += f"""<div class="warning">Attention: {len(deca.niveaux_competences)}
|
||||
@ -2454,7 +2452,7 @@ def formsemestre_validation_but(
|
||||
{warning}
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<form method="post" id="jury_but">
|
||||
"""
|
||||
)
|
||||
|
||||
@ -2467,6 +2465,10 @@ def formsemestre_validation_but(
|
||||
Les champs entourés en vert sont enregistrés.</div>"""
|
||||
)
|
||||
else:
|
||||
erase_span = f"""<a href="{
|
||||
url_for("notes.formsemestre_jury_but_erase",
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=deca.formsemestre_id,
|
||||
etudid=deca.etud.id)}" class="stdlink">effacer décisions</a>"""
|
||||
H.append(
|
||||
f"""<div class="but_settings">
|
||||
<input type="checkbox" onchange="enable_manual_codes(this)">
|
||||
@ -2477,7 +2479,8 @@ def formsemestre_validation_but(
|
||||
</div>
|
||||
|
||||
<div class="but_buttons">
|
||||
<input type="submit" value="Enregistrer ces décisions">
|
||||
<span><input type="submit" value="Enregistrer ces décisions"></span>
|
||||
<span>{erase_span}</span>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
@ -2790,7 +2793,9 @@ def formsemestre_jury_but_erase(
|
||||
explanation=f"""Les validations d'UE et autorisations de passage
|
||||
du semestre S{formsemestre.semestre_id} seront effacées."""
|
||||
if only_one_sem
|
||||
else """Les validations de toutes les UE, RCUE (compétences) et année seront effacées.""",
|
||||
else """Les validations de toutes les UE, RCUE (compétences) et année seront effacées.
|
||||
Les décisions de l'année scolaire précédente ne seront pas modifiées.
|
||||
""",
|
||||
cancel_url=dest_url,
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user