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