forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -220,20 +220,9 @@ def group_remove_etud(group_id: int, etudid: int):
|
|||||||
group = query.first_or_404()
|
group = query.first_or_404()
|
||||||
if not group.partition.formsemestre.etat:
|
if not group.partition.formsemestre.etat:
|
||||||
return json_error(403, "formsemestre verrouillé")
|
return json_error(403, "formsemestre verrouillé")
|
||||||
if etud in group.etuds:
|
|
||||||
group.etuds.remove(etud)
|
group.remove_etud(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)
|
|
||||||
return {"group_id": group_id, "etudid": etudid}
|
return {"group_id": group_id, "etudid": etudid}
|
||||||
|
|
||||||
|
|
||||||
|
@ -841,7 +841,7 @@ class FormSemestre(db.Model):
|
|||||||
Les groupes de parcours sont ceux de la partition scu.PARTITION_PARCOURS
|
Les groupes de parcours sont ceux de la partition scu.PARTITION_PARCOURS
|
||||||
et leur nom est le code du parcours (eg "Cyber").
|
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.
|
sinon traite tous les inscrits du semestre.
|
||||||
"""
|
"""
|
||||||
if self.formation.referentiel_competence_id is None:
|
if self.formation.referentiel_competence_id is None:
|
||||||
|
@ -11,8 +11,8 @@ from operator import attrgetter
|
|||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
from app.models import SHORT_STR_LEN
|
from app.models import Scolog, GROUPNAME_STR_LEN, SHORT_STR_LEN
|
||||||
from app.models import GROUPNAME_STR_LEN
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||||
|
|
||||||
@ -83,6 +83,14 @@ class Partition(db.Model):
|
|||||||
return False
|
return False
|
||||||
return True
|
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:
|
def is_parcours(self) -> bool:
|
||||||
"Vrai s'il s'agit de la partition de parcours"
|
"Vrai s'il s'agit de la partition de parcours"
|
||||||
return self.partition_name == scu.PARTITION_PARCOURS
|
return self.partition_name == scu.PARTITION_PARCOURS
|
||||||
@ -248,6 +256,24 @@ class GroupDescr(db.Model):
|
|||||||
return False
|
return False
|
||||||
return True
|
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 = db.Table(
|
||||||
"group_membership",
|
"group_membership",
|
||||||
|
@ -38,7 +38,7 @@ from app.comp import res_sem
|
|||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import Formation, FormSemestre, FormSemestreInscription, Scolog
|
from app.models import Formation, FormSemestre, FormSemestreInscription, Scolog
|
||||||
from app.models.etudiants import Identite
|
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
|
from app.models.validations import ScolarEvent
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import log
|
from app import log
|
||||||
@ -236,6 +236,10 @@ def do_formsemestre_desinscription(etudid, formsemestre_id):
|
|||||||
sco_moduleimpl.do_moduleimpl_inscription_delete(
|
sco_moduleimpl.do_moduleimpl_inscription_delete(
|
||||||
moduleimpl_inscription_id, formsemestre_id=formsemestre_id
|
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
|
# -- désincription du semestre
|
||||||
do_formsemestre_inscription_delete(
|
do_formsemestre_inscription_delete(
|
||||||
insem["formsemestre_inscription_id"], formsemestre_id=formsemestre_id
|
insem["formsemestre_inscription_id"], formsemestre_id=formsemestre_id
|
||||||
@ -259,7 +263,7 @@ def do_formsemestre_desinscription(etudid, formsemestre_id):
|
|||||||
cnx,
|
cnx,
|
||||||
method="formsemestre_desinscription",
|
method="formsemestre_desinscription",
|
||||||
etudid=etudid,
|
etudid=etudid,
|
||||||
msg="desinscription semestre %s" % formsemestre_id,
|
msg=f"desinscription semestre {formsemestre_id}",
|
||||||
commit=False,
|
commit=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -171,12 +171,16 @@ def list_inscrits_date(sem):
|
|||||||
return [x[0] for x in cursor.fetchall()]
|
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
|
"""Inscrit ces etudiants dans ce semestre
|
||||||
(la liste doit avoir été vérifiée au préalable)
|
(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: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
|
||||||
formsemestre.setup_parcours_groups()
|
formsemestre.setup_parcours_groups()
|
||||||
log(f"do_inscrit (inscrit_groupes={inscrit_groupes}): {etudids}")
|
log(f"do_inscrit (inscrit_groupes={inscrit_groupes}): {etudids}")
|
||||||
@ -187,7 +191,7 @@ def do_inscrit(sem, etudids, inscrit_groupes=False):
|
|||||||
etat=scu.INSCRIT,
|
etat=scu.INSCRIT,
|
||||||
method="formsemestre_inscr_passage",
|
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,
|
# Inscription dans les mêmes groupes que ceux du semestre d'origine,
|
||||||
# s'ils existent.
|
# s'ils existent.
|
||||||
# (mise en correspondance à partir du nom du groupe, sans tenir compte
|
# (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(
|
group: GroupDescr = db.session.get(
|
||||||
GroupDescr, partition_group["group_id"]
|
GroupDescr, partition_group["group_id"]
|
||||||
)
|
)
|
||||||
sco_groups.change_etud_group_in_partition(etudid, group)
|
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):
|
def do_desinscrit(sem: dict, etudids: list[int]):
|
||||||
log("do_desinscrit: %s" % etudids)
|
"désinscrit les étudiants indiqués du formsemestre"
|
||||||
|
log(f"do_desinscrit: {etudids}")
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
sco_formsemestre_inscriptions.do_formsemestre_desinscription(
|
sco_formsemestre_inscriptions.do_formsemestre_desinscription(
|
||||||
etudid, sem["formsemestre_id"]
|
etudid, sem["formsemestre_id"]
|
||||||
@ -273,6 +282,7 @@ def formsemestre_inscr_passage(
|
|||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
etuds=[],
|
etuds=[],
|
||||||
inscrit_groupes=False,
|
inscrit_groupes=False,
|
||||||
|
inscrit_parcours=False,
|
||||||
submitted=False,
|
submitted=False,
|
||||||
dialog_confirmed=False,
|
dialog_confirmed=False,
|
||||||
ignore_jury=False,
|
ignore_jury=False,
|
||||||
@ -291,6 +301,7 @@ def formsemestre_inscr_passage(
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
inscrit_groupes = int(inscrit_groupes)
|
inscrit_groupes = int(inscrit_groupes)
|
||||||
|
inscrit_parcours = int(inscrit_parcours)
|
||||||
ignore_jury = int(ignore_jury)
|
ignore_jury = int(ignore_jury)
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||||
# -- check lock
|
# -- check lock
|
||||||
@ -335,6 +346,7 @@ def formsemestre_inscr_passage(
|
|||||||
candidats_non_inscrits,
|
candidats_non_inscrits,
|
||||||
inscrits_ailleurs,
|
inscrits_ailleurs,
|
||||||
inscrit_groupes=inscrit_groupes,
|
inscrit_groupes=inscrit_groupes,
|
||||||
|
inscrit_parcours=inscrit_parcours,
|
||||||
ignore_jury=ignore_jury,
|
ignore_jury=ignore_jury,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -376,6 +388,7 @@ def formsemestre_inscr_passage(
|
|||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
"etuds": ",".join([str(x) for x in etuds]),
|
"etuds": ",".join([str(x) for x in etuds]),
|
||||||
"inscrit_groupes": inscrit_groupes,
|
"inscrit_groupes": inscrit_groupes,
|
||||||
|
"inscrit_parcours": inscrit_parcours,
|
||||||
"ignore_jury": ignore_jury,
|
"ignore_jury": ignore_jury,
|
||||||
"submitted": 1,
|
"submitted": 1,
|
||||||
},
|
},
|
||||||
@ -388,6 +401,7 @@ def formsemestre_inscr_passage(
|
|||||||
sem,
|
sem,
|
||||||
a_inscrire,
|
a_inscrire,
|
||||||
inscrit_groupes=inscrit_groupes,
|
inscrit_groupes=inscrit_groupes,
|
||||||
|
inscrit_parcours=inscrit_parcours,
|
||||||
)
|
)
|
||||||
# Désinscriptions:
|
# Désinscriptions:
|
||||||
do_desinscrit(sem, a_desinscrire)
|
do_desinscrit(sem, a_desinscrire)
|
||||||
@ -433,15 +447,21 @@ def _build_page(
|
|||||||
candidats_non_inscrits,
|
candidats_non_inscrits,
|
||||||
inscrits_ailleurs,
|
inscrits_ailleurs,
|
||||||
inscrit_groupes=False,
|
inscrit_groupes=False,
|
||||||
|
inscrit_parcours=False,
|
||||||
ignore_jury=False,
|
ignore_jury=False,
|
||||||
):
|
):
|
||||||
formsemestre: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
|
formsemestre: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
|
||||||
inscrit_groupes = int(inscrit_groupes)
|
inscrit_groupes = int(inscrit_groupes)
|
||||||
|
inscrit_parcours = int(inscrit_parcours)
|
||||||
ignore_jury = int(ignore_jury)
|
ignore_jury = int(ignore_jury)
|
||||||
if inscrit_groupes:
|
if inscrit_groupes:
|
||||||
inscrit_groupes_checked = " checked"
|
inscrit_groupes_checked = " checked"
|
||||||
else:
|
else:
|
||||||
inscrit_groupes_checked = ""
|
inscrit_groupes_checked = ""
|
||||||
|
if inscrit_parcours:
|
||||||
|
inscrit_parcours_checked = " checked"
|
||||||
|
else:
|
||||||
|
inscrit_parcours_checked = ""
|
||||||
if ignore_jury:
|
if ignore_jury:
|
||||||
ignore_jury_checked = " checked"
|
ignore_jury_checked = " checked"
|
||||||
else:
|
else:
|
||||||
@ -458,17 +478,23 @@ def _build_page(
|
|||||||
<a href="#help">aide</a>
|
<a href="#help">aide</a>
|
||||||
|
|
||||||
<input name="inscrit_groupes" type="checkbox" value="1"
|
<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()"
|
<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>
|
{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
|
<div class="pas_recap">Actuellement <span id="nbinscrits">{len(inscrits)}</span>
|
||||||
et {len(candidats_non_inscrits)} candidats supplémentaires
|
inscrits et {len(candidats_non_inscrits)} candidats supplémentaires.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>{scu.EMO_WARNING} <em>Seuls les semestres dont la date de fin est antérieure à la date de début
|
<div>{scu.EMO_WARNING}
|
||||||
de ce semestre ({formsemestre.date_debut.strftime("%d/%m/%Y")}) sont pris en compte.</em></div>
|
<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)}
|
{etuds_select_boxes(auth_etuds_by_sem, inscrits_ailleurs)}
|
||||||
|
|
||||||
<input type="submit" name="submitted" value="Appliquer les modifications"/>
|
<input type="submit" name="submitted" value="Appliquer les modifications"/>
|
||||||
@ -498,7 +524,8 @@ def _build_page(
|
|||||||
return H
|
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>
|
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
|
<p>Cette page permet d'inscrire des étudiants dans le semestre destination
|
||||||
<a class="stdlink"
|
<a class="stdlink"
|
||||||
@ -507,18 +534,34 @@ def formsemestre_inscr_passage_help(sem):
|
|||||||
}">{sem['titreannee']}</a>,
|
}">{sem['titreannee']}</a>,
|
||||||
et d'en désincrire si besoin.
|
et d'en désincrire si besoin.
|
||||||
</p>
|
</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.
|
<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
|
Ceux qui sont en <span class"inscrailleurs">gras et en rouge</span> sont inscrits
|
||||||
dans un <em>autre</em> semestre.</p>
|
dans un <em>autre</em> semestre.
|
||||||
<p>Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter d'autres
|
</p>
|
||||||
étudiants à inscrire dans le semestre destination.</p>
|
<p>Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter
|
||||||
<p>Si vous dé-selectionnez un étudiant déjà inscrit (en gras), il sera désinscrit.</p>
|
d'autres étudiants à inscrire dans le semestre destination.
|
||||||
<p>Le bouton <em>inscrire aux mêmes groupes</em> ne prend en compte que les groupes qui existent
|
</p>
|
||||||
dans les deux semestres: pensez à créer les partitions et groupes que vous souhaitez conserver
|
|
||||||
<b>avant</b> d'inscrire les étudiants.
|
<p>Si vous dé-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 (là 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>
|
||||||
<p class="help">Aucune action ne sera effectuée si vous n'appuyez pas sur le bouton "Appliquer les modifications" !</p>
|
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -468,7 +468,8 @@
|
|||||||
if (to[0] != "n") {
|
if (to[0] != "n") {
|
||||||
groupeSelected.closest(".grpPartitions").querySelector(`[value="${to}"]`).click();
|
groupeSelected.closest(".grpPartitions").querySelector(`[value="${to}"]`).click();
|
||||||
} else {
|
} else {
|
||||||
groupeSelected.closest(".grpPartitions").querySelector(`[value="aucun"]`).click();
|
let toNumber = to.split("-")[1];
|
||||||
|
groupeSelected.closest(".grpPartitions").querySelector(`[data-idpartition="${toNumber}"] [value="aucun"]`).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user