forked from ScoDoc/ScoDoc
Editions formations BUT: meilleurs avertissements et possibilité de changer des associations en super-admin si décision saisies.
This commit is contained in:
parent
7015789358
commit
845b0e9363
@ -209,26 +209,40 @@ def ue_set_parcours(ue_id: int):
|
|||||||
return {"status": ok, "message": error_message}
|
return {"status": ok, "message": error_message}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>/force",
|
||||||
|
defaults={"force": True},
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>/force",
|
||||||
|
defaults={"force": True},
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>",
|
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>",
|
||||||
|
defaults={"force": False},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>",
|
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>",
|
||||||
|
defaults={"force": False},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.EditFormation)
|
@permission_required(Permission.EditFormation)
|
||||||
@as_json
|
@as_json
|
||||||
def ue_assoc_niveau(ue_id: int, niveau_id: int):
|
def ue_assoc_niveau(ue_id: int, niveau_id: int, force=False):
|
||||||
"""Associe l'UE au niveau de compétence."""
|
"""Associe l'UE au niveau de compétence.
|
||||||
|
Si force, modifie l'association même si des décisions de jury sont présentes.
|
||||||
|
"""
|
||||||
query = UniteEns.query.filter_by(id=ue_id)
|
query = UniteEns.query.filter_by(id=ue_id)
|
||||||
if g.scodoc_dept:
|
if g.scodoc_dept:
|
||||||
query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id)
|
query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
ue: UniteEns = query.first_or_404()
|
ue: UniteEns = query.first_or_404()
|
||||||
niveau: ApcNiveau = ApcNiveau.get_or_404(niveau_id)
|
niveau: ApcNiveau = ApcNiveau.get_or_404(niveau_id)
|
||||||
ok, error_message = ue.set_niveau_competence(niveau)
|
ok, error_message = ue.set_niveau_competence(niveau, force=force)
|
||||||
if not ok:
|
if not ok:
|
||||||
if g.scodoc_dept: # "usage web"
|
if g.scodoc_dept: # "usage web"
|
||||||
flash(error_message, "error")
|
flash(error_message, "error")
|
||||||
@ -238,19 +252,31 @@ def ue_assoc_niveau(ue_id: int, niveau_id: int):
|
|||||||
return {"status": 0}
|
return {"status": 0}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/desassoc_niveau/force",
|
||||||
|
defaults={"force": True},
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/desassoc_niveau/force",
|
||||||
|
defaults={"force": True},
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/formation/ue/<int:ue_id>/desassoc_niveau",
|
"/formation/ue/<int:ue_id>/desassoc_niveau",
|
||||||
|
defaults={"force": False},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/formation/ue/<int:ue_id>/desassoc_niveau",
|
"/formation/ue/<int:ue_id>/desassoc_niveau",
|
||||||
|
defaults={"force": False},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.EditFormation)
|
@permission_required(Permission.EditFormation)
|
||||||
@as_json
|
@as_json
|
||||||
def ue_desassoc_niveau(ue_id: int):
|
def ue_desassoc_niveau(ue_id: int, force=False):
|
||||||
"""Désassocie cette UE de son niveau de compétence
|
"""Désassocie cette UE de son niveau de compétence
|
||||||
(si elle n'est pas associée, ne fait rien).
|
(si elle n'est pas associée, ne fait rien).
|
||||||
"""
|
"""
|
||||||
@ -258,7 +284,7 @@ def ue_desassoc_niveau(ue_id: int):
|
|||||||
if g.scodoc_dept:
|
if g.scodoc_dept:
|
||||||
query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id)
|
query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
ue: UniteEns = query.first_or_404()
|
ue: UniteEns = query.first_or_404()
|
||||||
ok, error_message = ue.set_niveau_competence(None)
|
ok, error_message = ue.set_niveau_competence(None, force=force)
|
||||||
if not ok:
|
if not ok:
|
||||||
if g.scodoc_dept: # "usage web"
|
if g.scodoc_dept: # "usage web"
|
||||||
flash(error_message, "error")
|
flash(error_message, "error")
|
||||||
|
@ -96,11 +96,13 @@ def but_parcours_validated(etud: Identite, parcour_id: int | None) -> bool:
|
|||||||
class EtudCursusBUT:
|
class EtudCursusBUT:
|
||||||
"""L'état de l'étudiant dans son cursus BUT
|
"""L'état de l'étudiant dans son cursus BUT
|
||||||
Liste des niveaux validés/à valider
|
Liste des niveaux validés/à valider
|
||||||
(utilisé pour le résumé sur la fiche étudiant)
|
(utilisé pour le résumé sur la fiche étudiant).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, etud: Identite, formation: Formation):
|
def __init__(self, etud: Identite, formation: Formation):
|
||||||
"""formation indique la spécialité préparée"""
|
"""formation indique la spécialité préparée.
|
||||||
|
Peut lever l'exception ScoValueError ou ScoNoReferentielCompetences
|
||||||
|
"""
|
||||||
# Vérifie que l'étudiant est bien inscrit à un sem. de cette formation
|
# Vérifie que l'étudiant est bien inscrit à un sem. de cette formation
|
||||||
if formation.id not in (
|
if formation.id not in (
|
||||||
ins.formsemestre.formation.id for ins in etud.formsemestre_inscriptions
|
ins.formsemestre.formation.id for ins in etud.formsemestre_inscriptions
|
||||||
@ -142,10 +144,10 @@ class EtudCursusBUT:
|
|||||||
if niveau is None:
|
if niveau is None:
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
f"""UE d'un RCUE ({
|
f"""UE d'un RCUE ({
|
||||||
validation_rcue.ue1.acronyme}/{validation_rcue.ue1.acronyme
|
validation_rcue.ue1.acronyme}/{validation_rcue.ue2.acronyme
|
||||||
}) non associée à un niveau de compétence.
|
}) non associée à un niveau de compétence.
|
||||||
Vérifiez la formation et les associations de ses UEs.
|
Vérifiez la formation et les associations de ses UEs.
|
||||||
Étudiant {etud.nomprenom}.
|
Étudiant {etud.html_link_fiche()}.
|
||||||
Formations concernées: <a href="{
|
Formations concernées: <a href="{
|
||||||
url_for('notes.ue_table', scodoc_dept=g.scodoc_dept,
|
url_for('notes.ue_table', scodoc_dept=g.scodoc_dept,
|
||||||
formation_id=validation_rcue.ue1.formation_id,
|
formation_id=validation_rcue.ue1.formation_id,
|
||||||
@ -156,7 +158,8 @@ class EtudCursusBUT:
|
|||||||
formation_id=validation_rcue.ue2.formation_id,
|
formation_id=validation_rcue.ue2.formation_id,
|
||||||
semestre_idx=validation_rcue.ue2.semestre_idx)
|
semestre_idx=validation_rcue.ue2.semestre_idx)
|
||||||
}">{validation_rcue.ue2.acronyme}</a>.
|
}">{validation_rcue.ue2.acronyme}</a>.
|
||||||
"""
|
""",
|
||||||
|
safe=True,
|
||||||
)
|
)
|
||||||
if not niveau.competence.id in self.validation_par_competence_et_annee:
|
if not niveau.competence.id in self.validation_par_competence_et_annee:
|
||||||
self.validation_par_competence_et_annee[niveau.competence.id] = {}
|
self.validation_par_competence_et_annee[niveau.competence.id] = {}
|
||||||
@ -625,8 +628,9 @@ def formsemestre_warning_apc_setup(
|
|||||||
)
|
)
|
||||||
if nb_ues_sans_parcours != nb_ues_tot:
|
if nb_ues_sans_parcours != nb_ues_tot:
|
||||||
H.append(
|
H.append(
|
||||||
"""Le semestre n'est associé à aucun parcours,
|
f"""Le semestre n'est associé à aucun parcours,
|
||||||
mais les UEs de la formation ont des parcours
|
mais les UEs de la formation ont des parcours
|
||||||
|
({nb_ues_sans_parcours} UEs sans parcours sur {nb_ues_tot} UEs au total).
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
# Vérifie les niveaux de chaque parcours
|
# Vérifie les niveaux de chaque parcours
|
||||||
|
@ -1473,7 +1473,7 @@ class BonusTarbes(BonusIUTRennes1):
|
|||||||
"""Calcul bonus optionnels (sport, culture), règle IUT de Tarbes.
|
"""Calcul bonus optionnels (sport, culture), règle IUT de Tarbes.
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Les étudiants opeuvent suivre un ou plusieurs activités optionnelles notées.
|
<li>Les étudiants peuvent suivre un ou plusieurs activités optionnelles notées.
|
||||||
La meilleure des notes obtenue est prise en compte, si elle est supérieure à 10/20.
|
La meilleure des notes obtenue est prise en compte, si elle est supérieure à 10/20.
|
||||||
</li>
|
</li>
|
||||||
<li>Le trentième des points au dessus de 10 est ajouté à la moyenne des UE en BUT,
|
<li>Le trentième des points au dessus de 10 est ajouté à la moyenne des UE en BUT,
|
||||||
|
@ -464,7 +464,9 @@ class UniteEns(models.ScoDocModel):
|
|||||||
> 0
|
> 0
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_niveau_competence(self, niveau: ApcNiveau | None) -> tuple[bool, str]:
|
def set_niveau_competence(
|
||||||
|
self, niveau: ApcNiveau | None, force: bool = False
|
||||||
|
) -> tuple[bool, str]:
|
||||||
"""Associe cette UE au niveau de compétence indiqué.
|
"""Associe cette UE au niveau de compétence indiqué.
|
||||||
Le niveau doit être dans l'un des parcours de l'UE (si elle n'est pas
|
Le niveau doit être dans l'un des parcours de l'UE (si elle n'est pas
|
||||||
de tronc commun).
|
de tronc commun).
|
||||||
@ -473,7 +475,8 @@ class UniteEns(models.ScoDocModel):
|
|||||||
|
|
||||||
Si niveau est None, désassocie.
|
Si niveau est None, désassocie.
|
||||||
|
|
||||||
Si l'UE est utilisée dans un validation de RCUE, on ne peut plus la changer de niveau.
|
Si l'UE est utilisée dans un validation de RCUE, on ne peut plus la changer
|
||||||
|
de niveau, sauf si force est vrai.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
- True if (de)association done, False on error.
|
- True if (de)association done, False on error.
|
||||||
@ -486,7 +489,7 @@ class UniteEns(models.ScoDocModel):
|
|||||||
"La formation n'est pas associée à un référentiel de compétences",
|
"La formation n'est pas associée à un référentiel de compétences",
|
||||||
)
|
)
|
||||||
# UE utilisée dans des validations RCUE ?
|
# UE utilisée dans des validations RCUE ?
|
||||||
if self.is_used_in_validation_rcue():
|
if not force and self.is_used_in_validation_rcue():
|
||||||
return (
|
return (
|
||||||
False,
|
False,
|
||||||
"UE utilisée dans un RCUE validé: son niveau ne peut plus être modifié",
|
"UE utilisée dans un RCUE validé: son niveau ne peut plus être modifié",
|
||||||
@ -521,7 +524,7 @@ class UniteEns(models.ScoDocModel):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
# Invalidation du cache
|
# Invalidation du cache
|
||||||
self.formation.invalidate_cached_sems()
|
self.formation.invalidate_cached_sems()
|
||||||
log(f"ue.set_niveau_competence( {self}, {niveau} )")
|
log(f"ue.set_niveau_competence( {self}, {niveau}, force={force} )")
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
def set_parcours(self, parcours: list[ApcParcours]) -> tuple[bool, str]:
|
def set_parcours(self, parcours: list[ApcParcours]) -> tuple[bool, str]:
|
||||||
|
@ -117,7 +117,7 @@ def do_formsemestre_archive(
|
|||||||
dept_id=formsemestre.dept_id,
|
dept_id=formsemestre.dept_id,
|
||||||
)
|
)
|
||||||
# Tableau recap notes en HTML (pour tous les etudiants, n'utilise pas les groupes)
|
# Tableau recap notes en HTML (pour tous les etudiants, n'utilise pas les groupes)
|
||||||
table_html, _, _ = gen_formsemestre_recapcomplet_html_table(
|
table_html, _, _, _ = gen_formsemestre_recapcomplet_html_table(
|
||||||
formsemestre, res, include_evaluations=True
|
formsemestre, res, include_evaluations=True
|
||||||
)
|
)
|
||||||
if table_html:
|
if table_html:
|
||||||
|
@ -58,7 +58,7 @@ from app.scodoc import (
|
|||||||
)
|
)
|
||||||
from app.scodoc.html_sidebar import retreive_formsemestre_from_request
|
from app.scodoc.html_sidebar import retreive_formsemestre_from_request
|
||||||
from app.scodoc.sco_bulletins import etud_descr_situation_semestre
|
from app.scodoc.sco_bulletins import etud_descr_situation_semestre
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences, ScoValueError
|
||||||
from app.scodoc.sco_formsemestre_validation import formsemestre_recap_parcours_table
|
from app.scodoc.sco_formsemestre_validation import formsemestre_recap_parcours_table
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
@ -473,7 +473,7 @@ def fiche_etud(etudid=None):
|
|||||||
if last_formsemestre and last_formsemestre.formation.is_apc():
|
if last_formsemestre and last_formsemestre.formation.is_apc():
|
||||||
try:
|
try:
|
||||||
but_cursus = cursus_but.EtudCursusBUT(etud, last_formsemestre.formation)
|
but_cursus = cursus_but.EtudCursusBUT(etud, last_formsemestre.formation)
|
||||||
except ScoValueError:
|
except (ScoValueError, ScoNoReferentielCompetences):
|
||||||
but_cursus = None
|
but_cursus = None
|
||||||
refcomp = last_formsemestre.formation.referentiel_competence
|
refcomp = last_formsemestre.formation.referentiel_competence
|
||||||
if refcomp:
|
if refcomp:
|
||||||
|
@ -112,7 +112,7 @@ def formsemestre_recapcomplet(
|
|||||||
visible_col_ids=visible_col_ids,
|
visible_col_ids=visible_col_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
table_html, _, freq_codes_annuels = _formsemestre_recapcomplet_to_html(
|
table_html, _, freq_codes_annuels, warnings = _formsemestre_recapcomplet_to_html(
|
||||||
formsemestre,
|
formsemestre,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
mode_jury=mode_jury,
|
mode_jury=mode_jury,
|
||||||
@ -120,11 +120,17 @@ def formsemestre_recapcomplet(
|
|||||||
selected_etudid=selected_etudid,
|
selected_etudid=selected_etudid,
|
||||||
)
|
)
|
||||||
|
|
||||||
H = [
|
H = []
|
||||||
# sco_formsemestre_status.formsemestre_status_head(
|
if warnings:
|
||||||
# formsemestre_id=formsemestre_id
|
H.append(
|
||||||
# ),
|
f"""
|
||||||
]
|
<div class="sco_box table-warnings">
|
||||||
|
<div class="sco_box_title">Avertissements</div>
|
||||||
|
<ul><li>
|
||||||
|
{'</li><li>'.join(warnings)}
|
||||||
|
</li></ul>
|
||||||
|
</div>"""
|
||||||
|
)
|
||||||
if len(formsemestre.inscriptions) > 0:
|
if len(formsemestre.inscriptions) > 0:
|
||||||
H.append(
|
H.append(
|
||||||
f"""<form id="export_menu" name="f" method="get" action="{request.base_url}">
|
f"""<form id="export_menu" name="f" method="get" action="{request.base_url}">
|
||||||
@ -300,15 +306,17 @@ def _formsemestre_recapcomplet_to_html(
|
|||||||
if tabformat not in ("html", "evals"):
|
if tabformat not in ("html", "evals"):
|
||||||
raise ScoValueError("invalid table format")
|
raise ScoValueError("invalid table format")
|
||||||
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
table_html, table, freq_codes_annuels = gen_formsemestre_recapcomplet_html_table(
|
table_html, table, freq_codes_annuels, warnings = (
|
||||||
formsemestre,
|
gen_formsemestre_recapcomplet_html_table(
|
||||||
res,
|
formsemestre,
|
||||||
include_evaluations=(tabformat == "evals"),
|
res,
|
||||||
mode_jury=mode_jury,
|
include_evaluations=(tabformat == "evals"),
|
||||||
filename=filename,
|
mode_jury=mode_jury,
|
||||||
selected_etudid=selected_etudid,
|
filename=filename,
|
||||||
|
selected_etudid=selected_etudid,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return table_html, table, freq_codes_annuels
|
return table_html, table, freq_codes_annuels, warnings
|
||||||
|
|
||||||
|
|
||||||
def _formsemestre_recapcomplet_to_file(
|
def _formsemestre_recapcomplet_to_file(
|
||||||
@ -473,7 +481,7 @@ def gen_formsemestre_recapcomplet_html_table(
|
|||||||
mode_jury=False,
|
mode_jury=False,
|
||||||
filename="",
|
filename="",
|
||||||
selected_etudid=None,
|
selected_etudid=None,
|
||||||
) -> tuple[str, TableRecap, collections.Counter]:
|
) -> tuple[str, TableRecap, collections.Counter, list[str]]:
|
||||||
"""Construit table recap pour le BUT
|
"""Construit table recap pour le BUT
|
||||||
Cache le résultat pour le semestre.
|
Cache le résultat pour le semestre.
|
||||||
Note: on cache le HTML et non l'objet Table.
|
Note: on cache le HTML et non l'objet Table.
|
||||||
@ -508,11 +516,12 @@ def gen_formsemestre_recapcomplet_html_table(
|
|||||||
freq_codes_annuels = (
|
freq_codes_annuels = (
|
||||||
table.freq_codes_annuels if hasattr(table, "freq_codes_annuels") else None
|
table.freq_codes_annuels if hasattr(table, "freq_codes_annuels") else None
|
||||||
)
|
)
|
||||||
cache_class.set(formsemestre.id, (table_html, freq_codes_annuels))
|
warnings = table.warnings
|
||||||
|
cache_class.set(formsemestre.id, (table_html, freq_codes_annuels, warnings))
|
||||||
else:
|
else:
|
||||||
table_html, freq_codes_annuels = table_html_cached
|
table_html, freq_codes_annuels, warnings = table_html_cached
|
||||||
|
|
||||||
return table_html, table, freq_codes_annuels
|
return table_html, table, freq_codes_annuels, warnings
|
||||||
|
|
||||||
|
|
||||||
def _gen_formsemestre_recapcomplet_table(
|
def _gen_formsemestre_recapcomplet_table(
|
||||||
|
@ -65,4 +65,10 @@ div.gt_caption {
|
|||||||
|
|
||||||
.dt-scroll-foot {
|
.dt-scroll-foot {
|
||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table-warnings {
|
||||||
|
background-color: yellow;
|
||||||
|
color: darkred;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
@ -1284,6 +1284,10 @@ div.sco_box_title {
|
|||||||
background-color: rgb(209, 255, 214);
|
background-color: rgb(209, 255, 214);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.sco_box.sco_dashed {
|
||||||
|
border: 1px dashed red;
|
||||||
|
}
|
||||||
|
|
||||||
div.vertical_spacing_but {
|
div.vertical_spacing_but {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ from app.scodoc.codes_cursus import (
|
|||||||
BUT_BARRE_RCUE,
|
BUT_BARRE_RCUE,
|
||||||
BUT_RCUE_SUFFISANT,
|
BUT_RCUE_SUFFISANT,
|
||||||
)
|
)
|
||||||
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.tables.recap import RowRecap, TableRecap
|
from app.tables.recap import RowRecap, TableRecap
|
||||||
|
|
||||||
@ -201,9 +202,13 @@ class TableJury(TableRecap):
|
|||||||
self.group_titles[group] = f"Compétences {annee}"
|
self.group_titles[group] = f"Compétences {annee}"
|
||||||
for row in self.rows:
|
for row in self.rows:
|
||||||
etud = row.etud
|
etud = row.etud
|
||||||
cursus_dict = cursus_but.EtudCursusBUT(
|
try:
|
||||||
etud, self.res.formsemestre.formation
|
cursus_dict = cursus_but.EtudCursusBUT(
|
||||||
).to_dict()
|
etud, self.res.formsemestre.formation
|
||||||
|
).to_dict()
|
||||||
|
except ScoValueError as exc:
|
||||||
|
cursus_dict = {}
|
||||||
|
self.warnings.append(exc.args[0])
|
||||||
first = True
|
first = True
|
||||||
for competence_id in cursus_dict:
|
for competence_id in cursus_dict:
|
||||||
for annee in ("BUT1", "BUT2", "BUT3"):
|
for annee in ("BUT1", "BUT2", "BUT3"):
|
||||||
|
@ -117,6 +117,8 @@ class Table(Element):
|
|||||||
#
|
#
|
||||||
self.caption = caption
|
self.caption = caption
|
||||||
self.origin = origin
|
self.origin = origin
|
||||||
|
self.warnings: list[str] = []
|
||||||
|
"liste d'avertissements rencontrés en construisant la table"
|
||||||
|
|
||||||
def _prepare(self):
|
def _prepare(self):
|
||||||
"""Prepare the table before generation:
|
"""Prepare the table before generation:
|
||||||
|
@ -124,6 +124,17 @@ Choisissez un parcours...
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if current_user.is_administrator() %}
|
||||||
|
<div class="sco_box sco_dashed">
|
||||||
|
<b>Vous êtes super-administrateur.</b>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="force_modification" name="force_modification">
|
||||||
|
<label for="force_modification">forcer modification même si décisions de jury enregistrées (dangereux !)</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% if parcour %}
|
{% if parcour %}
|
||||||
<div class="help">
|
<div class="help">
|
||||||
@ -150,7 +161,7 @@ Choisissez un parcours...
|
|||||||
function ue_assoc_niveau(event, niveau_id) {
|
function ue_assoc_niveau(event, niveau_id) {
|
||||||
let ue_id = event.target.value;
|
let ue_id = event.target.value;
|
||||||
let url = "";
|
let url = "";
|
||||||
let must_reload = false;
|
let force = document.getElementById('force_modification').checked;
|
||||||
if (ue_id == "") {
|
if (ue_id == "") {
|
||||||
/* Dé-associe */
|
/* Dé-associe */
|
||||||
ue_id = event.target.dataset.ue_id;
|
ue_id = event.target.dataset.ue_id;
|
||||||
@ -162,7 +173,9 @@ function ue_assoc_niveau(event, niveau_id) {
|
|||||||
)
|
)
|
||||||
}}';
|
}}';
|
||||||
url = desassoc_url.replace('11111', ue_id);
|
url = desassoc_url.replace('11111', ue_id);
|
||||||
must_reload=true;
|
if (force) {
|
||||||
|
url += '/force';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const assoc_url = '{{
|
const assoc_url = '{{
|
||||||
url_for(
|
url_for(
|
||||||
@ -172,6 +185,9 @@ function ue_assoc_niveau(event, niveau_id) {
|
|||||||
)
|
)
|
||||||
}}';
|
}}';
|
||||||
url = assoc_url.replace('11111', ue_id).replace('22222', niveau_id);
|
url = assoc_url.replace('11111', ue_id).replace('22222', niveau_id);
|
||||||
|
if (force) {
|
||||||
|
url += '/force';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -75,6 +75,8 @@ ETUDID = 1
|
|||||||
NIP = "NIP2"
|
NIP = "NIP2"
|
||||||
INE = "INE1"
|
INE = "INE1"
|
||||||
|
|
||||||
|
BUL_NB_FIELDS = 15
|
||||||
|
|
||||||
|
|
||||||
def test_etudiants_courant(api_headers):
|
def test_etudiants_courant(api_headers):
|
||||||
"""
|
"""
|
||||||
@ -508,7 +510,7 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
bulletin = r.json()
|
bulletin = r.json()
|
||||||
assert len(bulletin) == 14 # HARDCODED
|
assert len(bulletin) == BUL_NB_FIELDS
|
||||||
|
|
||||||
assert verify_fields(bulletin, BULLETIN_FIELDS) is True
|
assert verify_fields(bulletin, BULLETIN_FIELDS) is True
|
||||||
assert isinstance(bulletin["version"], str)
|
assert isinstance(bulletin["version"], str)
|
||||||
@ -845,7 +847,7 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
bul = r.json()
|
bul = r.json()
|
||||||
assert len(bul) == 14 # HARDCODED
|
assert len(bul) == BUL_NB_FIELDS
|
||||||
|
|
||||||
######### Test code ine #########
|
######### Test code ine #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
@ -856,7 +858,7 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
bul = r.json()
|
bul = r.json()
|
||||||
assert len(bul) == 14 # HARDCODED
|
assert len(bul) == BUL_NB_FIELDS
|
||||||
|
|
||||||
######## Bulletin BUT court en pdf #########
|
######## Bulletin BUT court en pdf #########
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
@ -915,15 +917,15 @@ def test_etudiant_bulletin_semestre(api_headers):
|
|||||||
bul = GET(
|
bul = GET(
|
||||||
f"/etudiant/etudid/{ETUDID}/formsemestre/1/bulletin/short", headers=api_headers
|
f"/etudiant/etudid/{ETUDID}/formsemestre/1/bulletin/short", headers=api_headers
|
||||||
)
|
)
|
||||||
assert len(bul) == 14 # HARDCODED
|
assert len(bul) == BUL_NB_FIELDS
|
||||||
|
|
||||||
######### Test code nip #########
|
######### Test code nip #########
|
||||||
bul = GET(f"/etudiant/nip/{NIP}/formsemestre/1/bulletin/short", headers=api_headers)
|
bul = GET(f"/etudiant/nip/{NIP}/formsemestre/1/bulletin/short", headers=api_headers)
|
||||||
assert len(bul) == 14 # HARDCODED
|
assert len(bul) == BUL_NB_FIELDS
|
||||||
|
|
||||||
######### Test code ine #########
|
######### Test code ine #########
|
||||||
bul = GET(f"/etudiant/ine/{INE}/formsemestre/1/bulletin/short", headers=api_headers)
|
bul = GET(f"/etudiant/ine/{INE}/formsemestre/1/bulletin/short", headers=api_headers)
|
||||||
assert len(bul) == 14 # HARDCODED
|
assert len(bul) == BUL_NB_FIELDS
|
||||||
|
|
||||||
################### SHORT + PDF #####################
|
################### SHORT + PDF #####################
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user