forked from ScoDoc/ScoDoc
Interface pour UE externes et éditions des validations
This commit is contained in:
parent
35fb269a41
commit
3325b41690
@ -114,16 +114,16 @@ def _validation_ue_delete(etudid: int, validation_id: int):
|
||||
# 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")
|
||||
return json_error(403, "opération non autorisée (117)")
|
||||
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")
|
||||
return json_error(403, "opération non autorisée (123)")
|
||||
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")
|
||||
return json_error(403, "opération non autorisée (126)")
|
||||
|
||||
log(f"validation_ue_delete: etuid={etudid} {validation}")
|
||||
db.session.delete(validation)
|
||||
|
@ -158,8 +158,16 @@ class ApcValidationAnnee(db.Model):
|
||||
if self.date
|
||||
else "(sans date)"
|
||||
)
|
||||
link = (
|
||||
self.formsemestre.html_link_status(
|
||||
label=f"{self.formsemestre.titre_formation(with_sem_idx=1)}",
|
||||
title=self.formsemestre.titre_annee(),
|
||||
)
|
||||
if self.formsemestre
|
||||
else "externe/antérieure"
|
||||
)
|
||||
return f"""Validation <b>année BUT{self.ordre}</b> émise par
|
||||
{self.formsemestre.html_link_status() if self.formsemestre else "-"}
|
||||
{link}
|
||||
: <b>{self.code}</b>
|
||||
{date_str}
|
||||
"""
|
||||
|
@ -163,12 +163,12 @@ class FormSemestre(db.Model):
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} {self.id} {self.titre_annee()}>"
|
||||
|
||||
def html_link_status(self) -> str:
|
||||
def html_link_status(self, label=None, title=None) -> str:
|
||||
"html link to status page"
|
||||
return f"""<a class="stdlink" href="{
|
||||
url_for("notes.formsemestre_status", scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=self.id,)
|
||||
}">{self.titre_mois()}</a>
|
||||
}" title="{title or ''}">{label or self.titre_mois()}</a>
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
|
@ -94,6 +94,14 @@ class ScolarFormSemestreValidation(db.Model):
|
||||
if self.moy_ue is not None
|
||||
else ""
|
||||
)
|
||||
link = (
|
||||
self.formsemestre.html_link_status(
|
||||
label=f"{self.formsemestre.titre_formation(with_sem_idx=1)}",
|
||||
title=self.formsemestre.titre_annee(),
|
||||
)
|
||||
if self.formsemestre
|
||||
else "externe/antérieure"
|
||||
)
|
||||
return f"""Validation
|
||||
{'<span class="redboldtext">externe</span>' if self.is_external else ""}
|
||||
de l'UE <b>{self.ue.acronyme}</b>
|
||||
@ -101,9 +109,7 @@ class ScolarFormSemestreValidation(db.Model):
|
||||
+ ", ".join([p.code for p in self.ue.parcours]))
|
||||
+ "</span>"
|
||||
if self.ue.parcours else ""}
|
||||
de {self.ue.formation.acronyme}
|
||||
{("émise par " + self.formsemestre.html_link_status())
|
||||
if self.formsemestre else "externe/antérieure"}
|
||||
{("émise par " + link)}
|
||||
: <b>{self.code}</b>{moyenne}
|
||||
le {self.event_date.strftime("%d/%m/%Y")} à {self.event_date.strftime("%Hh%M")}
|
||||
"""
|
||||
@ -149,10 +155,16 @@ class ScolarAutorisationInscription(db.Model):
|
||||
|
||||
def html(self) -> str:
|
||||
"Affichage html"
|
||||
link = (
|
||||
self.origin_formsemestre.html_link_status(
|
||||
label=f"{self.origin_formsemestre.titre_formation(with_sem_idx=1)}",
|
||||
title=self.origin_formsemestre.titre_annee(),
|
||||
)
|
||||
if self.origin_formsemestre
|
||||
else "externe/antérieure"
|
||||
)
|
||||
return f"""Autorisation de passage vers <b>S{self.semestre_id}</b> émise par
|
||||
{self.origin_formsemestre.html_link_status()
|
||||
if self.origin_formsemestre
|
||||
else "-"}
|
||||
{link}
|
||||
le {self.date.strftime("%d/%m/%Y")} à {self.date.strftime("%Hh%M")}
|
||||
"""
|
||||
|
||||
|
@ -196,6 +196,8 @@ CODES_SEM_ATTENTES = {ATT, ATB, ATJ} # semestre en attente
|
||||
|
||||
CODES_SEM_REO = {NAR} # reorientation
|
||||
|
||||
# Les codes d'UEs
|
||||
CODES_JURY_UE = {ADM, CMP, ADJ, ADJR, ADSUP, AJ, ATJ, RAT, DEF, ABAN, DEM, UEBSL}
|
||||
CODES_UE_VALIDES_DE_DROIT = {ADM, CMP} # validation "de droit"
|
||||
CODES_UE_VALIDES = CODES_UE_VALIDES_DE_DROIT | {ADJ, ADJR, ADSUP}
|
||||
"UE validée"
|
||||
|
@ -398,7 +398,7 @@ def formsemestre_validation_etud(
|
||||
selected_choice = choice
|
||||
break
|
||||
if not selected_choice:
|
||||
raise ValueError("code choix invalide ! (%s)" % codechoice)
|
||||
raise ValueError(f"code choix invalide ! ({codechoice})")
|
||||
#
|
||||
Se.valide_decision(selected_choice) # enregistre
|
||||
return _redirect_valid_choice(
|
||||
@ -1132,6 +1132,7 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
|
||||
},
|
||||
)
|
||||
)
|
||||
ue_codes = sorted(codes_cursus.CODES_JURY_UE)
|
||||
form_descr += [
|
||||
(
|
||||
"date",
|
||||
@ -1152,6 +1153,18 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
|
||||
"title": "Moyenne (/20) obtenue dans cette UE:",
|
||||
},
|
||||
),
|
||||
(
|
||||
"code_jury",
|
||||
{
|
||||
"input_type": "menu",
|
||||
"title": "Code jury",
|
||||
"explanation": " code donné par le jury (ADM si validée normalement)",
|
||||
"allow_null": True,
|
||||
"allowed_values": [""] + ue_codes,
|
||||
"labels": ["-"] + ue_codes,
|
||||
"default": ADM,
|
||||
},
|
||||
),
|
||||
]
|
||||
tf = TrivialFormulator(
|
||||
request.base_url,
|
||||
@ -1173,17 +1186,20 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
|
||||
de {etud.html_link_fiche()}
|
||||
</h2>
|
||||
|
||||
<p class="help">Utiliser cette page pour enregistrer une UE validée antérieurement,
|
||||
<p class="help">Utiliser cette page pour enregistrer des UEs validées antérieurement,
|
||||
<em>dans un semestre hors ScoDoc</em>.</p>
|
||||
<p class="expl"><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>pour les semestres précédents gérés avec ScoDoc,
|
||||
passer par la page jury normale)</em>).
|
||||
<p class="expl"><b>Les UE validées dans ScoDoc sont
|
||||
automatiquement prises en compte</b>.
|
||||
</p>
|
||||
<p>Cette page est surtout utile pour les étudiants ayant
|
||||
suivi un début de cursus dans <b>un autre établissement</b>, ou qui
|
||||
ont suivi une UE à l'étranger ou dans un semestre géré <b>sans ScoDoc</b>.
|
||||
</p>
|
||||
<p>Pour les semestres précédents gérés avec ScoDoc, passer par la page jury normale.
|
||||
</p>
|
||||
<p>Notez que l'UE est validée, avec enregistrement immédiat de la décision et
|
||||
l'attribution des ECTS si le code jury est validant (ADM).
|
||||
</p>
|
||||
<p>Notez que l'UE est validée (ADM), avec enregistrement immédiat de la décision et
|
||||
l'attribution des ECTS.</p>
|
||||
<p>On ne peut valider ici que les UEs du cursus <b>{formation.titre}</b></p>
|
||||
|
||||
{_get_etud_ue_cap_html(etud, formsemestre)}
|
||||
@ -1221,12 +1237,16 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
|
||||
else:
|
||||
semestre_id = None
|
||||
|
||||
if tf[2]["code_jury"] not in CODES_JURY_UE:
|
||||
flash("Code UE invalide")
|
||||
return flask.redirect(dest_url)
|
||||
do_formsemestre_validate_previous_ue(
|
||||
formsemestre,
|
||||
etud.id,
|
||||
tf[2]["ue_id"],
|
||||
tf[2]["moy_ue"],
|
||||
tf[2]["date"],
|
||||
code=tf[2]["code_jury"],
|
||||
semestre_id=semestre_id,
|
||||
)
|
||||
flash("Validation d'UE enregistrée")
|
||||
@ -1258,7 +1278,7 @@ def _get_etud_ue_cap_html(etud: Identite, formsemestre: FormSemestre) -> str:
|
||||
<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>"""
|
||||
<ul class="liste_validations">"""
|
||||
]
|
||||
for validation in validations:
|
||||
if validation.formsemestre_id is None:
|
||||
@ -1267,17 +1287,20 @@ def _get_etud_ue_cap_html(etud: Identite, formsemestre: FormSemestre) -> str:
|
||||
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()}
|
||||
H.append(f"""<li>{validation.html()}""")
|
||||
if validation.formsemestre.can_edit_jury():
|
||||
H.append(
|
||||
f"""
|
||||
<form class="inline-form">
|
||||
<button
|
||||
data-v_id="{validation.id}" data-type="validation_ue" data-etudid="{etud.id}"
|
||||
>effacer</button>
|
||||
</form>
|
||||
</li>
|
||||
""",
|
||||
)
|
||||
""",
|
||||
)
|
||||
else:
|
||||
H.append(scu.icontag("lock_img", border="0", title="Semestre verrouillé"))
|
||||
H.append("</li>")
|
||||
H.append("</ul></div>")
|
||||
return "\n".join(H)
|
||||
|
||||
@ -1300,7 +1323,7 @@ def do_formsemestre_validate_previous_ue(
|
||||
ue: UniteEns = UniteEns.query.get_or_404(ue_id)
|
||||
|
||||
cnx = ndb.GetDBConnexion()
|
||||
if ue_coefficient != None:
|
||||
if ue_coefficient is not None:
|
||||
sco_formsemestre.do_formsemestre_uecoef_edit_or_create(
|
||||
cnx, formsemestre.id, ue_id, ue_coefficient
|
||||
)
|
||||
|
@ -59,11 +59,13 @@ from app.scodoc.sco_formsemestre_validation import formsemestre_recap_parcours_t
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
|
||||
|
||||
def _menu_scolarite(authuser, sem: dict, etudid: int):
|
||||
def _menu_scolarite(
|
||||
authuser, formsemestre: FormSemestre, etudid: int, etat_inscription: str
|
||||
):
|
||||
"""HTML pour menu "scolarite" pour un etudiant dans un semestre.
|
||||
Le contenu du menu depend des droits de l'utilisateur et de l'état de l'étudiant.
|
||||
"""
|
||||
locked = not sem["etat"]
|
||||
locked = not formsemestre.etat
|
||||
if locked:
|
||||
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
||||
return lockicon # no menu
|
||||
@ -71,10 +73,10 @@ def _menu_scolarite(authuser, sem: dict, etudid: int):
|
||||
Permission.ScoEtudInscrit
|
||||
) and not authuser.has_permission(Permission.ScoEtudChangeGroups):
|
||||
return "" # no menu
|
||||
ins = sem["ins"]
|
||||
args = {"etudid": etudid, "formsemestre_id": ins["formsemestre_id"]}
|
||||
|
||||
if ins["etat"] != "D":
|
||||
args = {"etudid": etudid, "formsemestre_id": formsemestre.id}
|
||||
|
||||
if etat_inscription != scu.DEMISSION:
|
||||
dem_title = "Démission"
|
||||
dem_url = "scolar.form_dem"
|
||||
else:
|
||||
@ -82,14 +84,14 @@ def _menu_scolarite(authuser, sem: dict, etudid: int):
|
||||
dem_url = "scolar.do_cancel_dem"
|
||||
|
||||
# Note: seul un etudiant inscrit (I) peut devenir défaillant.
|
||||
if ins["etat"] != codes_cursus.DEF:
|
||||
if etat_inscription != codes_cursus.DEF:
|
||||
def_title = "Déclarer défaillance"
|
||||
def_url = "scolar.form_def"
|
||||
elif ins["etat"] == codes_cursus.DEF:
|
||||
elif etat_inscription == codes_cursus.DEF:
|
||||
def_title = "Annuler la défaillance"
|
||||
def_url = "scolar.do_cancel_def"
|
||||
def_enabled = (
|
||||
(ins["etat"] != "D")
|
||||
(etat_inscription != scu.DEMISSION)
|
||||
and authuser.has_permission(Permission.ScoEtudInscrit)
|
||||
and not locked
|
||||
)
|
||||
@ -128,6 +130,12 @@ def _menu_scolarite(authuser, sem: dict, etudid: int):
|
||||
"enabled": authuser.has_permission(Permission.ScoEtudInscrit)
|
||||
and not locked,
|
||||
},
|
||||
{
|
||||
"title": "Gérer les validations d'UEs antérieures",
|
||||
"endpoint": "notes.formsemestre_validate_previous_ue",
|
||||
"args": args,
|
||||
"enabled": formsemestre.can_edit_jury(),
|
||||
},
|
||||
{
|
||||
"title": "Inscrire à un autre semestre",
|
||||
"endpoint": "notes.formsemestre_inscription_with_modules_form",
|
||||
@ -250,8 +258,8 @@ def ficheEtud(etudid=None):
|
||||
info["last_formsemestre_id"] = ""
|
||||
sem_info = {}
|
||||
for sem in info["sems"]:
|
||||
formsemestre: FormSemestre = FormSemestre.query.get(sem["formsemestre_id"])
|
||||
if sem["ins"]["etat"] != scu.INSCRIT:
|
||||
formsemestre: FormSemestre = FormSemestre.query.get(sem["formsemestre_id"])
|
||||
descr, _ = etud_descr_situation_semestre(
|
||||
etudid,
|
||||
formsemestre,
|
||||
@ -283,7 +291,7 @@ def ficheEtud(etudid=None):
|
||||
)
|
||||
grlink = ", ".join(grlinks)
|
||||
# infos ajoutées au semestre dans le parcours (groupe, menu)
|
||||
menu = _menu_scolarite(authuser, sem, etudid)
|
||||
menu = _menu_scolarite(authuser, formsemestre, etudid, sem["ins"]["etat"])
|
||||
if menu:
|
||||
sem_info[sem["formsemestre_id"]] = (
|
||||
"<table><tr><td>" + grlink + "</td><td>" + menu + "</td></tr></table>"
|
||||
|
@ -7,3 +7,7 @@ div.jury_decisions_list div {
|
||||
span.parcours {
|
||||
color:blueviolet;
|
||||
}
|
||||
|
||||
div.ue_list_etud_validations ul.liste_validations li {
|
||||
margin-bottom: 8px;
|
||||
}
|
@ -11,27 +11,30 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
// Handle button click event here
|
||||
event.preventDefault();
|
||||
const etudid = event.target.dataset.etudid;
|
||||
const v_id = event.target.dataset.v_id;
|
||||
const validation_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");
|
||||
}
|
||||
});
|
||||
delete_validation(etudid, validation_type, validation_id);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function delete_validation(etudid, validation_type, validation_id) {
|
||||
const response = await fetch(
|
||||
`${SCO_URL}/../api/etudiant/${etudid}/jury/${validation_type}/${validation_id}/delete`,
|
||||
{
|
||||
method: "POST",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
location.reload();
|
||||
} else {
|
||||
const data = await response.json();
|
||||
sco_error_message("erreur: " + data.message);
|
||||
}
|
||||
}
|
||||
|
||||
function update_ue_list() {
|
||||
var ue_id = $("#tf_ue_id")[0].value;
|
||||
if (ue_id) {
|
||||
|
@ -34,6 +34,32 @@ quelle que soit leur origine.</p>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="sco_box">
|
||||
<div class="sco_box_title">Autres actions:</div>
|
||||
<ul>
|
||||
<li><a class="stdlink" href="{{
|
||||
url_for('notes.jury_delete_manual',
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
etudid=etud.id
|
||||
)
|
||||
}}">effacer les décisions une à une</a>
|
||||
</li>
|
||||
{% if formsemestre_origine is not none %}
|
||||
<li><a class="stdlink" href="{{
|
||||
url_for('notes.formsemestre_jury_but_erase',
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_origine.id,
|
||||
etudid=etud.id, only_one_sem=1)
|
||||
}}">
|
||||
effacer seulement les décisions émises par le semestre
|
||||
{{formsemestre_origine.titre_formation(with_sem_idx=1)|safe}}
|
||||
(efface aussi la décision annuelle)
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
@ -2534,21 +2534,20 @@ def formsemestre_validation_but(
|
||||
</div>"""
|
||||
)
|
||||
else:
|
||||
erase_span = f"""<a href="{
|
||||
url_for("notes.formsemestre_jury_but_erase",
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=deca.formsemestre.id,
|
||||
etudid=deca.etud.id)}" class="stdlink"
|
||||
title="efface décisions issues des jurys de cette année"
|
||||
>effacer décisions de ce jury</a>
|
||||
|
||||
erase_span = f"""
|
||||
<a style="margin-left: 16px;" class="stdlink"
|
||||
href="{
|
||||
url_for("notes.erase_decisions_annee_formation",
|
||||
scodoc_dept=g.scodoc_dept, formation_id=deca.formsemestre.formation.id,
|
||||
etudid=deca.etud.id, annee=deca.annee_but)}"
|
||||
title="efface toutes décisions concernant le BUT{deca.annee_but}
|
||||
de cet étudiant (même extérieures ou issues d'un redoublement)"
|
||||
>effacer toutes ses décisions de BUT{deca.annee_but}</a>
|
||||
etudid=deca.etud.id, annee=deca.annee_but, formsemestre_id=formsemestre_id)}"
|
||||
>effacer des décisions de jury</a>
|
||||
|
||||
<a style="margin-left: 16px;" class="stdlink"
|
||||
href="{
|
||||
url_for("notes.formsemestre_validate_previous_ue",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
etudid=deca.etud.id, formsemestre_id=formsemestre_id)}"
|
||||
>enregistrer des UEs antérieures</a>
|
||||
"""
|
||||
H.append(
|
||||
f"""<div class="but_settings">
|
||||
@ -2966,6 +2965,12 @@ def erase_decisions_annee_formation(etudid: int, formation_id: int, annee: int):
|
||||
)
|
||||
)
|
||||
validations = jury.erase_decisions_annee_formation(etud, formation, annee)
|
||||
formsemestre_origine_id = request.args.get("formsemestre_id")
|
||||
formsemestre_origine = (
|
||||
FormSemestre.query.get_or_404(formsemestre_origine_id)
|
||||
if formsemestre_origine_id
|
||||
else None
|
||||
)
|
||||
return render_template(
|
||||
"jury/erase_decisions_annee_formation.j2",
|
||||
annee=annee,
|
||||
@ -2974,6 +2979,7 @@ def erase_decisions_annee_formation(etudid: int, formation_id: int, annee: int):
|
||||
),
|
||||
etud=etud,
|
||||
formation=formation,
|
||||
formsemestre_origine=formsemestre_origine,
|
||||
validations=validations,
|
||||
sco=ScoData(),
|
||||
title=f"Effacer décisions de jury {etud.nom} - année {annee}",
|
||||
|
Loading…
Reference in New Issue
Block a user