forked from ScoDoc/ScoDoc
form inscription/desinscription à toutes les UEs du BUT
This commit is contained in:
parent
79bdf03caa
commit
9a4b78be16
@ -122,6 +122,10 @@ def formsemestre_get_ue_capitalisees(formsemestre: FormSemestre) -> pd.DataFrame
|
||||
event_date :
|
||||
} ]
|
||||
"""
|
||||
|
||||
# Note: pour récupérer aussi les UE validées en CMp ou ADJ, changer une ligne
|
||||
# and ( SFV.code = 'ADM' or SFV.code = 'ADJ' or SFV.code = 'CMP' )
|
||||
|
||||
query = """
|
||||
SELECT DISTINCT SFV.*, ue.ue_code
|
||||
FROM
|
||||
|
@ -35,7 +35,7 @@ from flask_login import current_user
|
||||
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
from app.models import FormSemestre, Identite, UniteEns
|
||||
|
||||
import app.scodoc.notesdb as ndb
|
||||
import app.scodoc.sco_utils as scu
|
||||
@ -297,7 +297,13 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
||||
options.append(modimpl)
|
||||
|
||||
# Page HTML:
|
||||
H = [html_sco_header.html_sem_header("Inscriptions aux modules du semestre")]
|
||||
H = [
|
||||
html_sco_header.html_sem_header(
|
||||
"Inscriptions aux modules et UE du semestre",
|
||||
javascripts=["js/etud_info.js", "js/moduleimpl_inscriptions_stats.js"],
|
||||
init_qtip=True,
|
||||
)
|
||||
]
|
||||
|
||||
H.append(f"<h3>Inscrits au semestre: {len(inscrits)} étudiants</h3>")
|
||||
|
||||
@ -393,7 +399,9 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
||||
# Etudiants "dispensés" d'une UE (capitalisée)
|
||||
ues_cap_info = get_etuds_with_capitalized_ue(formsemestre_id)
|
||||
if ues_cap_info:
|
||||
H.append('<h3>Étudiants avec UEs capitalisées:</h3><ul class="ue_inscr_list">')
|
||||
H.append(
|
||||
'<h3>Étudiants avec UEs capitalisées (ADM):</h3><ul class="ue_inscr_list">'
|
||||
)
|
||||
ues = [
|
||||
sco_edit_ue.ue_list({"ue_id": ue_id})[0] for ue_id in ues_cap_info.keys()
|
||||
]
|
||||
@ -461,7 +469,8 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
||||
if can_change:
|
||||
H.append(
|
||||
f"""<div><a class="stdlink" href="{
|
||||
url_for("notes.etud_inscrit_ue", scodoc_dept=g.scodoc_dept, etudid=etud["etudid"],
|
||||
url_for("notes.etud_inscrit_ue",
|
||||
scodoc_dept=g.scodoc_dept, etudid=etud["etudid"],
|
||||
formsemestre_id=formsemestre_id, ue_id=ue["ue_id"])
|
||||
}">inscrire à {"" if is_apc else "tous les modules de"} cette UE</a></div>
|
||||
"""
|
||||
@ -469,6 +478,9 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
||||
H.append("</li>")
|
||||
H.append("</ul></li>")
|
||||
H.append("</ul>")
|
||||
# BUT: propose dispense de toutes UEs
|
||||
if is_apc:
|
||||
H.append(_list_but_ue_inscriptions(res, read_only=not can_change))
|
||||
|
||||
H.append(
|
||||
"""<hr/><p class="help">Cette page décrit les inscriptions actuelles.
|
||||
@ -483,6 +495,93 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
||||
return "\n".join(H)
|
||||
|
||||
|
||||
def _list_but_ue_inscriptions(res: NotesTableCompat, read_only: bool = True) -> str:
|
||||
"""HTML pour dispenser/reinscrire chaque étudiant à chaque UE du BUT"""
|
||||
H = [
|
||||
"""
|
||||
<div class="list_but_ue_inscriptions">
|
||||
<h3>Inscriptions/déinscription aux UEs du BUT</h3>
|
||||
<form class="list_but_ue_inscriptions">
|
||||
"""
|
||||
]
|
||||
table_inscr = _table_but_ue_inscriptions(res)
|
||||
ue_ids = set.union(*(set(x.keys()) for x in table_inscr.values()))
|
||||
ues = sorted(
|
||||
(UniteEns.query.get(ue_id) for ue_id in ue_ids),
|
||||
key=lambda u: (u.numero or 0, u.acronyme),
|
||||
)
|
||||
H.append("""<table><tr><th></th>""")
|
||||
for ue in ues:
|
||||
H.append(f"""<th title="{ue.titre or ''}">{ue.acronyme}</th>""")
|
||||
H.append("""</tr>""")
|
||||
|
||||
for etudid, ues_etud in table_inscr.items():
|
||||
etud: Identite = Identite.query.get(etudid)
|
||||
H.append(
|
||||
f"""<tr><td><a class="discretelink etudinfo" id={etudid}
|
||||
href="{url_for(
|
||||
"scolar.ficheEtud",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
etudid=etudid,
|
||||
)}"
|
||||
>{etud.nomprenom}</a></td>"""
|
||||
)
|
||||
for ue in ues:
|
||||
est_inscr = ues_etud.get(ue.id) # None si pas concerné
|
||||
if est_inscr is None:
|
||||
content = ""
|
||||
else:
|
||||
content = f"""<input type="checkbox"
|
||||
{'checked' if est_inscr else ''}
|
||||
{'disabled' if read_only else ''}
|
||||
title="{etud.nomprenom} {'inscrit' if est_inscr else 'non inscrit'} à l'UE {ue.acronyme}",
|
||||
onchange="change_ue_inscr(this);"
|
||||
data-url_inscr={
|
||||
url_for("notes.etud_inscrit_ue",
|
||||
scodoc_dept=g.scodoc_dept, etudid=etudid,
|
||||
formsemestre_id=res.formsemestre.id, ue_id=ue.id)
|
||||
}
|
||||
data-url_desinscr={
|
||||
url_for("notes.etud_desinscrit_ue",
|
||||
scodoc_dept=g.scodoc_dept, etudid=etudid,
|
||||
formsemestre_id=res.formsemestre.id, ue_id=ue.id)
|
||||
}
|
||||
/>
|
||||
"""
|
||||
|
||||
H.append(f"""<td>{content}</td>""")
|
||||
H.append(
|
||||
"""</table>
|
||||
</form>
|
||||
<div class="help">
|
||||
L'inscription ou désinscription aux UE du BUT n'affecte pas les inscriptions aux modules
|
||||
mais permet de "dispenser" un étudiant de suivre certaines UE de son parcours.
|
||||
Il peut s'agit d'étudiants redoublants ayant déjà acquis l'UE, ou d'autres cas particuliers.
|
||||
La dispense d'UE est réversible à tout moment (avant le jury de fin de semestre)
|
||||
et n'affecte pas les notes saisies.
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
return "\n".join(H)
|
||||
|
||||
|
||||
def _table_but_ue_inscriptions(res: NotesTableCompat) -> dict[int, dict]:
|
||||
""" "table" avec les inscriptions aux UEs de chaque étudiant
|
||||
{
|
||||
etudid : { ue_id : True | False }
|
||||
}
|
||||
"""
|
||||
return {
|
||||
etudid: {
|
||||
ue_id: (etudid, ue_id) not in res.dispense_ues
|
||||
for ue_id in res.etud_ues_ids(etudid)
|
||||
}
|
||||
for etudid, inscr in res.formsemestre.etuds_inscriptions.items()
|
||||
if inscr.etat == scu.INSCRIT
|
||||
}
|
||||
|
||||
|
||||
def descr_inscrs_module(moduleimpl_id, set_all, partitions):
|
||||
"""returns tous_inscrits, nb_inscrits, descr"""
|
||||
ins = sco_moduleimpl.do_moduleimpl_inscription_list(moduleimpl_id=moduleimpl_id)
|
||||
|
@ -1955,6 +1955,56 @@ span.eval_coef_ue {
|
||||
|
||||
span.eval_coef_ue_titre {}
|
||||
|
||||
/* Inscriptions modules/UE */
|
||||
div.list_but_ue_inscriptions {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
padding-left: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-radius: 16px;
|
||||
border: 2px solid black;
|
||||
background-color: #eafffa;
|
||||
}
|
||||
|
||||
div.list_but_ue_inscriptions h3 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
div.list_but_ue_inscriptions table th:first-child {
|
||||
border-left: 0px;
|
||||
border-top: 0px;
|
||||
}
|
||||
|
||||
div.list_but_ue_inscriptions table th:last-child,
|
||||
div.list_but_ue_inscriptions table td:last-child {
|
||||
border-right: 1px solid salmon;
|
||||
}
|
||||
|
||||
div.list_but_ue_inscriptions table th {
|
||||
border-top: 1px solid salmon;
|
||||
}
|
||||
|
||||
div.list_but_ue_inscriptions table th,
|
||||
div.list_but_ue_inscriptions table td {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
border-left: 1px solid salmon;
|
||||
border-bottom: 1px solid salmon;
|
||||
}
|
||||
|
||||
form.list_but_ue_inscriptions {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
form.list_but_ue_inscriptions td:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
form.list_but_ue_inscriptions td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* Formulaire edition des partitions */
|
||||
form#editpart table {
|
||||
border: 1px solid gray;
|
||||
|
17
app/static/js/moduleimpl_inscriptions_stats.js
Normal file
17
app/static/js/moduleimpl_inscriptions_stats.js
Normal file
@ -0,0 +1,17 @@
|
||||
/* Page Inscriptions aux modules et UE du semestre
|
||||
*/
|
||||
|
||||
function change_ue_inscr(elt) {
|
||||
let url = "";
|
||||
if (elt.checked) {
|
||||
url = elt.dataset.url_inscr;
|
||||
} else {
|
||||
url = elt.dataset.url_desinscr;
|
||||
}
|
||||
$.post(url,
|
||||
{},
|
||||
function (result) {
|
||||
sco_message("changement inscription UE enregistré");
|
||||
}
|
||||
);
|
||||
}
|
@ -50,7 +50,7 @@ from app.but import jury_but_view
|
||||
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import ScolarNews
|
||||
from app.models import ScolarNews, Scolog
|
||||
from app.models.but_refcomp import ApcNiveau, ApcParcours
|
||||
from app.models.config import ScoDocSiteConfig
|
||||
from app.models.etudiants import Identite
|
||||
@ -1600,10 +1600,12 @@ sco_publish(
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/etud_desinscrit_ue")
|
||||
@bp.route(
|
||||
"/etud_desinscrit_ue/<int:etudid>/<int:formsemestre_id>/<int:ue_id>",
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoEtudInscrit)
|
||||
@scodoc7func
|
||||
def etud_desinscrit_ue(etudid, formsemestre_id, ue_id):
|
||||
"""
|
||||
- En classique: désinscrit l'etudiant de tous les modules de cette UE dans ce semestre.
|
||||
@ -1617,6 +1619,13 @@ def etud_desinscrit_ue(etudid, formsemestre_id, ue_id):
|
||||
disp = DispenseUE(ue_id=ue_id, etudid=etudid)
|
||||
db.session.add(disp)
|
||||
db.session.commit()
|
||||
log(f"etud_desinscrit_ue {etud} {ue}")
|
||||
Scolog.logdb(
|
||||
method="etud_desinscrit_ue",
|
||||
etudid=etud.id,
|
||||
msg=f"Désinscription de l'UE {ue.acronyme}",
|
||||
commit=True,
|
||||
)
|
||||
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre.id)
|
||||
else:
|
||||
sco_moduleimpl_inscriptions.do_etud_desinscrit_ue_classic(
|
||||
@ -1632,10 +1641,12 @@ def etud_desinscrit_ue(etudid, formsemestre_id, ue_id):
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/etud_inscrit_ue")
|
||||
@bp.route(
|
||||
"/etud_inscrit_ue/<int:etudid>/<int:formsemestre_id>/<int:ue_id>",
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoEtudInscrit)
|
||||
@scodoc7func
|
||||
def etud_inscrit_ue(etudid, formsemestre_id, ue_id):
|
||||
"""
|
||||
En classic: inscrit l'étudiant à tous les modules de cette UE dans ce semestre.
|
||||
@ -1649,6 +1660,13 @@ def etud_inscrit_ue(etudid, formsemestre_id, ue_id):
|
||||
if ue.formation.is_apc():
|
||||
for disp in DispenseUE.query.filter_by(etudid=etud.id, ue_id=ue_id):
|
||||
db.session.delete(disp)
|
||||
log(f"etud_inscrit_ue {etud} {ue}")
|
||||
Scolog.logdb(
|
||||
method="etud_inscrit_ue",
|
||||
etudid=etud.id,
|
||||
msg=f"Inscription à l'UE {ue.acronyme}",
|
||||
commit=True,
|
||||
)
|
||||
db.session.commit()
|
||||
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre.id)
|
||||
else:
|
||||
|
@ -34,6 +34,7 @@ from app.views import ScoData
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def refcomp(refcomp_id):
|
||||
"""Le référentiel de compétences, en JSON."""
|
||||
ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
|
||||
return jsonify(ref.to_dict())
|
||||
|
||||
@ -42,6 +43,7 @@ def refcomp(refcomp_id):
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def refcomp_show(refcomp_id):
|
||||
"""Affichage du référentiel de compétences."""
|
||||
ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
|
||||
return render_template(
|
||||
"but/refcomp_show.html",
|
||||
@ -60,6 +62,7 @@ def refcomp_show(refcomp_id):
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoChangeFormation)
|
||||
def refcomp_delete(refcomp_id):
|
||||
"""Suppression du référentiel de la base. Le fichier source n'est pas affecté."""
|
||||
ref = ApcReferentielCompetences.query.get_or_404(refcomp_id)
|
||||
db.session.delete(ref)
|
||||
db.session.commit()
|
||||
|
@ -1,6 +1,7 @@
|
||||
[pytest]
|
||||
markers =
|
||||
slow: marks tests as slow (deselect with '-m "not slow"')
|
||||
but_gb
|
||||
lemans
|
||||
lyon
|
||||
|
||||
|
@ -30,6 +30,7 @@ DEPT = TestConfig.DEPT_TEST
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.but_gb
|
||||
def test_but_jury_GB(test_client):
|
||||
"""Tests sur un cursus GB
|
||||
- construction des semestres et de leurs étudianst à partir du yaml
|
||||
|
Loading…
Reference in New Issue
Block a user