Passage étudiants depuis autres semestres: ajout option pour conserver juste le groupe de parcours + Fix désinscription

This commit is contained in:
Emmanuel Viennet 2023-08-31 13:38:17 +02:00
parent 224ec7be81
commit e0c6439c92
5 changed files with 103 additions and 41 deletions

View File

@ -220,20 +220,9 @@ def group_remove_etud(group_id: int, etudid: int):
group = query.first_or_404()
if not group.partition.formsemestre.etat:
return json_error(403, "formsemestre verrouillé")
if etud in group.etuds:
group.etuds.remove(etud)
db.session.commit()
Scolog.logdb(
method="group_remove_etud",
etudid=etud.id,
msg=f"Retrait du groupe {group.group_name} de {group.partition.partition_name}",
commit=True,
)
# Update parcours
group.partition.formsemestre.update_inscriptions_parcours_from_groups(
etudid=etudid
)
sco_cache.invalidate_formsemestre(group.partition.formsemestre_id)
group.remove_etud(etud)
return {"group_id": group_id, "etudid": etudid}

View File

@ -841,7 +841,7 @@ class FormSemestre(db.Model):
Les groupes de parcours sont ceux de la partition scu.PARTITION_PARCOURS
et leur nom est le code du parcours (eg "Cyber").
Si etudid est sépcifié, n'affecte que cet étudiant,
Si etudid est spécifié, n'affecte que cet étudiant,
sinon traite tous les inscrits du semestre.
"""
if self.formation.referentiel_competence_id is None:

View File

@ -11,8 +11,8 @@ from operator import attrgetter
from sqlalchemy.exc import IntegrityError
from app import db, log
from app.models import SHORT_STR_LEN
from app.models import GROUPNAME_STR_LEN
from app.models import Scolog, GROUPNAME_STR_LEN, SHORT_STR_LEN
from app.scodoc import sco_cache
from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
@ -83,6 +83,14 @@ class Partition(db.Model):
return False
return True
@classmethod
def formsemestre_remove_etud(cls, formsemestre_id: int, etud: "Identite"):
"retire l'étudiant de toutes les partitions de ce semestre"
for group in GroupDescr.query.join(Partition).filter_by(
formsemestre_id=formsemestre_id
):
group.remove_etud(etud)
def is_parcours(self) -> bool:
"Vrai s'il s'agit de la partition de parcours"
return self.partition_name == scu.PARTITION_PARCOURS
@ -248,6 +256,24 @@ class GroupDescr(db.Model):
return False
return True
def remove_etud(self, etud: "Identite"):
"Enlève l'étudiant de ce groupe s'il en fait partie (ne fait rien sinon)"
if etud in self.etuds:
self.etuds.remove(etud)
db.session.commit()
Scolog.logdb(
method="group_remove_etud",
etudid=etud.id,
msg=f"Retrait du groupe {self.group_name} de {self.partition.partition_name}",
commit=True,
)
# Update parcours
if self.partition.partition_name == scu.PARTITION_PARCOURS:
self.partition.formsemestre.update_inscriptions_parcours_from_groups(
etudid=etud.id
)
sco_cache.invalidate_formsemestre(self.partition.formsemestre_id)
group_membership = db.Table(
"group_membership",

View File

@ -38,7 +38,7 @@ from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.models import Formation, FormSemestre, FormSemestreInscription, Scolog
from app.models.etudiants import Identite
from app.models.groups import GroupDescr
from app.models.groups import Partition, GroupDescr
from app.models.validations import ScolarEvent
import app.scodoc.sco_utils as scu
from app import log
@ -236,6 +236,10 @@ def do_formsemestre_desinscription(etudid, formsemestre_id):
sco_moduleimpl.do_moduleimpl_inscription_delete(
moduleimpl_inscription_id, formsemestre_id=formsemestre_id
)
# -- désincription de tous les groupes des partitions de ce semestre
Partition.formsemestre_remove_etud(formsemestre_id, etud)
# -- désincription du semestre
do_formsemestre_inscription_delete(
insem["formsemestre_inscription_id"], formsemestre_id=formsemestre_id
@ -259,7 +263,7 @@ def do_formsemestre_desinscription(etudid, formsemestre_id):
cnx,
method="formsemestre_desinscription",
etudid=etudid,
msg="desinscription semestre %s" % formsemestre_id,
msg=f"desinscription semestre {formsemestre_id}",
commit=False,
)

View File

@ -171,12 +171,16 @@ def list_inscrits_date(sem):
return [x[0] for x in cursor.fetchall()]
def do_inscrit(sem, etudids, inscrit_groupes=False):
def do_inscrit(sem, etudids, inscrit_groupes=False, inscrit_parcours=False):
"""Inscrit ces etudiants dans ce semestre
(la liste doit avoir été vérifiée au préalable)
En option: inscrit aux mêmes groupes que dans le semestre origine
En option:
- Si inscrit_groupes, inscrit aux mêmes groupes que dans le semestre origine
(toutes partitions, y compris parcours)
- Si inscrit_parcours, inscrit au même groupe de parcours (mais ignore les autres partitions)
(si les deux sont vrais, inscrit_parcours n'a pas d'effet)
"""
# TODO à ré-écrire pour utiliser le smodèle, notamment GroupDescr
# TODO à ré-écrire pour utiliser les modèles, notamment GroupDescr
formsemestre: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
formsemestre.setup_parcours_groups()
log(f"do_inscrit (inscrit_groupes={inscrit_groupes}): {etudids}")
@ -187,7 +191,7 @@ def do_inscrit(sem, etudids, inscrit_groupes=False):
etat=scu.INSCRIT,
method="formsemestre_inscr_passage",
)
if inscrit_groupes:
if inscrit_groupes or inscrit_parcours:
# Inscription dans les mêmes groupes que ceux du semestre d'origine,
# s'ils existent.
# (mise en correspondance à partir du nom du groupe, sans tenir compte
@ -223,11 +227,16 @@ def do_inscrit(sem, etudids, inscrit_groupes=False):
group: GroupDescr = db.session.get(
GroupDescr, partition_group["group_id"]
)
if inscrit_groupes or (
group.partition.partition_name == scu.PARTITION_PARCOURS
and inscrit_parcours
):
sco_groups.change_etud_group_in_partition(etudid, group)
def do_desinscrit(sem, etudids):
log("do_desinscrit: %s" % etudids)
def do_desinscrit(sem: dict, etudids: list[int]):
"désinscrit les étudiants indiqués du formsemestre"
log(f"do_desinscrit: {etudids}")
for etudid in etudids:
sco_formsemestre_inscriptions.do_formsemestre_desinscription(
etudid, sem["formsemestre_id"]
@ -273,6 +282,7 @@ def formsemestre_inscr_passage(
formsemestre_id,
etuds=[],
inscrit_groupes=False,
inscrit_parcours=False,
submitted=False,
dialog_confirmed=False,
ignore_jury=False,
@ -291,6 +301,7 @@ def formsemestre_inscr_passage(
"""
inscrit_groupes = int(inscrit_groupes)
inscrit_parcours = int(inscrit_parcours)
ignore_jury = int(ignore_jury)
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
# -- check lock
@ -335,6 +346,7 @@ def formsemestre_inscr_passage(
candidats_non_inscrits,
inscrits_ailleurs,
inscrit_groupes=inscrit_groupes,
inscrit_parcours=inscrit_parcours,
ignore_jury=ignore_jury,
)
else:
@ -376,6 +388,7 @@ def formsemestre_inscr_passage(
"formsemestre_id": formsemestre_id,
"etuds": ",".join([str(x) for x in etuds]),
"inscrit_groupes": inscrit_groupes,
"inscrit_parcours": inscrit_parcours,
"ignore_jury": ignore_jury,
"submitted": 1,
},
@ -388,6 +401,7 @@ def formsemestre_inscr_passage(
sem,
a_inscrire,
inscrit_groupes=inscrit_groupes,
inscrit_parcours=inscrit_parcours,
)
# Désinscriptions:
do_desinscrit(sem, a_desinscrire)
@ -433,15 +447,21 @@ def _build_page(
candidats_non_inscrits,
inscrits_ailleurs,
inscrit_groupes=False,
inscrit_parcours=False,
ignore_jury=False,
):
formsemestre: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
inscrit_groupes = int(inscrit_groupes)
inscrit_parcours = int(inscrit_parcours)
ignore_jury = int(ignore_jury)
if inscrit_groupes:
inscrit_groupes_checked = " checked"
else:
inscrit_groupes_checked = ""
if inscrit_parcours:
inscrit_parcours_checked = " checked"
else:
inscrit_parcours_checked = ""
if ignore_jury:
ignore_jury_checked = " checked"
else:
@ -458,17 +478,23 @@ def _build_page(
&nbsp;<a href="#help">aide</a>
<input name="inscrit_groupes" type="checkbox" value="1"
{inscrit_groupes_checked}>inscrire aux mêmes groupes</input>
{inscrit_groupes_checked}>inscrire aux mêmes groupes (y compris parcours)</input>
<input name="inscrit_parcours" type="checkbox" value="1"
{inscrit_parcours_checked}>inscrire aux mêmes parcours</input>
<input name="ignore_jury" type="checkbox" value="1" onchange="document.f.submit()"
{ignore_jury_checked}>inclure tous les étudiants (même sans décision de jury)</input>
<div class="pas_recap">Actuellement <span id="nbinscrits">{len(inscrits)}</span> inscrits
et {len(candidats_non_inscrits)} candidats supplémentaires
<div class="pas_recap">Actuellement <span id="nbinscrits">{len(inscrits)}</span>
inscrits et {len(candidats_non_inscrits)} candidats supplémentaires.
</div>
<div>{scu.EMO_WARNING} <em>Seuls les semestres dont la date de fin est antérieure à la date de début
de ce semestre ({formsemestre.date_debut.strftime("%d/%m/%Y")}) sont pris en compte.</em></div>
<div>{scu.EMO_WARNING}
<em>Seuls les semestres dont la date de fin est antérieure à la date de début
de ce semestre ({formsemestre.date_debut.strftime("%d/%m/%Y")}) sont pris en
compte.</em>
</div>
{etuds_select_boxes(auth_etuds_by_sem, inscrits_ailleurs)}
<input type="submit" name="submitted" value="Appliquer les modifications"/>
@ -498,7 +524,8 @@ def _build_page(
return H
def formsemestre_inscr_passage_help(sem):
def formsemestre_inscr_passage_help(sem: dict):
"texte d'aide en bas de la page passage des étudiants"
return f"""<div class="pas_help"><h3><a name="help">Explications</a></h3>
<p>Cette page permet d'inscrire des étudiants dans le semestre destination
<a class="stdlink"
@ -507,18 +534,34 @@ def formsemestre_inscr_passage_help(sem):
}">{sem['titreannee']}</a>,
et d'en désincrire si besoin.
</p>
<p>Les étudiants sont groupés par semestres d'origines. Ceux qui sont en caractères
<p>Les étudiants sont groupés par semestre d'origine. Ceux qui sont en caractères
<span class="inscrit">gras</span> sont déjà inscrits dans le semestre destination.
Ceux qui sont en <span class"inscrailleurs">gras et en rouge</span> sont inscrits
dans un <em>autre</em> semestre.</p>
<p>Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter d'autres
étudiants à inscrire dans le semestre destination.</p>
<p>Si vous -selectionnez un étudiant déjà inscrit (en gras), il sera désinscrit.</p>
<p>Le bouton <em>inscrire aux mêmes groupes</em> ne prend en compte que les groupes qui existent
dans les deux semestres: pensez à créer les partitions et groupes que vous souhaitez conserver
<b>avant</b> d'inscrire les étudiants.
dans un <em>autre</em> semestre.
</p>
<p>Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter
d'autres étudiants à inscrire dans le semestre destination.
</p>
<p>Si vous -selectionnez un étudiant déjà inscrit (en gras), il sera désinscrit.
</p>
<p>Le bouton <em>inscrire aux mêmes groupes</em> ne prend en compte que les groupes
qui existent dans les deux semestres: pensez à créer les partitions et groupes que
vous souhaitez conserver <b>avant</b> d'inscrire les étudiants.
</p>
<p>Les parcours de BUT sont gérés comme des groupes de la partition parcours: si on
conserve les groupes, on conserve les parcours ( aussi, pensez à les cocher dans
<a class="stdlink" href="{
url_for("notes.formsemestre_editwithmodules", scodoc_dept=g.scodoc_dept,
formsemestre_id=sem["formsemestre_id"] )
}">modifier le semestre</a> avant de faire passer les étudiants).
</a>
<p class="help">Aucune action ne sera effectuée si vous n'appuyez pas sur le bouton
"Appliquer les modifications" !
</p>
<p class="help">Aucune action ne sera effectuée si vous n'appuyez pas sur le bouton "Appliquer les modifications" !</p>
</div>
"""