WIP: amelioration form jury BUT

This commit is contained in:
Emmanuel Viennet 2022-06-29 16:30:01 +02:00
parent 581131f54f
commit b0e78b67ea
8 changed files with 125 additions and 73 deletions

View File

@ -36,7 +36,7 @@ from app.scodoc.sco_exceptions import ScoValueError
def formsemestre_saisie_jury_but( def formsemestre_saisie_jury_but(
formsemestre2: FormSemestre, formsemestre2: FormSemestre,
readonly: bool = False, read_only: bool = False,
selected_etudid: int = None, selected_etudid: int = None,
mode="jury", mode="jury",
) -> str: ) -> str:
@ -72,7 +72,7 @@ def formsemestre_saisie_jury_but(
) )
rows, titles, column_ids = get_table_jury_but( rows, titles, column_ids = get_table_jury_but(
formsemestre2, readonly=readonly, mode=mode formsemestre2, read_only=read_only, mode=mode
) )
if not rows: if not rows:
return ( return (
@ -109,7 +109,7 @@ def formsemestre_saisie_jury_but(
""" """
) )
if (mode == "recap") and not readonly: if (mode == "recap") and not read_only:
H.append( H.append(
f""" f"""
<p><a class="stdlink" href="{url_for( <p><a class="stdlink" href="{url_for(
@ -333,6 +333,7 @@ class RowCollector:
+ ((" " + scu.EMO_WARNING) if deca.nb_rcues_under_8 > 0 else ""), + ((" " + scu.EMO_WARNING) if deca.nb_rcues_under_8 > 0 else ""),
"col_rcue col_rcues_validables" + klass, "col_rcue col_rcues_validables" + klass,
) )
self["_rcues_validables_data"] = {"etudid": deca.etud.id}
if len(deca.rcues_annee) > 0: if len(deca.rcues_annee) > 0:
# permet un tri par nb de niveaux validables + moyenne gen indicative S_pair # permet un tri par nb de niveaux validables + moyenne gen indicative S_pair
if deca.res_pair and deca.etud.id in deca.res_pair.etud_moy_gen: if deca.res_pair and deca.etud.id in deca.res_pair.etud_moy_gen:
@ -353,7 +354,7 @@ class RowCollector:
def get_table_jury_but( def get_table_jury_but(
formsemestre2: FormSemestre, readonly: bool = False, mode="jury" formsemestre2: FormSemestre, read_only: bool = False, mode="jury"
) -> tuple[list[dict], list[str], list[str]]: ) -> tuple[list[dict], list[str], list[str]]:
"""Construit la table des résultats annuels pour le jury BUT""" """Construit la table des résultats annuels pour le jury BUT"""
res2: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre2) res2: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre2)
@ -383,7 +384,7 @@ def get_table_jury_but(
"col_code_annee", "col_code_annee",
) )
# --- Le lien de saisie # --- Le lien de saisie
if not readonly and not mode == "recap": if mode != "recap":
row.add_cell( row.add_cell(
"lien_saisie", "lien_saisie",
"", "",
@ -394,7 +395,7 @@ def get_table_jury_but(
etudid=etud.id, etudid=etud.id,
formsemestre_id=formsemestre2.id, formsemestre_id=formsemestre2.id,
)}" class="stdlink"> )}" class="stdlink">
{"modif." if deca.code_valide else "saisie"} {"voir" if read_only else ("modif." if deca.code_valide else "saisie")}
décision</a> décision</a>
""", """,
"col_lien_saisie_but", "col_lien_saisie_but",

View File

@ -399,7 +399,7 @@ class ResultatsSemestre(ResultatsCache):
# --- TABLEAU RECAP # --- TABLEAU RECAP
def get_table_recap( def get_table_recap(
self, convert_values=False, include_evaluations=False, modejury=False self, convert_values=False, include_evaluations=False, mode_jury=False
): ):
"""Result: tuple avec """Result: tuple avec
- rows: liste de dicts { column_id : value } - rows: liste de dicts { column_id : value }
@ -550,7 +550,7 @@ class ResultatsSemestre(ResultatsCache):
titles_bot[ titles_bot[
f"_{col_id}_target_attrs" f"_{col_id}_target_attrs"
] = f"""title="{ue.titre} S{ue.semestre_idx or '?'}" """ ] = f"""title="{ue.titre} S{ue.semestre_idx or '?'}" """
if modejury: if mode_jury:
# pas d'autre colonnes de résultats # pas d'autre colonnes de résultats
continue continue
# Bonus (sport) dans cette UE ? # Bonus (sport) dans cette UE ?
@ -650,7 +650,7 @@ class ResultatsSemestre(ResultatsCache):
elif nb_ues_validables < len(ues_sans_bonus): elif nb_ues_validables < len(ues_sans_bonus):
row["_ues_validables_class"] += " moy_inf" row["_ues_validables_class"] += " moy_inf"
row["_ues_validables_order"] = nb_ues_validables # pour tri row["_ues_validables_order"] = nb_ues_validables # pour tri
if modejury: if mode_jury:
dec_sem = self.validations.decisions_jury.get(etudid) dec_sem = self.validations.decisions_jury.get(etudid)
jury_code_sem = dec_sem["code"] if dec_sem else "" jury_code_sem = dec_sem["code"] if dec_sem else ""
idx = add_cell( idx = add_cell(

View File

@ -111,7 +111,7 @@ def formsemestre_validation_etud_form(
url_tableau = url_for( url_tableau = url_for(
"notes.formsemestre_recapcomplet", "notes.formsemestre_recapcomplet",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
modejury=1, mode_jury=1,
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
selected_etudid=etudid, # va a la bonne ligne selected_etudid=etudid, # va a la bonne ligne
) )
@ -979,7 +979,7 @@ def do_formsemestre_validation_auto(formsemestre_id):
H.append("</ul>") H.append("</ul>")
H.append( H.append(
f"""<a href="{url_for('notes.formsemestre_recapcomplet', f"""<a href="{url_for('notes.formsemestre_recapcomplet',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, modejury=1) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1)
}">continuer</a>""" }">continuer</a>"""
) )
H.append(html_sco_header.sco_footer()) H.append(html_sco_header.sco_footer())

View File

@ -501,7 +501,7 @@ def formsemestre_pvjury(formsemestre_id, format="html", publish=True):
from app.but import jury_but_recap from app.but import jury_but_recap
return jury_but_recap.formsemestre_saisie_jury_but( return jury_but_recap.formsemestre_saisie_jury_but(
formsemestre, readonly=True, mode="recap" formsemestre, read_only=True, mode="recap"
) )
# /XXX # /XXX
footer = html_sco_header.sco_footer() footer = html_sco_header.sco_footer()

View File

@ -57,7 +57,7 @@ from app.scodoc import sco_preferences
def formsemestre_recapcomplet( def formsemestre_recapcomplet(
formsemestre_id=None, formsemestre_id=None,
modejury=False, mode_jury=False,
tabformat="html", tabformat="html",
sortcol=None, sortcol=None,
xml_with_decisions=False, xml_with_decisions=False,
@ -78,7 +78,7 @@ def formsemestre_recapcomplet(
xml, json : concaténation de tous les bulletins, au format demandé xml, json : concaténation de tous les bulletins, au format demandé
pdf : NON SUPPORTE (car tableau trop grand pour générer un pdf utilisable) pdf : NON SUPPORTE (car tableau trop grand pour générer un pdf utilisable)
modejury: cache modules, affiche lien saisie decision jury mode_jury: cache modules, affiche lien saisie decision jury
xml_with_decisions: publie décisions de jury dans xml et json xml_with_decisions: publie décisions de jury dans xml et json
force_publishing: publie les xml et json même si bulletins non publiés force_publishing: publie les xml et json même si bulletins non publiés
selected_etudid: etudid sélectionné (pour scroller au bon endroit) selected_etudid: etudid sélectionné (pour scroller au bon endroit)
@ -91,14 +91,14 @@ def formsemestre_recapcomplet(
if tabformat not in supported_formats: if tabformat not in supported_formats:
raise ScoValueError(f"Format non supporté: {tabformat}") raise ScoValueError(f"Format non supporté: {tabformat}")
is_file = tabformat in file_formats is_file = tabformat in file_formats
modejury = int(modejury) mode_jury = int(mode_jury)
xml_with_decisions = int(xml_with_decisions) xml_with_decisions = int(xml_with_decisions)
force_publishing = int(force_publishing) force_publishing = int(force_publishing)
data = _do_formsemestre_recapcomplet( data = _do_formsemestre_recapcomplet(
formsemestre_id, formsemestre_id,
format=tabformat, format=tabformat,
modejury=modejury, mode_jury=mode_jury,
sortcol=sortcol, sortcol=sortcol,
xml_with_decisions=xml_with_decisions, xml_with_decisions=xml_with_decisions,
force_publishing=force_publishing, force_publishing=force_publishing,
@ -123,9 +123,9 @@ def formsemestre_recapcomplet(
<input type="hidden" name="formsemestre_id" value="{formsemestre_id}"></input> <input type="hidden" name="formsemestre_id" value="{formsemestre_id}"></input>
""" """
) )
if modejury: if mode_jury:
H.append( H.append(
f'<input type="hidden" name="modejury" value="{modejury}"></input>' f'<input type="hidden" name="mode_jury" value="{mode_jury}"></input>'
) )
H.append( H.append(
'<select name="tabformat" onchange="document.f.submit()" class="noprint">' '<select name="tabformat" onchange="document.f.submit()" class="noprint">'
@ -163,7 +163,7 @@ def formsemestre_recapcomplet(
) )
if sco_permissions_check.can_validate_sem(formsemestre_id): if sco_permissions_check.can_validate_sem(formsemestre_id):
H.append("<p>") H.append("<p>")
if modejury: if mode_jury:
H.append( H.append(
f"""<a class="stdlink" href="{url_for('notes.formsemestre_validation_auto', f"""<a class="stdlink" href="{url_for('notes.formsemestre_validation_auto',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
@ -172,7 +172,7 @@ def formsemestre_recapcomplet(
else: else:
H.append( H.append(
f"""<a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet', f"""<a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, modejury=1) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1)
}">Saisie des décisions du jury</a>""" }">Saisie des décisions du jury</a>"""
) )
H.append("</p>") H.append("</p>")
@ -196,7 +196,7 @@ def _do_formsemestre_recapcomplet(
formsemestre_id=None, formsemestre_id=None,
format="html", # html, xml, xls, xlsall, json format="html", # html, xml, xls, xlsall, json
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML) xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
modejury=False, # saisie décisions jury mode_jury=False, # saisie décisions jury
sortcol=None, # indice colonne a trier dans table T sortcol=None, # indice colonne a trier dans table T
xml_with_decisions=False, xml_with_decisions=False,
force_publishing=True, force_publishing=True,
@ -215,7 +215,7 @@ def _do_formsemestre_recapcomplet(
formsemestre, formsemestre,
res, res,
include_evaluations=(format == "evals"), include_evaluations=(format == "evals"),
modejury=modejury, mode_jury=mode_jury,
filename=filename, filename=filename,
selected_etudid=selected_etudid, selected_etudid=selected_etudid,
) )
@ -368,34 +368,34 @@ def gen_formsemestre_recapcomplet_html(
formsemestre: FormSemestre, formsemestre: FormSemestre,
res: NotesTableCompat, res: NotesTableCompat,
include_evaluations=False, include_evaluations=False,
modejury=False, mode_jury=False,
filename="", filename="",
selected_etudid=None, selected_etudid=None,
): ):
"""Construit table recap pour le BUT """Construit table recap pour le BUT
Cache le résultat pour le semestre (sauf en mode jury). Cache le résultat pour le semestre (sauf en mode jury).
Si modejury, cache colonnes modules et affiche un lien vers la saisie de la décision de jury Si mode_jury, cache colonnes modules et affiche un lien vers la saisie de la décision de jury
Return: data, filename Return: data, filename
data est une chaine, le <div>...</div> incluant le tableau. data est une chaine, le <div>...</div> incluant le tableau.
""" """
table_html = None table_html = None
if not (modejury or selected_etudid): if not (mode_jury or selected_etudid):
if include_evaluations: if include_evaluations:
table_html = sco_cache.TableRecapWithEvalsCache.get(formsemestre.id) table_html = sco_cache.TableRecapWithEvalsCache.get(formsemestre.id)
else: else:
table_html = sco_cache.TableRecapCache.get(formsemestre.id) table_html = sco_cache.TableRecapCache.get(formsemestre.id)
if modejury or (table_html is None): if mode_jury or (table_html is None):
table_html = _gen_formsemestre_recapcomplet_html( table_html = _gen_formsemestre_recapcomplet_html(
formsemestre, formsemestre,
res, res,
include_evaluations, include_evaluations,
modejury, mode_jury,
filename, filename,
selected_etudid=selected_etudid, selected_etudid=selected_etudid,
) )
if not modejury: if not mode_jury:
if include_evaluations: if include_evaluations:
sco_cache.TableRecapWithEvalsCache.set(formsemestre.id, table_html) sco_cache.TableRecapWithEvalsCache.set(formsemestre.id, table_html)
else: else:
@ -408,13 +408,15 @@ def _gen_formsemestre_recapcomplet_html(
formsemestre: FormSemestre, formsemestre: FormSemestre,
res: NotesTableCompat, res: NotesTableCompat,
include_evaluations=False, include_evaluations=False,
modejury=False, mode_jury=False,
filename: str = "", filename: str = "",
selected_etudid=None, selected_etudid=None,
) -> str: ) -> str:
"""Génère le html""" """Génère le html"""
rows, footer_rows, titles, column_ids = res.get_table_recap( rows, footer_rows, titles, column_ids = res.get_table_recap(
convert_values=True, include_evaluations=include_evaluations, modejury=modejury convert_values=True,
include_evaluations=include_evaluations,
mode_jury=mode_jury,
) )
if not rows: if not rows:
return ( return (
@ -423,7 +425,7 @@ def _gen_formsemestre_recapcomplet_html(
H = [ H = [
f"""<div class="table_recap"><table class="table_recap { f"""<div class="table_recap"><table class="table_recap {
'apc' if formsemestre.formation.is_apc() else 'classic' 'apc' if formsemestre.formation.is_apc() else 'classic'
} {'jury' if modejury else ''}" } {'jury' if mode_jury else ''}"
data-filename="{filename}">""" data-filename="{filename}">"""
] ]
# header # header

View File

@ -1097,6 +1097,10 @@ def gen_cell(key: str, row: dict, elt="td", with_col_class=False):
if with_col_class: if with_col_class:
klass = key + " " + klass klass = key + " " + klass
attrs = f'class="{klass}"' if klass else "" attrs = f'class="{klass}"' if klass else ""
data = row.get(f"_{key}_data") # dict
if data:
for k in data:
attrs += f' data-{k}="{data[k]}"'
order = row.get(f"_{key}_order") order = row.get(f"_{key}_order")
if order: if order:
attrs += f' data-order="{order}"' attrs += f' data-order="{order}"'

View File

@ -65,6 +65,13 @@
font-weight: bold; font-weight: bold;
} }
.but_navigation {
padding-top: 16px;
grid-column: 1 / -1;
display: flex;
justify-content: space-between;
}
div.but_section_annee { div.but_section_annee {
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -73,9 +80,10 @@ div.but_settings {
margin-top: 16px; margin-top: 16px;
} }
span.but_explanation { .but_explanation {
color: blueviolet; color: blueviolet;
font-style: italic; font-style: italic;
padding-top: 12px;
} }
select:disabled { select:disabled {

View File

@ -31,7 +31,7 @@ Module notes: issu de ScoDoc7 / ZNotes.py
Emmanuel Viennet, 2021 Emmanuel Viennet, 2021
""" """
import html from email.policy import default
from operator import itemgetter from operator import itemgetter
import time import time
from xml.etree import ElementTree from xml.etree import ElementTree
@ -58,14 +58,12 @@ from app import db
from app import models from app import models
from app.models import ScolarNews from app.models import ScolarNews
from app.auth.models import User from app.auth.models import User
from app.but import apc_edit_ue, bulletin_but, jury_but_recap from app.but import apc_edit_ue, jury_but_recap
from app.decorators import ( from app.decorators import (
scodoc, scodoc,
scodoc7func, scodoc7func,
permission_required, permission_required,
permission_required_compat_scodoc7, permission_required_compat_scodoc7,
admin_required,
login_required,
) )
from app.views import notes_bp as bp from app.views import notes_bp as bp
@ -2217,22 +2215,24 @@ def formsemestre_validation_etud_manu(
# --- Jurys BUT # --- Jurys BUT
@bp.route( @bp.route(
"/formsemestre_validation_but/<int:formsemestre_id>/<int:etudid>", "/formsemestre_validation_but/<int:formsemestre_id>/<etudid>",
methods=["GET", "POST"], methods=["GET", "POST"],
) )
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
def formsemestre_validation_but(formsemestre_id: int, etudid: int): def formsemestre_validation_but(
formsemestre_id: int,
etudid: int,
):
"Form. saisie décision jury semestre BUT" "Form. saisie décision jury semestre BUT"
if not sco_permissions_check.can_validate_sem(formsemestre_id): # la route ne donne pas le type d'etudid pour pouvoir construire des URLs
return scu.confirm_dialog( # provisoires avec NEXT et PREV
message=f"<p>Opération non autorisée pour {current_user}</h2>", try:
dest_url=url_for( etudid = int(etudid)
"notes.formsemestre_status", except:
scodoc_dept=g.scodoc_dept, abort(404, "invalid etudid")
formsemestre_id=formsemestre_id, read_only = not sco_permissions_check.can_validate_sem(formsemestre_id)
),
)
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title="Validation BUT", page_title="Validation BUT",
@ -2270,8 +2270,9 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
if len(deca.rcues_annee) == 0: if len(deca.rcues_annee) == 0:
raise ScoValueError("année incomplète: pas de jury BUT annuel possible") raise ScoValueError("année incomplète: pas de jury BUT annuel possible")
if request.method == "POST": if request.method == "POST":
deca.record_form(request.form) if not read_only:
flash("codes enregistrés") deca.record_form(request.form)
flash("codes enregistrés")
return flask.redirect( return flask.redirect(
url_for( url_for(
"notes.formsemestre_validation_but", "notes.formsemestre_validation_but",
@ -2280,7 +2281,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
etudid=etudid, etudid=etudid,
) )
) )
if deca.code_valide: if deca.code_valide and not read_only:
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,
@ -2313,7 +2314,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
<span>({'non ' if deca.code_valide is None else ''}enregistrée)</span> <span>({'non ' if deca.code_valide is None else ''}enregistrée)</span>
<span>{erase_span}</span> <span>{erase_span}</span>
</div> </div>
<span class="but_explanation">{deca.explanation}</span> <div class="but_explanation">{deca.explanation}</div>
</div> </div>
<div><b>Niveaux de compétences et unités d'enseignement :</b></div> <div><b>Niveaux de compétences et unités d'enseignement :</b></div>
<div class="but_annee"> <div class="but_annee">
@ -2339,6 +2340,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
dec_rcue.rcue.ue_1, dec_rcue.rcue.ue_1,
dec_rcue.rcue.moy_ue_1, dec_rcue.rcue.moy_ue_1,
deca.decisions_ues[dec_rcue.rcue.ue_1.id], deca.decisions_ues[dec_rcue.rcue.ue_1.id],
disabled=read_only,
) )
) )
# Semestre pair # Semestre pair
@ -2347,6 +2349,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
dec_rcue.rcue.ue_2, dec_rcue.rcue.ue_2,
dec_rcue.rcue.moy_ue_2, dec_rcue.rcue.moy_ue_2,
deca.decisions_ues[dec_rcue.rcue.ue_2.id], deca.decisions_ues[dec_rcue.rcue.ue_2.id],
disabled=read_only,
) )
) )
# RCUE # RCUE
@ -2366,24 +2369,58 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
) )
H.append("</div>") # but_annee H.append("</div>") # but_annee
if read_only:
H.append(
"""<div class="but_explanation">Vous n'avez pas la permission de modifier ces décisions.
Les champs entourés en vert sont enregistrés.</div>"""
)
else:
H.append(
f"""<div class="but_settings">
<input type="checkbox" onchange="enable_manual_codes(this)">
<em>permettre la saisie manuelles des codes d'année et de niveaux.
Dans ce cas, il vous revient de vous assurer de la cohérence entre
vos codes d'UE/RCUE/Année !</em>
</input>
</div>
<div class="but_buttons">
<input type="submit" value="Enregistrer ces décisions">
</div>
"""
)
H.append( H.append(
f"""<div class="but_settings"> f"""<div class="but_navigation">
<input type="checkbox" onchange="enable_manual_codes(this)"> <div class="back_list">
<em>permettre la saisie manuelles des codes d'année et de niveaux. <a href="{url_for("notes.formsemestre_saisie_jury", scodoc_dept=g.scodoc_dept,
Dans ce cas, il vous revient de vous assurer de la cohérence entre formsemestre_id=formsemestre_id, selected_etudid=etud.id
vos codes d'UE/RCUE/Année !</em> )}" class="stdlink">retour à la liste</a>
</input>
</div> </div>
</div>"""
<div class="but_buttons">
<span><input type="submit" value="Enregistrer ces décisions"></span>
<span><a href="{url_for(
"notes.formsemestre_saisie_jury", scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id, selected_etudid=etud.id
)}">retour à la liste</a></span>
</div>
"""
) )
# # --- Navigation
# prev = f"""<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>
# """
# H.append(
# f"""
# <div class="but_navigation">
# <div class="prev">
# {prev}
# </div>
# <div class="back_list">
# <a href="{url_for(
# "notes.formsemestre_saisie_jury", scodoc_dept=g.scodoc_dept,
# formsemestre_id=formsemestre_id, selected_etudid=etud.id
# )}" class="stdlink">retour à la liste</a>
# </div>
# <div class="next">
# next TODO
# </div>
# </div>"""
# )
H.append("</form>") # but_annee H.append("</form>") # but_annee
H.append( H.append(
@ -2425,7 +2462,7 @@ def _gen_but_select(
def _gen_but_niveau_ue( def _gen_but_niveau_ue(
ue: UniteEns, moy_ue: float, dec_ue: jury_but.DecisionsProposeesUE ue: UniteEns, moy_ue: float, dec_ue: jury_but.DecisionsProposeesUE, disabled=False
): ):
return f"""<div class="but_niveau_ue { return f"""<div class="but_niveau_ue {
'recorded' if dec_ue.code_valide is not None else ''} 'recorded' if dec_ue.code_valide is not None else ''}
@ -2435,7 +2472,7 @@ def _gen_but_niveau_ue(
<div class="but_code">{ <div class="but_code">{
_gen_but_select("code_ue_"+str(ue.id), _gen_but_select("code_ue_"+str(ue.id),
dec_ue.codes, dec_ue.codes,
dec_ue.code_valide dec_ue.code_valide, disabled=disabled
) )
}</div> }</div>
</div>""" </div>"""
@ -2640,18 +2677,18 @@ def formsemestre_saisie_jury(formsemestre_id: int, selected_etudid: int = None):
en semestres pairs de BUT, table spécifique avec l'année en semestres pairs de BUT, table spécifique avec l'année
sinon, redirect vers page recap en mode jury sinon, redirect vers page recap en mode jury
""" """
readonly = not sco_permissions_check.can_validate_sem(formsemestre_id) read_only = not sco_permissions_check.can_validate_sem(formsemestre_id)
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0: if formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0:
return jury_but_recap.formsemestre_saisie_jury_but( return jury_but_recap.formsemestre_saisie_jury_but(
formsemestre, readonly, selected_etudid=selected_etudid formsemestre, read_only, selected_etudid=selected_etudid
) )
return redirect( return redirect(
url_for( url_for(
"notes.formsemestre_recapcomplet", "notes.formsemestre_recapcomplet",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
modejury=1, mode_jury=1,
) )
) )
@ -2662,14 +2699,14 @@ def formsemestre_saisie_jury(formsemestre_id: int, selected_etudid: int = None):
@scodoc7func @scodoc7func
def formsemestre_jury_but_recap(formsemestre_id: int, selected_etudid: int = None): def formsemestre_jury_but_recap(formsemestre_id: int, selected_etudid: int = None):
"""Tableau affichage des codes""" """Tableau affichage des codes"""
readonly = not sco_permissions_check.can_validate_sem(formsemestre_id) read_only = not sco_permissions_check.can_validate_sem(formsemestre_id)
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if not (formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0): if not (formsemestre.formation.is_apc() and formsemestre.semestre_id % 2 == 0):
raise ScoValueError( raise ScoValueError(
"formsemestre_jury_but_recap: réservé aux semestres pairs de BUT" "formsemestre_jury_but_recap: réservé aux semestres pairs de BUT"
) )
return jury_but_recap.formsemestre_saisie_jury_but( return jury_but_recap.formsemestre_saisie_jury_but(
formsemestre, readonly=readonly, selected_etudid=selected_etudid, mode="recap" formsemestre, read_only=read_only, selected_etudid=selected_etudid, mode="recap"
) )