Creation d'une partition avec les groupes d'étapes

This commit is contained in:
viennet 2020-12-01 16:46:45 +01:00
parent 9477caf06a
commit 317252575a
11 changed files with 938 additions and 425 deletions

View File

@ -1616,8 +1616,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
security.declareProtected(ScoView, "view_module_abs")
def view_module_abs(self, REQUEST, moduleimpl_id, format="html"):
"""Visulalisation des absences a un module
"""
"""Visulalisation des absences a un module"""
M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0]
sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"])
debut_sem = DateDMYtoISO(sem["date_debut"])
@ -1903,7 +1902,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
_formsemestre_inscriptionEditor = EditableTable(
"notes_formsemestre_inscription",
"formsemestre_inscription_id",
("formsemestre_inscription_id", "etudid", "formsemestre_id", "etat"),
("formsemestre_inscription_id", "etudid", "formsemestre_id", "etat", "etape"),
sortkey="formsemestre_id",
)
@ -2011,7 +2010,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
):
"""desinscrit l'etudiant de ce semestre (et donc de tous les modules).
A n'utiliser qu'en cas d'erreur de saisie.
S'il s'agit d'un semestre extérieur et qu'il n'y a plus d'inscrit,
S'il s'agit d'un semestre extérieur et qu'il n'y a plus d'inscrit,
le semestre sera supprimé.
"""
sem = sco_formsemestre.get_formsemestre(self, formsemestre_id)
@ -2264,8 +2263,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
security.declareProtected(ScoEtudInscrit, "etud_desinscrit_ue")
def etud_desinscrit_ue(self, etudid, formsemestre_id, ue_id, REQUEST=None):
"""Desinscrit l'etudiant de tous les modules de cette UE dans ce semestre.
"""
"""Desinscrit l'etudiant de tous les modules de cette UE dans ce semestre."""
sco_moduleimpl_inscriptions.do_etud_desinscrit_ue(
self, etudid, formsemestre_id, ue_id, REQUEST=REQUEST
)
@ -2278,8 +2276,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
security.declareProtected(ScoEtudInscrit, "etud_inscrit_ue")
def etud_inscrit_ue(self, etudid, formsemestre_id, ue_id, REQUEST=None):
"""Inscrit l'etudiant de tous les modules de cette UE dans ce semestre.
"""
"""Inscrit l'etudiant de tous les modules de cette UE dans ce semestre."""
sco_moduleimpl_inscriptions.do_etud_inscrit_ue(
self, etudid, formsemestre_id, ue_id, REQUEST=REQUEST
)
@ -2411,8 +2408,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
REQUEST=None,
**kw
):
"""Create an evaluation
"""
"""Create an evaluation"""
args = locals()
log("do_evaluation_create: args=" + str(args))
self._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
@ -2758,8 +2754,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
def can_edit_notes(self, authuser, moduleimpl_id, allow_ens=True):
"""True if authuser can enter or edit notes in this module.
If allow_ens, grant access to all ens in this module
Si des décisions de jury ont déjà été saisies dans ce semestre,
Si des décisions de jury ont déjà été saisies dans ce semestre,
seul le directeur des études peut saisir des notes (et il ne devrait pas).
"""
uid = str(authuser)
@ -3319,8 +3315,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
def formsemestre_validation_suppress_etud(
self, formsemestre_id, etudid, REQUEST=None, dialog_confirmed=False
):
"""Suppression des decisions de jury pour un etudiant.
"""
"""Suppression des decisions de jury pour un etudiant."""
if not self._can_validate_sem(REQUEST, formsemestre_id):
return self.confirmDialog(
message="<p>Opération non autorisée pour %s</h2>"

File diff suppressed because it is too large Load Diff

View File

@ -487,6 +487,7 @@ CREATE TABLE notes_formsemestre_inscription (
etudid text REFERENCES identite(etudid),
formsemestre_id text REFERENCES notes_formsemestre(formsemestre_id),
etat text, -- I inscrit, D demission en cours de semestre, DEF si "defaillant"
etape text, -- etape apogee d'inscription (experimental 2020)
UNIQUE(formsemestre_id, etudid)
) WITH OIDS;

View File

@ -45,10 +45,11 @@ def do_formsemestre_inscription_with_modules(
etudid,
group_ids=[],
etat="I",
etape=None,
REQUEST=None,
method="inscription_with_modules",
):
"""Inscrit cet etudiant a ce semestre et TOUS ses modules STANDARDS
"""Inscrit cet etudiant à ce semestre et TOUS ses modules STANDARDS
(donc sauf le sport)
"""
# inscription au semestre
@ -258,8 +259,7 @@ def formsemestre_inscription_with_modules(
def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=None):
"""Dialogue pour (des)inscription a des modules optionnels
"""
"""Dialogue pour (dés)inscription à des modules optionnels."""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
if sem["etat"] != "1":
raise ScoValueError("Modification impossible: semestre verrouille")
@ -320,14 +320,11 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No
sem_origin = sco_formsemestre.get_formsemestre(
context, ue_status["formsemestre_id"]
)
ue_descr += (
' <a class="discretelink" href="formsemestre_bulletinetud?formsemestre_id=%s&amp;etudid=%s" title="%s">(capitalisée le %s)'
% (
sem_origin["formsemestre_id"],
etudid,
sem_origin["titreannee"],
DateISOtoDMY(ue_status["event_date"]),
)
ue_descr += ' <a class="discretelink" href="formsemestre_bulletinetud?formsemestre_id=%s&amp;etudid=%s" title="%s">(capitalisée le %s)' % (
sem_origin["formsemestre_id"],
etudid,
sem_origin["titreannee"],
DateISOtoDMY(ue_status["event_date"]),
)
descr.append(
(

View File

@ -63,7 +63,7 @@ def checkGroupName(
): # XXX unused: now allow any string as a group or partition name
"Raises exception if not a valid group name"
if groupName and (
not re.match("^\w+$", groupName) or (simplesqlquote(groupName) != groupName)
not re.match(r"^\w+$", groupName) or (simplesqlquote(groupName) != groupName)
):
log("!!! invalid group name: " + groupName)
raise ValueError("invalid group name: " + groupName)
@ -103,8 +103,7 @@ def get_group(context, group_id):
def group_delete(context, group, force=False):
"""Delete a group.
"""
"""Delete a group."""
# if not group['group_name'] and not force:
# raise ValueError('cannot suppress this group')
# remove memberships:
@ -156,8 +155,7 @@ def get_default_partition(context, formsemestre_id):
def get_formsemestre_groups(context, formsemestre_id, with_default=False):
"""Returns ( partitions, { partition_id : { etudid : group } } )
"""
"""Returns ( partitions, { partition_id : { etudid : group } } )."""
partitions = get_partitions_list(
context, formsemestre_id, with_default=with_default
)
@ -179,8 +177,7 @@ def get_partition_groups(context, partition):
def get_default_group(context, formsemestre_id, fix_if_missing=False, REQUEST=None):
"""Returns group_id for default ('tous') group
"""
"""Returns group_id for default ('tous') group"""
r = SimpleDictFetch(
context,
"SELECT gd.group_id FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_name is NULL AND p.partition_id = gd.partition_id",
@ -261,10 +258,8 @@ def get_group_members(context, group_id, etat=None):
def get_group_infos(context, group_id, etat=None): # was _getlisteetud
"""legacy code: used by group_list and trombino
"""
"""legacy code: used by group_list and trombino"""
cnx = context.GetDBConnexion()
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
group = get_group(context, group_id)
sem = sco_formsemestre.get_formsemestre(context, group["formsemestre_id"])
@ -370,8 +365,7 @@ def formsemestre_get_etud_groupnames(context, formsemestre_id, attr="group_name"
def etud_add_group_infos(context, etud, sem, sep=" "):
"""Add informations on partitions and group memberships to etud (a dict with an etudid)
"""
"""Add informations on partitions and group memberships to etud (a dict with an etudid)"""
etud[
"partitions"
] = collections.OrderedDict() # partition_id : group + partition_name
@ -553,8 +547,7 @@ def set_group(context, etudid, group_id):
def change_etud_group_in_partition(
context, etudid, group_id, partition=None, REQUEST=None
):
"""Inscrit etud au groupe de cette partition, et le desinscrit d'autres groupes de cette partition.
"""
"""Inscrit etud au groupe de cette partition, et le desinscrit d'autres groupes de cette partition."""
log("change_etud_group_in_partition: etudid=%s group_id=%s" % (etudid, group_id))
# 0- La partition
@ -700,7 +693,7 @@ def createGroup(context, partition_id, group_name="", default=False, REQUEST=Non
"""
partition = get_partition(context, partition_id)
formsemestre_id = partition["formsemestre_id"]
if not context.Notes.can_change_groups(REQUEST, formsemestre_id):
if REQUEST and not context.Notes.can_change_groups(REQUEST, formsemestre_id):
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
#
if group_name:
@ -756,7 +749,7 @@ def partition_create(
redirect=1,
):
"""Create a new partition"""
if not context.Notes.can_change_groups(REQUEST, formsemestre_id):
if REQUEST and not context.Notes.can_change_groups(REQUEST, formsemestre_id):
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
if partition_name:
partition_name = partition_name.strip()
@ -800,7 +793,8 @@ def getArrowIconsTags(context, REQUEST):
def editPartitionForm(context, formsemestre_id=None, REQUEST=None):
"""Form to create/suppress partitions"""
# ad-hoc form
canedit = context.Notes.can_change_groups(REQUEST, formsemestre_id)
if not context.Notes.can_change_groups(REQUEST, formsemestre_id):
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
partitions = get_partitions_list(context, formsemestre_id)
arrow_up, arrow_down, arrow_none = getArrowIconsTags(context, REQUEST)
suppricon = icontag(
@ -1294,6 +1288,48 @@ def get_prev_moy(context, etudid, formsemestre_id):
return 0.0
def create_etapes_partition(context, formsemestre_id, partition_name="apo_etapes"):
"""Crée une partition "apo_etapes" avec un groupe par étape Apogée.
Cette partition n'est crée que si plusieurs étapes différentes existent dans ce
semestre.
Si la partition existe déjà, ses groupes sont mis à jour (les groupes devenant
vides ne sont pas supprimés).
"""
log("create_etapes_partition(%s)" % formsemestre_id)
ins = context.do_formsemestre_inscription_list(
args={"formsemestre_id": formsemestre_id}
)
etapes = {i["etape"] for i in ins if i["etape"]}
partitions = get_partitions_list(context, formsemestre_id, with_default=False)
partition = None
for p in partitions:
if p["partition_name"] == partition_name:
partition = p
break
if len(etapes) < 2 and not partition:
return # moins de deux étapes, pas de création
if partition:
pid = partition["partition_id"]
else:
pid = partition_create(
context, formsemestre_id, partition_name=partition_name, redirect=False
)
partition = get_partition(context, pid)
groups = get_partition_groups(context, partition)
groups_by_names = {g["group_name"]: g for g in groups}
for etape in etapes:
if not (etape in groups_by_names):
gid = createGroup(context, pid, etape)
g = get_group(context, gid)
groups_by_names[etape] = g
# Place les etudiants dans les groupes
for i in ins:
if i["etape"]:
change_etud_group_in_partition(
context, i["etudid"], groups_by_names[i["etape"]]["group_id"], partition
)
def do_evaluation_listeetuds_groups(
context, evaluation_id, groups=None, getallstudents=False, include_dems=False
):
@ -1340,7 +1376,7 @@ def do_evaluation_listeetuds_groups(
def do_evaluation_listegroupes(context, evaluation_id, include_default=False):
"""Donne la liste des groupes dans lesquels figurent des etudiants inscrits
"""Donne la liste des groupes dans lesquels figurent des etudiants inscrits
au module/semestre auquel appartient cette evaluation.
Si include_default, inclue aussi le groupe par defaut ('tous')
[ group ]

View File

@ -47,8 +47,6 @@ def affectGroups(context, partition_id, REQUEST=None):
if not context.Notes.can_change_groups(REQUEST, formsemestre_id):
raise AccessDenied("vous n'avez pas la permission d'effectuer cette opération")
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.sco_header(
REQUEST,

View File

@ -429,8 +429,12 @@ def groups_table(
):
"""liste etudiants inscrits dans ce semestre
format: csv, json, xml, xls, allxls, xlsappel, moodlecsv, pdf
Si with_codes, ajoute 3 colonnes avec les codes etudid, NIP, INE
Si with_codes, ajoute 4 colonnes avec les codes etudid, NIP, INE et etape
"""
log(
"enter groups_table %s: %s"
% (groups_infos.members[0]["nom"], groups_infos.members[0].get("etape", "-"))
)
authuser = REQUEST.AUTHENTICATED_USER
with_codes = int(with_codes)
@ -784,8 +788,7 @@ def groups_table(
def tab_absences_html(context, groups_infos, etat=None, REQUEST=None):
"""contenu du tab "absences et feuilles diverses"
"""
"""contenu du tab "absences et feuilles diverses" """
authuser = REQUEST.AUTHENTICATED_USER
H = ['<div class="tab-content">']
if not groups_infos.members:
@ -841,8 +844,7 @@ def tab_absences_html(context, groups_infos, etat=None, REQUEST=None):
def tab_photos_html(context, groups_infos, etat=None, REQUEST=None):
"""contenu du tab "photos"
"""
"""contenu du tab "photos" """
if not groups_infos.members:
return '<div class="tab-content"><h3>Aucun étudiant !</h3></div>'
@ -850,8 +852,7 @@ def tab_photos_html(context, groups_infos, etat=None, REQUEST=None):
def form_choix_jour_saisie_hebdo(context, groups_infos, REQUEST=None):
"""Formulaire choix jour semaine pour saisie.
"""
"""Formulaire choix jour semaine pour saisie."""
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoAbsChange, context):
return ""
@ -893,7 +894,7 @@ def export_groups_as_moodle_csv(context, formsemestre_id=None, REQUEST=None):
jo@univ.fr,S3-A
jo@univ.fr,S3-B1
if jo belongs to group A in a partition, and B1 in another one.
Caution: if groups in different partitions share the same name, there will be
Caution: if groups in different partitions share the same name, there will be
duplicates... should we prefix the group names with the partition's name ?
"""
if not formsemestre_id:

View File

@ -508,7 +508,7 @@ def check_paiement_etuds(context, etuds):
Seuls les etudiants avec code NIP sont renseignés.
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud.
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud, ainsi que l'étape.
En sortie: modif les champs de chaque etud
'paiementinscription' : True, False ou None

View File

@ -596,6 +596,8 @@ def formsemestre_pvjury_pdf(
Si etudid, PV pour un seul etudiant. Sinon, tout les inscrits au groupe indiqué.
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Mise à jour des groupes d'étapes:
sco_groups.create_etapes_partition(context, formsemestre_id)
groups_infos = None
if etudid:
# PV pour ce seul étudiant:

View File

@ -438,7 +438,7 @@ def table_suivi_cohorte(
for s in sems:
ins = context.do_formsemestre_inscription_list(
args={"formsemestre_id": s["formsemestre_id"]}
) # avec dems
) # sans dems
inset = Set([i["etudid"] for i in ins])
s["members"] = orig_set.intersection(inset)
nb_dipl = 0 # combien de diplomes dans ce semestre ?

View File

@ -597,6 +597,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES
# Les champs suivants sont facultatifs (pas toujours renvoyés par le portail)
"code_ine": etud.get("ine", "").strip(),
"sexe": gender2sex(etud["gender"].strip()),
"etape": etud.get("etape", None),
"email": etud.get("mail", "").strip(),
"emailperso": etud.get("mailperso", "").strip(),
"date_naissance": etud.get("naissance", "").strip(),
@ -619,7 +620,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES
do_import_etud_admission(context, cnx, args["etudid"], etud)
# Adresse
adresse_id = scolars.adresse_create(cnx, args)
scolars.adresse_create(cnx, args)
# Inscription au semestre
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
@ -627,6 +628,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES
sem["formsemestre_id"],
args["etudid"],
etat="I",
etape=args["etape"],
REQUEST=REQUEST,
method="synchro_apogee",
)
@ -754,6 +756,18 @@ def get_bac(etud):
return serie_bac, spe_bac
def update_etape_formsemestre_inscription(context, ins, etud):
"""Met à jour l'étape de l'inscription.
Args:
ins (dict): formsemestre_inscription
etud (dict): etudiant portail Apo
"""
if etud["etape"] != ins["etape"]:
ins["etape"] = etud["etape"]
context.do_formsemestre_inscription_edit(args=ins)
def formsemestre_import_etud_admission(
context, formsemestre_id, import_identite=True, import_email=False
):
@ -797,6 +811,7 @@ def formsemestre_import_etud_admission(
# pas vu dans les etudiants de l'étape, tente en individuel
etud = sco_portal_apogee.get_etud_apogee(context, code_nip)
if etud:
update_etape_formsemestre_inscription(context, i, etud)
do_import_etud_admission(
context,
cnx,