forked from ScoDoc/ScoDoc
Améliore UI gestion des UE antérieures
This commit is contained in:
parent
52db344926
commit
66983ff767
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
from flask import g, url_for
|
from flask import g, url_for
|
||||||
from flask_json import as_json
|
from flask_json import as_json
|
||||||
from flask_login import login_required
|
from flask_login import current_user, login_required
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import db, log
|
from app import db, log
|
||||||
@ -29,6 +29,7 @@ from app.models import (
|
|||||||
)
|
)
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from app.scodoc.sco_utils import json_error
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre/<int:formsemestre_id>/decisions_jury")
|
@bp.route("/formsemestre/<int:formsemestre_id>/decisions_jury")
|
||||||
@ -73,7 +74,7 @@ def _news_delete_jury_etud(etud: Identite):
|
|||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoEtudInscrit)
|
@permission_required(Permission.ScoView)
|
||||||
@as_json
|
@as_json
|
||||||
def validation_ue_delete(etudid: int, validation_id: int):
|
def validation_ue_delete(etudid: int, validation_id: int):
|
||||||
"Efface cette validation"
|
"Efface cette validation"
|
||||||
@ -90,7 +91,7 @@ def validation_ue_delete(etudid: int, validation_id: int):
|
|||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoEtudInscrit)
|
@permission_required(Permission.ScoView)
|
||||||
@as_json
|
@as_json
|
||||||
def validation_formsemestre_delete(etudid: int, validation_id: int):
|
def validation_formsemestre_delete(etudid: int, validation_id: int):
|
||||||
"Efface cette validation"
|
"Efface cette validation"
|
||||||
@ -106,6 +107,24 @@ def _validation_ue_delete(etudid: int, validation_id: int):
|
|||||||
validation = ScolarFormSemestreValidation.query.filter_by(
|
validation = ScolarFormSemestreValidation.query.filter_by(
|
||||||
id=validation_id, etudid=etudid
|
id=validation_id, etudid=etudid
|
||||||
).first_or_404()
|
).first_or_404()
|
||||||
|
# Vérification de la permission:
|
||||||
|
# A le droit de supprimer cette validation: le chef de dept ou quelqu'un ayant
|
||||||
|
# le droit de saisir des décisions de jury dans le formsemestre concerné s'il y en a un
|
||||||
|
# (c'est le cas pour les validations de jury, mais pas pour les "antérieures" non
|
||||||
|
# rattachées à un formsemestre)
|
||||||
|
if not g.scodoc_dept: # accès API
|
||||||
|
if not current_user.has_permission(Permission.ScoEtudInscrit):
|
||||||
|
return json_error(403, "validation_delete: non autorise")
|
||||||
|
else:
|
||||||
|
if validation.formsemestre:
|
||||||
|
if (
|
||||||
|
validation.formsemestre.dept_id != g.scodoc_dept_id
|
||||||
|
) or not validation.formsemestre.can_edit_jury():
|
||||||
|
return json_error(403, "validation_delete: non autorise")
|
||||||
|
elif not current_user.has_permission(Permission.ScoEtudInscrit):
|
||||||
|
# Validation non rattachée à un semestre: on doit être chef
|
||||||
|
return json_error(403, "validation_delete: non autorise")
|
||||||
|
|
||||||
log(f"validation_ue_delete: etuid={etudid} {validation}")
|
log(f"validation_ue_delete: etuid={etudid} {validation}")
|
||||||
db.session.delete(validation)
|
db.session.delete(validation)
|
||||||
sco_cache.invalidate_formsemestre_etud(etud)
|
sco_cache.invalidate_formsemestre_etud(etud)
|
||||||
|
@ -8,6 +8,8 @@ from app import log
|
|||||||
from app.models import SHORT_STR_LEN
|
from app.models import SHORT_STR_LEN
|
||||||
from app.models import CODE_STR_LEN
|
from app.models import CODE_STR_LEN
|
||||||
from app.models.events import Scolog
|
from app.models.events import Scolog
|
||||||
|
from app.scodoc import sco_cache
|
||||||
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
class ScolarFormSemestreValidation(db.Model):
|
class ScolarFormSemestreValidation(db.Model):
|
||||||
@ -70,6 +72,14 @@ class ScolarFormSemestreValidation(db.Model):
|
|||||||
return f"""décision sur semestre {self.formsemestre.titre_mois()} du {
|
return f"""décision sur semestre {self.formsemestre.titre_mois()} du {
|
||||||
self.event_date.strftime("%d/%m/%Y")}"""
|
self.event_date.strftime("%d/%m/%Y")}"""
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"Efface cette validation"
|
||||||
|
log(f"{self.__class__.__name__}.delete({self})")
|
||||||
|
etud = self.etud
|
||||||
|
db.session.delete(self)
|
||||||
|
db.session.commit()
|
||||||
|
sco_cache.invalidate_formsemestre_etud(etud)
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
"as a dict"
|
"as a dict"
|
||||||
d = dict(self.__dict__)
|
d = dict(self.__dict__)
|
||||||
@ -79,15 +89,22 @@ class ScolarFormSemestreValidation(db.Model):
|
|||||||
def html(self, detail=False) -> str:
|
def html(self, detail=False) -> str:
|
||||||
"Affichage html"
|
"Affichage html"
|
||||||
if self.ue_id is not None:
|
if self.ue_id is not None:
|
||||||
return f"""Validation de l'UE <b>{self.ue.acronyme}</b>
|
moyenne = (
|
||||||
|
f", moyenne {scu.fmt_note(self.moy_ue)}/20 "
|
||||||
|
if self.moy_ue is not None
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
return f"""Validation
|
||||||
|
{'<span class="redboldtext">externe</span>' if self.is_external else ""}
|
||||||
|
de l'UE <b>{self.ue.acronyme}</b>
|
||||||
{('parcours <span class="parcours">'
|
{('parcours <span class="parcours">'
|
||||||
+ ", ".join([p.code for p in self.ue.parcours]))
|
+ ", ".join([p.code for p in self.ue.parcours]))
|
||||||
+ "</span>"
|
+ "</span>"
|
||||||
if self.ue.parcours else ""}
|
if self.ue.parcours else ""}
|
||||||
de {self.ue.formation.acronyme}
|
de {self.ue.formation.acronyme}
|
||||||
{("émise par " + self.formsemestre.html_link_status())
|
{("émise par " + self.formsemestre.html_link_status())
|
||||||
if self.formsemestre else ""}
|
if self.formsemestre else "externe/antérieure"}
|
||||||
: <b>{self.code}</b>
|
: <b>{self.code}</b>{moyenne}
|
||||||
le {self.event_date.strftime("%d/%m/%Y")} à {self.event_date.strftime("%Hh%M")}
|
le {self.event_date.strftime("%d/%m/%Y")} à {self.event_date.strftime("%Hh%M")}
|
||||||
"""
|
"""
|
||||||
else:
|
else:
|
||||||
|
@ -1238,7 +1238,7 @@ def make_menu_autres_operations(
|
|||||||
"enabled": current_user.has_permission(Permission.ScoImplement),
|
"enabled": current_user.has_permission(Permission.ScoImplement),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Enregistrer une validation d'UE antérieure",
|
"title": "Gérer les validations d'UEs antérieures",
|
||||||
"endpoint": "notes.formsemestre_validate_previous_ue",
|
"endpoint": "notes.formsemestre_validate_previous_ue",
|
||||||
"args": {
|
"args": {
|
||||||
"formsemestre_id": formsemestre.id,
|
"formsemestre_id": formsemestre.id,
|
||||||
|
@ -972,7 +972,7 @@ def do_formsemestre_validate_ue(
|
|||||||
moy_ue = ue_status["moy"] if ue_status else ""
|
moy_ue = ue_status["moy"] if ue_status else ""
|
||||||
args["moy_ue"] = moy_ue
|
args["moy_ue"] = moy_ue
|
||||||
log("formsemestre_validate_ue: create %s" % args)
|
log("formsemestre_validate_ue: create %s" % args)
|
||||||
if code != None:
|
if code is not None:
|
||||||
scolar_formsemestre_validation_create(cnx, args)
|
scolar_formsemestre_validation_create(cnx, args)
|
||||||
else:
|
else:
|
||||||
log("formsemestre_validate_ue: code is None, not recording validation")
|
log("formsemestre_validate_ue: code is None, not recording validation")
|
||||||
|
@ -502,7 +502,7 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
else:
|
else:
|
||||||
clone_form = ""
|
clone_form = ""
|
||||||
bonus_div = """<div id="bonus_description"></div>"""
|
bonus_div = """<div id="bonus_description"></div>"""
|
||||||
ue_div = """<div id="ue_list_code"></div>"""
|
ue_div = """<div id="ue_list_code" class="sco_box sco_green_bg"></div>"""
|
||||||
return (
|
return (
|
||||||
"\n".join(H)
|
"\n".join(H)
|
||||||
+ tf[1]
|
+ tf[1]
|
||||||
@ -1375,13 +1375,12 @@ def _ue_table_modules(
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def ue_sharing_code(ue_code=None, ue_id=None, hide_ue_id=None):
|
def ue_sharing_code(ue_code: str = "", ue_id: int = None, hide_ue_id: int = None):
|
||||||
"""HTML list of UE sharing this code
|
"""HTML list of UE sharing this code
|
||||||
Either ue_code or ue_id may be specified.
|
Either ue_code or ue_id may be specified.
|
||||||
hide_ue_id spécifie un id à retirer de la liste.
|
hide_ue_id spécifie un id à retirer de la liste.
|
||||||
"""
|
"""
|
||||||
ue_code = str(ue_code)
|
if ue_id is not None:
|
||||||
if ue_id:
|
|
||||||
ue = UniteEns.query.get_or_404(ue_id)
|
ue = UniteEns.query.get_or_404(ue_id)
|
||||||
if not ue_code:
|
if not ue_code:
|
||||||
ue_code = ue.ue_code
|
ue_code = ue.ue_code
|
||||||
@ -1400,29 +1399,36 @@ def ue_sharing_code(ue_code=None, ue_id=None, hide_ue_id=None):
|
|||||||
.filter_by(dept_id=g.scodoc_dept_id)
|
.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
if hide_ue_id: # enlève l'ue de depart
|
if hide_ue_id is not None: # enlève l'ue de depart
|
||||||
q_ues = q_ues.filter(UniteEns.id != hide_ue_id)
|
q_ues = q_ues.filter(UniteEns.id != hide_ue_id)
|
||||||
|
|
||||||
ues = q_ues.all()
|
ues = q_ues.all()
|
||||||
|
msg = " dans les formations du département "
|
||||||
if not ues:
|
if not ues:
|
||||||
if ue_id:
|
if ue_id is not None:
|
||||||
return (
|
return f"""<span class="ue_share">Seule UE avec code {
|
||||||
f"""<span class="ue_share">Seule UE avec code {ue_code or '-'}</span>"""
|
ue_code if ue_code is not None else '-'}{msg}</span>"""
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return f"""<span class="ue_share">Aucune UE avec code {ue_code or '-'}</span>"""
|
return f"""<span class="ue_share">Aucune UE avec code {
|
||||||
|
ue_code if ue_code is not None else '-'}{msg}</span>"""
|
||||||
H = []
|
H = []
|
||||||
if ue_id:
|
if ue_id:
|
||||||
H.append(
|
H.append(
|
||||||
f"""<span class="ue_share">Autres UE avec le code {ue_code or '-'}:</span>"""
|
f"""<span class="ue_share">Pour information, autres UEs avec le code {
|
||||||
|
ue_code if ue_code is not None else '-'}{msg}:</span>"""
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
H.append(f"""<span class="ue_share">UE avec le code {ue_code or '-'}:</span>""")
|
H.append(
|
||||||
|
f"""<span class="ue_share">UE avec le code {
|
||||||
|
ue_code if ue_code is not None else '-'}{msg}:</span>"""
|
||||||
|
)
|
||||||
H.append("<ul>")
|
H.append("<ul>")
|
||||||
for ue in ues:
|
for ue in ues:
|
||||||
H.append(
|
H.append(
|
||||||
f"""<li>{ue.acronyme} ({ue.titre}) dans <a class="stdlink"
|
f"""<li>{ue.acronyme} ({ue.titre}) dans
|
||||||
href="{url_for("notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation.id)}"
|
<a class="stdlink" href="{
|
||||||
|
url_for("notes.ue_table",
|
||||||
|
scodoc_dept=g.scodoc_dept, formation_id=ue.formation.id)}"
|
||||||
>{ue.formation.acronyme} ({ue.formation.titre})</a>, version {ue.formation.version}
|
>{ue.formation.acronyme} ({ue.formation.titre})</a>, version {ue.formation.version}
|
||||||
</li>
|
</li>
|
||||||
"""
|
"""
|
||||||
|
@ -517,7 +517,7 @@ def _record_ue_validations_and_coefs(
|
|||||||
)
|
)
|
||||||
assert code is None or (note) # si code validant, il faut une note
|
assert code is None or (note) # si code validant, il faut une note
|
||||||
sco_formsemestre_validation.do_formsemestre_validate_previous_ue(
|
sco_formsemestre_validation.do_formsemestre_validate_previous_ue(
|
||||||
formsemestre.id,
|
formsemestre,
|
||||||
etud.id,
|
etud.id,
|
||||||
ue.id,
|
ue.id,
|
||||||
note,
|
note,
|
||||||
|
@ -31,8 +31,9 @@ import time
|
|||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import url_for, flash, g, request
|
from flask import url_for, flash, g, request
|
||||||
from app.models.etudiants import Identite
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from app.models.etudiants import Identite
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import db, log
|
from app import db, log
|
||||||
@ -1081,62 +1082,44 @@ def formsemestre_validation_suppress_etud(formsemestre_id, etudid):
|
|||||||
) # > suppr. decision jury (peut affecter de plusieurs semestres utilisant UE capitalisée)
|
) # > suppr. decision jury (peut affecter de plusieurs semestres utilisant UE capitalisée)
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_validate_previous_ue(formsemestre_id, etudid):
|
def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite):
|
||||||
"""Form. saisie UE validée hors ScoDoc
|
"""Form. saisie UE validée hors ScoDoc
|
||||||
(pour étudiants arrivant avec un UE antérieurement validée).
|
(pour étudiants arrivant avec un UE antérieurement validée).
|
||||||
"""
|
"""
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
formation: Formation = formsemestre.formation
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
formation: Formation = Formation.query.get_or_404(sem["formation_id"])
|
|
||||||
H = [
|
|
||||||
html_sco_header.sco_header(
|
|
||||||
page_title="Validation UE",
|
|
||||||
javascripts=["js/validate_previous_ue.js"],
|
|
||||||
),
|
|
||||||
'<table style="width: 100%"><tr><td>',
|
|
||||||
"""<h2 class="formsemestre">%s: validation d'une UE antérieure</h2>"""
|
|
||||||
% etud["nomprenom"],
|
|
||||||
(
|
|
||||||
'</td><td style="text-align: right;"><a href="%s">%s</a></td></tr></table>'
|
|
||||||
% (
|
|
||||||
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid),
|
|
||||||
sco_photos.etud_photo_html(etud, title="fiche de %s" % etud["nom"]),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
f"""<p class="help">Utiliser cette page pour enregistrer une UE validée antérieurement,
|
|
||||||
<em>dans un semestre hors ScoDoc</em>.</p>
|
|
||||||
<p><b>Les UE validées dans ScoDoc sont déjà
|
|
||||||
automatiquement prises en compte</b>. Cette page n'est utile que pour les étudiants ayant
|
|
||||||
suivi un début de cursus dans <b>un autre établissement</b>, ou bien dans un semestre géré
|
|
||||||
<b>sans ScoDoc</b> et qui <b>redouble</b> ce semestre
|
|
||||||
(<em>ne pas utiliser pour les semestres précédents !</em>).
|
|
||||||
</p>
|
|
||||||
<p>Notez que l'UE est validée, avec enregistrement immédiat de la décision et
|
|
||||||
l'attribution des ECTS.</p>
|
|
||||||
<p>On ne peut prendre en compte ici que les UE du cursus <b>{formation.titre}</b></p>
|
|
||||||
""",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Toutes les UE de cette formation sont présentées (même celles des autres semestres)
|
# Toutes les UEs non bonus de cette formation sont présentées
|
||||||
ues = formation.ues.order_by(UniteEns.numero)
|
# avec indice de semestre <= semestre courant ou NULL
|
||||||
ue_names = ["Choisir..."] + [f"{ue.acronyme} {ue.titre}" for ue in ues]
|
ues = formation.ues.filter(
|
||||||
|
UniteEns.type != UE_SPORT,
|
||||||
|
db.or_(
|
||||||
|
UniteEns.semestre_idx == None,
|
||||||
|
UniteEns.semestre_idx <= formsemestre.semestre_id,
|
||||||
|
),
|
||||||
|
).order_by(UniteEns.semestre_idx, UniteEns.numero)
|
||||||
|
|
||||||
|
ue_names = ["Choisir..."] + [
|
||||||
|
f"""{('S'+str(ue.semestre_idx)+' : ') if ue.semestre_idx is not None else ''
|
||||||
|
}{ue.acronyme} {ue.titre} ({ue.ue_code or ""})"""
|
||||||
|
for ue in ues
|
||||||
|
]
|
||||||
ue_ids = [""] + [ue.id for ue in ues]
|
ue_ids = [""] + [ue.id for ue in ues]
|
||||||
tf = TrivialFormulator(
|
form_descr = [
|
||||||
request.base_url,
|
("etudid", {"input_type": "hidden"}),
|
||||||
scu.get_request_args(),
|
("formsemestre_id", {"input_type": "hidden"}),
|
||||||
(
|
(
|
||||||
("etudid", {"input_type": "hidden"}),
|
"ue_id",
|
||||||
("formsemestre_id", {"input_type": "hidden"}),
|
{
|
||||||
(
|
"input_type": "menu",
|
||||||
"ue_id",
|
"title": "Unité d'Enseignement (UE)",
|
||||||
{
|
"allow_null": False,
|
||||||
"input_type": "menu",
|
"allowed_values": ue_ids,
|
||||||
"title": "Unité d'Enseignement (UE)",
|
"labels": ue_names,
|
||||||
"allow_null": False,
|
},
|
||||||
"allowed_values": ue_ids,
|
),
|
||||||
"labels": ue_names,
|
]
|
||||||
},
|
if not formation.is_apc():
|
||||||
),
|
form_descr.append(
|
||||||
(
|
(
|
||||||
"semestre_id",
|
"semestre_id",
|
||||||
{
|
{
|
||||||
@ -1147,69 +1130,159 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid):
|
|||||||
"allowed_values": [""] + [x for x in range(11)],
|
"allowed_values": [""] + [x for x in range(11)],
|
||||||
"labels": ["-"] + list(range(11)),
|
"labels": ["-"] + list(range(11)),
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
(
|
)
|
||||||
"date",
|
form_descr += [
|
||||||
{
|
(
|
||||||
"input_type": "date",
|
"date",
|
||||||
"size": 9,
|
{
|
||||||
"explanation": "j/m/a",
|
"input_type": "date",
|
||||||
"default": time.strftime("%d/%m/%Y"),
|
"size": 9,
|
||||||
},
|
"explanation": "j/m/a",
|
||||||
),
|
"default": time.strftime("%d/%m/%Y"),
|
||||||
(
|
},
|
||||||
"moy_ue",
|
|
||||||
{
|
|
||||||
"type": "float",
|
|
||||||
"allow_null": False,
|
|
||||||
"min_value": 0,
|
|
||||||
"max_value": 20,
|
|
||||||
"title": "Moyenne (/20) obtenue dans cette UE:",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
cancelbutton="Annuler",
|
(
|
||||||
|
"moy_ue",
|
||||||
|
{
|
||||||
|
"type": "float",
|
||||||
|
"allow_null": False,
|
||||||
|
"min_value": 0,
|
||||||
|
"max_value": 20,
|
||||||
|
"title": "Moyenne (/20) obtenue dans cette UE:",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
tf = TrivialFormulator(
|
||||||
|
request.base_url,
|
||||||
|
scu.get_request_args(),
|
||||||
|
form_descr,
|
||||||
|
cancelbutton="Revenir au bulletin",
|
||||||
submitlabel="Enregistrer validation d'UE",
|
submitlabel="Enregistrer validation d'UE",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
X = """
|
return f"""
|
||||||
<div id="ue_list_etud_validations"><!-- filled by get_etud_ue_cap_html --></div>
|
{html_sco_header.sco_header(
|
||||||
<div id="ue_list_code"><!-- filled by ue_sharing_code --></div>
|
page_title="Validation UE antérieure",
|
||||||
"""
|
javascripts=["js/validate_previous_ue.js"],
|
||||||
warn, ue_multiples = check_formation_ues(formation.id)
|
cssstyles=["css/jury_delete_manual.css"],
|
||||||
return "\n".join(H) + tf[1] + X + warn + html_sco_header.sco_footer()
|
etudid=etud.id,
|
||||||
elif tf[0] == -1:
|
)}
|
||||||
return flask.redirect(
|
<h2 class="formsemestre">Gestion des validations d'UEs antérieures
|
||||||
scu.NotesURL()
|
de {etud.html_link_fiche()}
|
||||||
+ "/formsemestre_status?formsemestre_id="
|
</h2>
|
||||||
+ str(formsemestre_id)
|
|
||||||
)
|
<p class="help">Utiliser cette page pour enregistrer une UE validée antérieurement,
|
||||||
else:
|
<em>dans un semestre hors ScoDoc</em>.</p>
|
||||||
if tf[2]["semestre_id"]:
|
<p class="expl"><b>Les UE validées dans ScoDoc sont déjà
|
||||||
semestre_id = int(tf[2]["semestre_id"])
|
automatiquement prises en compte</b>. Cette page n'est utile que pour les étudiants ayant
|
||||||
else:
|
suivi un début de cursus dans <b>un autre établissement</b>, ou bien dans un semestre géré
|
||||||
semestre_id = None
|
<b>sans ScoDoc</b> et qui <b>redouble</b> ce semestre
|
||||||
do_formsemestre_validate_previous_ue(
|
(<em>pour les semestres précédents gérés avec ScoDoc,
|
||||||
formsemestre_id,
|
passer par la page jury normale)</em>).
|
||||||
etudid,
|
</p>
|
||||||
tf[2]["ue_id"],
|
<p>Notez que l'UE est validée (ADM), avec enregistrement immédiat de la décision et
|
||||||
tf[2]["moy_ue"],
|
l'attribution des ECTS.</p>
|
||||||
tf[2]["date"],
|
<p>On ne peut valider ici que les UEs du cursus <b>{formation.titre}</b></p>
|
||||||
semestre_id=semestre_id,
|
|
||||||
)
|
{_get_etud_ue_cap_html(etud, formsemestre)}
|
||||||
flash("Validation d'UE enregistrée")
|
|
||||||
|
<div class="sco_box">
|
||||||
|
<div class="sco_box_title">
|
||||||
|
Enregistrer une UE antérieure
|
||||||
|
</div>
|
||||||
|
{tf[1]}
|
||||||
|
</div>
|
||||||
|
<div id="ue_list_code" class="sco_box sco_green_bg">
|
||||||
|
<!-- filled by ue_sharing_code -->
|
||||||
|
</div>
|
||||||
|
{check_formation_ues(formation.id)[0]}
|
||||||
|
{html_sco_header.sco_footer()}
|
||||||
|
"""
|
||||||
|
|
||||||
|
dest_url = url_for(
|
||||||
|
"notes.formsemestre_validate_previous_ue",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=formsemestre.id,
|
||||||
|
etudid=etud.id,
|
||||||
|
)
|
||||||
|
if tf[0] == -1:
|
||||||
return flask.redirect(
|
return flask.redirect(
|
||||||
url_for(
|
url_for(
|
||||||
"notes.formsemestre_bulletinetud",
|
"notes.formsemestre_bulletinetud",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=formsemestre_id,
|
formsemestre_id=formsemestre.id,
|
||||||
etudid=etudid,
|
etudid=etud.id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if tf[2].get("semestre_id"):
|
||||||
|
semestre_id = int(tf[2]["semestre_id"])
|
||||||
|
else:
|
||||||
|
semestre_id = None
|
||||||
|
|
||||||
|
do_formsemestre_validate_previous_ue(
|
||||||
|
formsemestre,
|
||||||
|
etud.id,
|
||||||
|
tf[2]["ue_id"],
|
||||||
|
tf[2]["moy_ue"],
|
||||||
|
tf[2]["date"],
|
||||||
|
semestre_id=semestre_id,
|
||||||
|
)
|
||||||
|
flash("Validation d'UE enregistrée")
|
||||||
|
return flask.redirect(dest_url)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_etud_ue_cap_html(etud: Identite, formsemestre: FormSemestre) -> str:
|
||||||
|
"""HTML listant les validations d'UEs pour cet étudiant dans des formations de même
|
||||||
|
code que celle du formsemestre indiqué.
|
||||||
|
"""
|
||||||
|
validations: list[ScolarFormSemestreValidation] = (
|
||||||
|
ScolarFormSemestreValidation.query.filter_by(etudid=etud.id)
|
||||||
|
.join(UniteEns)
|
||||||
|
.join(Formation)
|
||||||
|
.filter_by(formation_code=formsemestre.formation.formation_code)
|
||||||
|
.order_by(
|
||||||
|
sa.desc(UniteEns.semestre_idx),
|
||||||
|
UniteEns.acronyme,
|
||||||
|
sa.desc(ScolarFormSemestreValidation.event_date),
|
||||||
|
)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not validations:
|
||||||
|
return ""
|
||||||
|
H = [
|
||||||
|
f"""<div class="sco_box sco_lightgreen_bg ue_list_etud_validations">
|
||||||
|
<div class="sco_box_title">Validations d'UEs dans cette formation</div>
|
||||||
|
<div class="help">Liste de toutes les UEs validées par {etud.html_link_fiche()},
|
||||||
|
sur des semestres ou déclarées comme "antérieures" (externes).
|
||||||
|
</div>
|
||||||
|
<ul>"""
|
||||||
|
]
|
||||||
|
for validation in validations:
|
||||||
|
if validation.formsemestre_id is None:
|
||||||
|
origine = " enregistrée d'un parcours antérieur (hors ScoDoc)"
|
||||||
|
else:
|
||||||
|
origine = f", du semestre {formsemestre.html_link_status()}"
|
||||||
|
if validation.semestre_id is not None:
|
||||||
|
origine += f" (<b>S{validation.semestre_id}</b>)"
|
||||||
|
H.append(
|
||||||
|
f"""
|
||||||
|
<li>{validation.html()}
|
||||||
|
<form class="inline-form">
|
||||||
|
<button
|
||||||
|
data-v_id="{validation.id}" data-type="validation_ue" data-etudid="{etud.id}"
|
||||||
|
>effacer</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
H.append("</ul></div>")
|
||||||
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def do_formsemestre_validate_previous_ue(
|
def do_formsemestre_validate_previous_ue(
|
||||||
formsemestre_id,
|
formsemestre: FormSemestre,
|
||||||
etudid,
|
etudid,
|
||||||
ue_id,
|
ue_id,
|
||||||
moy_ue,
|
moy_ue,
|
||||||
@ -1222,21 +1295,20 @@ def do_formsemestre_validate_previous_ue(
|
|||||||
Si le coefficient est spécifié, modifie le coefficient de
|
Si le coefficient est spécifié, modifie le coefficient de
|
||||||
cette UE (utile seulement pour les semestres extérieurs).
|
cette UE (utile seulement pour les semestres extérieurs).
|
||||||
"""
|
"""
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
ue: UniteEns = UniteEns.query.get_or_404(ue_id)
|
ue: UniteEns = UniteEns.query.get_or_404(ue_id)
|
||||||
|
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
if ue_coefficient != None:
|
if ue_coefficient != None:
|
||||||
sco_formsemestre.do_formsemestre_uecoef_edit_or_create(
|
sco_formsemestre.do_formsemestre_uecoef_edit_or_create(
|
||||||
cnx, formsemestre_id, ue_id, ue_coefficient
|
cnx, formsemestre.id, ue_id, ue_coefficient
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
sco_formsemestre.do_formsemestre_uecoef_delete(cnx, formsemestre_id, ue_id)
|
sco_formsemestre.do_formsemestre_uecoef_delete(cnx, formsemestre.id, ue_id)
|
||||||
sco_cursus_dut.do_formsemestre_validate_ue(
|
sco_cursus_dut.do_formsemestre_validate_ue(
|
||||||
cnx,
|
cnx,
|
||||||
nt,
|
nt,
|
||||||
formsemestre_id, # "importe" cette UE dans le semestre (new 3/2015)
|
formsemestre.id, # "importe" cette UE dans le semestre (new 3/2015)
|
||||||
etudid,
|
etudid,
|
||||||
ue_id,
|
ue_id,
|
||||||
code,
|
code,
|
||||||
@ -1274,62 +1346,6 @@ def _invalidate_etud_formation_caches(etudid, formation_id):
|
|||||||
) # > modif decision UE (inval tous semestres avec cet etudiant, ok mais conservatif)
|
) # > modif decision UE (inval tous semestres avec cet etudiant, ok mais conservatif)
|
||||||
|
|
||||||
|
|
||||||
def get_etud_ue_cap_html(etudid, formsemestre_id, ue_id):
|
|
||||||
"""Ramene bout de HTML pour pouvoir supprimer une validation de cette UE"""
|
|
||||||
valids = ndb.SimpleDictFetch(
|
|
||||||
"""SELECT SFV.*
|
|
||||||
FROM scolar_formsemestre_validation SFV
|
|
||||||
WHERE ue_id=%(ue_id)s
|
|
||||||
AND etudid=%(etudid)s""",
|
|
||||||
{"etudid": etudid, "ue_id": ue_id},
|
|
||||||
)
|
|
||||||
if not valids:
|
|
||||||
return ""
|
|
||||||
H = [
|
|
||||||
'<div class="existing_valids"><span>Validations existantes pour cette UE:</span><ul>'
|
|
||||||
]
|
|
||||||
for valid in valids:
|
|
||||||
valid["event_date"] = ndb.DateISOtoDMY(valid["event_date"])
|
|
||||||
if valid["moy_ue"] != None:
|
|
||||||
valid["m"] = ", moyenne %(moy_ue)g/20" % valid
|
|
||||||
else:
|
|
||||||
valid["m"] = ""
|
|
||||||
if valid["formsemestre_id"]:
|
|
||||||
sem = sco_formsemestre.get_formsemestre(valid["formsemestre_id"])
|
|
||||||
valid["s"] = ", du semestre %s" % sem["titreannee"]
|
|
||||||
else:
|
|
||||||
valid["s"] = " enregistrée d'un parcours antérieur (hors ScoDoc)"
|
|
||||||
if valid["semestre_id"]:
|
|
||||||
valid["s"] += " (<b>S%d</b>)" % valid["semestre_id"]
|
|
||||||
valid["ds"] = formsemestre_id
|
|
||||||
H.append(
|
|
||||||
'<li>%(code)s%(m)s%(s)s, le %(event_date)s <a class="stdlink" href="etud_ue_suppress_validation?etudid=%(etudid)s&ue_id=%(ue_id)s&formsemestre_id=%(ds)s" title="supprime cette validation">effacer</a></li>'
|
|
||||||
% valid
|
|
||||||
)
|
|
||||||
H.append("</ul></div>")
|
|
||||||
return "\n".join(H)
|
|
||||||
|
|
||||||
|
|
||||||
def etud_ue_suppress_validation(etudid, formsemestre_id, ue_id):
|
|
||||||
"""Suppress a validation (ue_id, etudid) and redirect to formsemestre"""
|
|
||||||
log("etud_ue_suppress_validation( %s, %s, %s)" % (etudid, formsemestre_id, ue_id))
|
|
||||||
cnx = ndb.GetDBConnexion()
|
|
||||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
|
||||||
cursor.execute(
|
|
||||||
"DELETE FROM scolar_formsemestre_validation WHERE etudid=%(etudid)s and ue_id=%(ue_id)s",
|
|
||||||
{"etudid": etudid, "ue_id": ue_id},
|
|
||||||
)
|
|
||||||
|
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
_invalidate_etud_formation_caches(etudid, sem["formation_id"])
|
|
||||||
|
|
||||||
return flask.redirect(
|
|
||||||
scu.NotesURL()
|
|
||||||
+ "/formsemestre_validate_previous_ue?etudid=%s&formsemestre_id=%s"
|
|
||||||
% (etudid, formsemestre_id)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def check_formation_ues(formation_id):
|
def check_formation_ues(formation_id):
|
||||||
"""Verifie que les UE d'une formation sont chacune utilisée dans un seul semestre_id
|
"""Verifie que les UE d'une formation sont chacune utilisée dans un seul semestre_id
|
||||||
Si ce n'est pas le cas, c'est probablement (mais pas forcément) une erreur de
|
Si ce n'est pas le cas, c'est probablement (mais pas forcément) une erreur de
|
||||||
|
@ -4,10 +4,6 @@ div.jury_decisions_list div {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.jury_decisions_list form {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.parcours {
|
span.parcours {
|
||||||
color:blueviolet;
|
color:blueviolet;
|
||||||
}
|
}
|
||||||
|
@ -76,16 +76,16 @@ div.flashes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.alert {
|
div.alert {
|
||||||
/*
|
padding: 16px;
|
||||||
position: absolute;
|
border-radius: 12px;
|
||||||
top: 10px;
|
font-size: 200%;
|
||||||
right: 10px; */
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.alert-info {
|
div.alert-info {
|
||||||
color: #0019d7;
|
color: #208d3b;
|
||||||
background-color: #68f36d;
|
background-color: #fffd97;
|
||||||
border-color: #0a8d0c;
|
border-color: #208d3b;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.alert-error {
|
div.alert-error {
|
||||||
@ -94,6 +94,9 @@ div.alert-error {
|
|||||||
border-color: #8d0a17;
|
border-color: #8d0a17;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.inline-form {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
div.tab-content {
|
div.tab-content {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
@ -1112,9 +1115,11 @@ a.discretelink:hover {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expl, .help {
|
||||||
|
max-width: var(--sco-content-max-width);
|
||||||
|
}
|
||||||
.help {
|
.help {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
max-width: 800px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.help_important {
|
.help_important {
|
||||||
@ -1122,13 +1127,28 @@ a.discretelink:hover {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.sco_help {
|
div.sco_box, div.sco_help {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
margin-left: 0px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
border: 1px solid grey;
|
||||||
|
max-width: var(--sco-content-max-width);
|
||||||
|
}
|
||||||
|
div.sco_help {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
max-width: 800px;
|
background-color: rgb(209, 255, 214);
|
||||||
|
}
|
||||||
|
div.sco_box_title {
|
||||||
|
font-size: 120%;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.sco_green_bg {
|
||||||
|
background-color: rgb(155, 218, 155);
|
||||||
|
}
|
||||||
|
.sco_lightgreen_bg {
|
||||||
background-color: rgb(209, 255, 214);
|
background-color: rgb(209, 255, 214);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2504,13 +2524,7 @@ input.sco_tag_checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div#ue_list_code {
|
div#ue_list_code {
|
||||||
background-color: rgb(155, 218, 155);
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
border-radius: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.notes_module_list {
|
ul.notes_module_list {
|
||||||
@ -2596,16 +2610,6 @@ div#ue_list_modules {
|
|||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#ue_list_etud_validations {
|
|
||||||
background-color: rgb(220, 250, 220);
|
|
||||||
padding-left: 4px;
|
|
||||||
padding-bottom: 1px;
|
|
||||||
margin: 3ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#ue_list_etud_validations span {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.ue_share {
|
span.ue_share {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -1,31 +1,43 @@
|
|||||||
// Affiche et met a jour la liste des UE partageant le meme code
|
// Affiche et met a jour la liste des UE partageant le meme code
|
||||||
|
|
||||||
$().ready(function () {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
update_ue_validations();
|
update_ue_list();
|
||||||
update_ue_list();
|
$("#tf_ue_id").bind("change", update_ue_list);
|
||||||
$("#tf_ue_id").bind("change", update_ue_list);
|
|
||||||
$("#tf_ue_id").bind("change", update_ue_validations);
|
const buttons = document.querySelectorAll(".ue_list_etud_validations button");
|
||||||
|
|
||||||
|
buttons.forEach((button) => {
|
||||||
|
button.addEventListener("click", (event) => {
|
||||||
|
// Handle button click event here
|
||||||
|
event.preventDefault();
|
||||||
|
const etudid = event.target.dataset.etudid;
|
||||||
|
const v_id = event.target.dataset.v_id;
|
||||||
|
const validation_type = event.target.dataset.type;
|
||||||
|
if (confirm("Supprimer cette validation ?")) {
|
||||||
|
fetch(
|
||||||
|
`${SCO_URL}/../api/etudiant/${etudid}/jury/${validation_type}/${v_id}/delete`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
}
|
||||||
|
).then((response) => {
|
||||||
|
// Handle the response
|
||||||
|
if (response.ok) {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
throw new Error("Request failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function update_ue_list() {
|
function update_ue_list() {
|
||||||
var ue_id = $("#tf_ue_id")[0].value;
|
var ue_id = $("#tf_ue_id")[0].value;
|
||||||
if (ue_id) {
|
if (ue_id) {
|
||||||
var query = "ue_sharing_code?ue_id=" + ue_id;
|
var query = SCO_URL + "/Notes/ue_sharing_code?ue_id=" + ue_id;
|
||||||
$.get(query, '', function (data) {
|
$.get(query, "", function (data) {
|
||||||
$("#ue_list_code").html(data);
|
$("#ue_list_code").html(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_ue_validations() {
|
|
||||||
var etudid = $("#tf_etudid")[0].value;
|
|
||||||
var ue_id = $("#tf_ue_id")[0].value;
|
|
||||||
var formsemestre_id = $("#tf_formsemestre_id")[0].value;
|
|
||||||
if (ue_id) {
|
|
||||||
var query = SCO_URL + "/Notes/get_etud_ue_cap_html?ue_id=" + ue_id + "&etudid=" + etudid + "&formsemestre_id=" + formsemestre_id;
|
|
||||||
$.get(query, '', function (data) {
|
|
||||||
$("#ue_list_etud_validations").html(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,10 @@ pages de saisie de jury habituelles).
|
|||||||
<ul>
|
<ul>
|
||||||
{% for v in sem_vals %}
|
{% for v in sem_vals %}
|
||||||
<li>{{v.html()|safe}}
|
<li>{{v.html()|safe}}
|
||||||
<form><button data-v_id="{{v.id}}" data-type="validation_formsemestre">effacer</button></form>
|
<form>
|
||||||
|
<button
|
||||||
|
data-v_id="{{v.id}}" data-type="validation_formsemestre" data-etudid="{{etud.id}}"
|
||||||
|
>effacer</button></form>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -39,7 +42,10 @@ pages de saisie de jury habituelles).
|
|||||||
<ul>
|
<ul>
|
||||||
{% for v in ue_vals %}
|
{% for v in ue_vals %}
|
||||||
<li>{{v.html(detail=True)|safe}}
|
<li>{{v.html(detail=True)|safe}}
|
||||||
<form><button data-v_id="{{v.id}}" data-type="validation_ue">effacer</button></form>
|
<form class="inline-form">
|
||||||
|
<button data-v_id="{{v.id}}" data-type="validation_ue" data-etudid="{{etud.id"}}
|
||||||
|
>effacer</button>
|
||||||
|
</form>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -52,7 +58,10 @@ pages de saisie de jury habituelles).
|
|||||||
<ul>
|
<ul>
|
||||||
{% for v in rcue_vals %}
|
{% for v in rcue_vals %}
|
||||||
<li>{{v.html()|safe}}
|
<li>{{v.html()|safe}}
|
||||||
<form><button data-v_id="{{v.id}}" data-type="validation_rcue">effacer</button></form>
|
<form>
|
||||||
|
<button data-v_id="{{v.id}}" data-type="validation_rcue" data-etudid="{{etud.id}}"
|
||||||
|
>effacer</button>
|
||||||
|
</form>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -65,7 +74,10 @@ pages de saisie de jury habituelles).
|
|||||||
<ul>
|
<ul>
|
||||||
{% for v in annee_but_vals %}
|
{% for v in annee_but_vals %}
|
||||||
<li>{{v.html()|safe}}
|
<li>{{v.html()|safe}}
|
||||||
<form><button data-v_id="{{v.id}}" data-type="validation_annee_but">effacer</button></form>
|
<form>
|
||||||
|
<button data-v_id="{{v.id}}" data-type="validation_annee_but" data-etudid="{{etud.id}}"
|
||||||
|
>effacer</button>
|
||||||
|
</form>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -78,7 +90,10 @@ pages de saisie de jury habituelles).
|
|||||||
<ul>
|
<ul>
|
||||||
{% for v in autorisations %}
|
{% for v in autorisations %}
|
||||||
<li>{{v.html()|safe}}
|
<li>{{v.html()|safe}}
|
||||||
<form><button data-v_id="{{v.id}}" data-type="autorisation_inscription">effacer</button></form>
|
<form>
|
||||||
|
<button data-v_id="{{v.id}}" data-type="autorisation_inscription" data-etudid="{{etud.id}}"
|
||||||
|
>effacer</button>
|
||||||
|
</form>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -113,10 +128,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
button.addEventListener('click', (event) => {
|
button.addEventListener('click', (event) => {
|
||||||
// Handle button click event here
|
// Handle button click event here
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
const etudid = event.target.dataset.etudid;
|
||||||
const v_id = event.target.dataset.v_id;
|
const v_id = event.target.dataset.v_id;
|
||||||
const validation_type = event.target.dataset.type;
|
const validation_type = event.target.dataset.type;
|
||||||
if (confirm("Supprimer cette validation ?")) {
|
if (confirm("Supprimer cette validation ?")) {
|
||||||
fetch(`${SCO_URL}/../api/etudiant/{{etud.id}}/jury/${validation_type}/${v_id}/delete`,
|
fetch(`${SCO_URL}/../api/etudiant/${etudid}/jury/${validation_type}/${v_id}/delete`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
|
@ -56,17 +56,22 @@ from app.but.forms import jury_but_forms
|
|||||||
|
|
||||||
from app.comp import jury, res_sem
|
from app.comp import jury, res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import Formation, ScolarAutorisationInscription, ScolarNews, Scolog
|
from app.models import (
|
||||||
|
Formation,
|
||||||
|
ScolarFormSemestreValidation,
|
||||||
|
ScolarAutorisationInscription,
|
||||||
|
ScolarNews,
|
||||||
|
Scolog,
|
||||||
|
)
|
||||||
from app.models.but_refcomp import ApcNiveau
|
from app.models.but_refcomp import ApcNiveau
|
||||||
from app.models.config import ScoDocSiteConfig
|
from app.models.config import ScoDocSiteConfig
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.models.formsemestre import FormSemestre
|
from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
||||||
from app.models.formsemestre import FormSemestreUEComputationExpr
|
from app.models.formsemestre import FormSemestreUEComputationExpr
|
||||||
from app.models.moduleimpls import ModuleImpl
|
from app.models.moduleimpls import ModuleImpl
|
||||||
from app.models.modules import Module
|
from app.models.modules import Module
|
||||||
from app.models.ues import DispenseUE, UniteEns
|
from app.models.ues import DispenseUE, UniteEns
|
||||||
from app.scodoc.sco_exceptions import ScoFormationConflict, ScoPermissionDenied
|
from app.scodoc.sco_exceptions import ScoFormationConflict, ScoPermissionDenied
|
||||||
from app.tables import jury_recap
|
|
||||||
from app.views import notes_bp as bp
|
from app.views import notes_bp as bp
|
||||||
|
|
||||||
from app.decorators import (
|
from app.decorators import (
|
||||||
@ -483,7 +488,21 @@ def ue_set_internal(ue_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
sco_publish("/ue_sharing_code", sco_edit_ue.ue_sharing_code, Permission.ScoView)
|
@bp.route("/ue_sharing_code")
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
@scodoc7func
|
||||||
|
def ue_sharing_code():
|
||||||
|
ue_code = request.args.get("ue_code")
|
||||||
|
ue_id = request.args.get("ue_id")
|
||||||
|
hide_ue_id = request.args.get("hide_ue_id")
|
||||||
|
return sco_edit_ue.ue_sharing_code(
|
||||||
|
ue_code=ue_code,
|
||||||
|
ue_id=None if ue_id is None else int(ue_id),
|
||||||
|
hide_ue_id=None if hide_ue_id is None else int(hide_ue_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
sco_publish(
|
sco_publish(
|
||||||
"/edit_ue_set_code_apogee",
|
"/edit_ue_set_code_apogee",
|
||||||
sco_edit_ue.edit_ue_set_code_apogee,
|
sco_edit_ue.edit_ue_set_code_apogee,
|
||||||
@ -2621,10 +2640,12 @@ def formsemestre_validation_auto_but(formsemestre_id: int = None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre_validate_previous_ue", methods=["GET", "POST"])
|
@bp.route(
|
||||||
|
"/formsemestre_validate_previous_ue/<int:formsemestre_id>/<int:etudid>",
|
||||||
|
methods=["GET", "POST"],
|
||||||
|
)
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
@scodoc7func
|
|
||||||
def formsemestre_validate_previous_ue(formsemestre_id, etudid=None):
|
def formsemestre_validate_previous_ue(formsemestre_id, etudid=None):
|
||||||
"Form. saisie UE validée hors ScoDoc"
|
"Form. saisie UE validée hors ScoDoc"
|
||||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
@ -2636,9 +2657,15 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid=None):
|
|||||||
formsemestre_id=formsemestre_id,
|
formsemestre_id=formsemestre_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
etud: Identite = (
|
||||||
|
Identite.query.filter_by(id=etudid)
|
||||||
|
.join(FormSemestreInscription)
|
||||||
|
.filter_by(formsemestre_id=formsemestre_id)
|
||||||
|
.first_or_404()
|
||||||
|
)
|
||||||
|
|
||||||
return sco_formsemestre_validation.formsemestre_validate_previous_ue(
|
return sco_formsemestre_validation.formsemestre_validate_previous_ue(
|
||||||
formsemestre_id, etudid
|
formsemestre, etud
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -2671,34 +2698,6 @@ def formsemestre_ext_edit_ue_validations(formsemestre_id, etudid=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
sco_publish(
|
|
||||||
"/get_etud_ue_cap_html",
|
|
||||||
sco_formsemestre_validation.get_etud_ue_cap_html,
|
|
||||||
Permission.ScoView,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/etud_ue_suppress_validation")
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoView)
|
|
||||||
@scodoc7func
|
|
||||||
def etud_ue_suppress_validation(etudid, formsemestre_id, ue_id):
|
|
||||||
"""Suppress a validation (ue_id, etudid) and redirect to formsemestre"""
|
|
||||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
|
||||||
if not formsemestre.can_edit_jury():
|
|
||||||
raise ScoPermissionDenied(
|
|
||||||
dest_url=url_for(
|
|
||||||
"notes.formsemestre_status",
|
|
||||||
scodoc_dept=g.scodoc_dept,
|
|
||||||
formsemestre_id=formsemestre_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return sco_formsemestre_validation.etud_ue_suppress_validation(
|
|
||||||
etudid, formsemestre_id, ue_id
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/formsemestre_validation_auto")
|
@bp.route("/formsemestre_validation_auto")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
|
Loading…
Reference in New Issue
Block a user