diff --git a/app/scodoc/notesdb.py b/app/scodoc/notesdb.py index 5a53c544..6fa29fb9 100644 --- a/app/scodoc/notesdb.py +++ b/app/scodoc/notesdb.py @@ -96,7 +96,7 @@ def DBInsertDict( convert_empty_to_nulls=1, return_id=True, ignore_conflicts=False, -): +) -> int: """insert into table values in dict 'vals' Return: id de l'object créé """ @@ -327,7 +327,7 @@ class EditableTable(object): self.sql_default_values = None self.insert_ignore_conflicts = insert_ignore_conflicts - def create(self, cnx, args): + def create(self, cnx, args) -> int: "create object in table" vals = dictfilter(args, self.dbfields, self.filter_nulls) if self.id_name in vals: diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index dc1b4f84..8cf7c3c0 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -461,7 +461,7 @@ def ue_list(formation_id=None, msg=""): else: lockicon = "" - arrow_up, arrow_down, arrow_none = sco_groups.getArrowIconsTags() + arrow_up, arrow_down, arrow_none = sco_groups.get_arrow_icons_tags() delete_icon = scu.icontag( "delete_small_img", title="Supprimer (module inutilisé)", alt="supprimer" ) diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py index e65a9205..6d29b8cf 100644 --- a/app/scodoc/sco_formsemestre.py +++ b/app/scodoc/sco_formsemestre.py @@ -246,7 +246,7 @@ def do_formsemestre_create(args, silent=False): default=True, redirect=0, ) - _group_id = sco_groups.createGroup(partition_id, default=True) + _group_id = sco_groups.create_group(partition_id, default=True) # news if "titre" not in args: diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index e66ca28d..fb6c6a54 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -51,6 +51,7 @@ from app.scodoc import sco_etud from app.scodoc import sco_evaluations from app.scodoc import sco_formations from app.scodoc import sco_formsemestre +from app.scodoc import sco_groups_copy from app.scodoc import sco_modalites from app.scodoc import sco_moduleimpl from app.scodoc import sco_parcours_dut @@ -1073,32 +1074,11 @@ def do_formsemestre_clone( args["formsemestre_id"] = formsemestre_id _ = sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, args) - # 5- Copy partitions + # 5- Copy partitions and groups if clone_partitions: - listgroups = [] - listnamegroups = [] - # Création des partitions: - for part in sco_groups.get_partitions_list(orig_formsemestre_id): - if part["partition_name"] != None: - partname = part["partition_name"] - new_partition_id = sco_groups.partition_create( - formsemestre_id, - partition_name=partname, - redirect=0, - ) - for g in sco_groups.get_partition_groups(part): - if g["group_name"] != None: - listnamegroups.append(g["group_name"]) - listgroups.append([new_partition_id, listnamegroups]) - listnamegroups = [] - - # Création des groupes dans les nouvelles partitions: - for newpart in sco_groups.get_partitions_list(formsemestre_id): - for g in listgroups: - if newpart["partition_id"] == g[0]: - part_id = g[0] - for group_name in g[1]: - _ = sco_groups.createGroup(part_id, group_name=group_name) + sco_groups_copy.clone_partitions_and_groups( + orig_formsemestre_id, formsemestre_id + ) return formsemestre_id diff --git a/app/scodoc/sco_groups.py b/app/scodoc/sco_groups.py index dac98924..dd1de1f3 100644 --- a/app/scodoc/sco_groups.py +++ b/app/scodoc/sco_groups.py @@ -60,18 +60,6 @@ from app.scodoc.sco_permissions import Permission from app.scodoc.TrivialFormulator import TrivialFormulator -def checkGroupName( - groupName, -): # 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(r"^\w+$", groupName) - or (scu.simplesqlquote(groupName) != groupName) - ): - log("!!! invalid group name: " + groupName) - raise ValueError("invalid group name: " + groupName) - - partitionEditor = ndb.EditableTable( "partition", "partition_id", @@ -217,7 +205,7 @@ def get_default_group(formsemestre_id, fix_if_missing=False): partition_id = partition_create( formsemestre_id, default=True, redirect=False ) - group_id = createGroup(partition_id, default=True) + group_id = create_group(partition_id, default=True) return group_id # debug check if len(r) != 1: @@ -722,7 +710,7 @@ def setGroups( # Supprime les groupes indiqués comme supprimés: for group_id in groupsToDelete: - suppressGroup(group_id, partition_id=partition_id) + delete_group(group_id, partition_id=partition_id) # Crée les nouveaux groupes for line in groupsToCreate.split("\n"): # for each group_name (one per line) @@ -730,7 +718,7 @@ def setGroups( group_name = fs[0].strip() if not group_name: continue - group_id = createGroup(partition_id, group_name) + group_id = create_group(partition_id, group_name) # Place dans ce groupe les etudiants indiqués: for etudid in fs[1:-1]: change_etud_group_in_partition(etudid, group_id, partition) @@ -743,7 +731,7 @@ def setGroups( return response -def createGroup(partition_id, group_name="", default=False): +def create_group(partition_id, group_name="", default=False) -> int: """Create a new group in this partition""" partition = get_partition(partition_id) formsemestre_id = partition["formsemestre_id"] @@ -763,12 +751,12 @@ def createGroup(partition_id, group_name="", default=False): group_id = groupEditor.create( cnx, {"partition_id": partition_id, "group_name": group_name} ) - log("createGroup: created group_id=%s" % group_id) + log("create_group: created group_id=%s" % group_id) # return group_id -def suppressGroup(group_id, partition_id=None): +def delete_group(group_id, partition_id=None): """form suppression d'un groupe. (ne desinscrit pas les etudiants, change juste leur affectation aux groupes) @@ -785,7 +773,7 @@ def suppressGroup(group_id, partition_id=None): if not sco_permissions_check.can_change_groups(partition["formsemestre_id"]): raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") log( - "suppressGroup: group_id=%s group_name=%s partition_name=%s" + "delete_group: group_id=%s group_name=%s partition_name=%s" % (group_id, group["group_name"], partition["partition_name"]) ) group_delete(group) @@ -834,7 +822,7 @@ def partition_create( return partition_id -def getArrowIconsTags(): +def get_arrow_icons_tags(): """returns html tags for arrows""" # arrow_up = scu.icontag("arrow_up", title="remonter") @@ -850,7 +838,7 @@ def editPartitionForm(formsemestre_id=None): if not sco_permissions_check.can_change_groups(formsemestre_id): raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") partitions = get_partitions_list(formsemestre_id) - arrow_up, arrow_down, arrow_none = getArrowIconsTags() + arrow_up, arrow_down, arrow_none = get_arrow_icons_tags() suppricon = scu.icontag( "delete_small_img", border="0", alt="supprimer", title="Supprimer" ) @@ -1153,7 +1141,7 @@ def partition_set_name(partition_id, partition_name, redirect=1): ) -def group_set_name(group_id, group_name, redirect=1): +def group_set_name(group_id, group_name, redirect=True): """Set group name""" if group_name: group_name = group_name.strip() @@ -1223,7 +1211,7 @@ def group_rename(group_id): ) else: # form submission - return group_set_name(group_id, tf[2]["group_name"], redirect=1) + return group_set_name(group_id, tf[2]["group_name"]) def groups_auto_repartition(partition_id=None): @@ -1298,7 +1286,7 @@ def groups_auto_repartition(partition_id=None): # except: # H.append('

Nom de groupe invalide: %s

'%group_name) # return '\n'.join(H) + tf[1] + html_sco_header.sco_footer() - group_ids.append(createGroup(partition_id, group_name)) + group_ids.append(create_group(partition_id, group_name)) # nt = sco_cache.NotesTableCache.get(formsemestre_id) # > identdict identdict = nt.identdict @@ -1382,7 +1370,7 @@ def create_etapes_partition(formsemestre_id, partition_name="apo_etapes"): groups_by_names = {g["group_name"]: g for g in groups} for etape in etapes: if not (etape in groups_by_names): - gid = createGroup(pid, etape) + gid = create_group(pid, etape) g = get_group(gid) groups_by_names[etape] = g # Place les etudiants dans les groupes diff --git a/app/scodoc/sco_groups_copy.py b/app/scodoc/sco_groups_copy.py new file mode 100644 index 00000000..77d6e1d0 --- /dev/null +++ b/app/scodoc/sco_groups_copy.py @@ -0,0 +1,66 @@ +from app import db + +from app.scodoc import sco_groups +import app.scodoc.notesdb as ndb + + +def clone_partitions_and_groups( + orig_formsemestre_id: int, formsemestre_id: int, inscrit_etuds=False +): + """Crée dans le semestre formsemestre_id les mêmes partitions et groupes que ceux + de orig_formsemestre_id. + Si inscrit_etuds, inscrit les mêmes étudiants (rarement souhaité). + """ + list_groups_per_part = [] + list_groups = [] + groups_old2new = {} # old group_id : new_group_id + # Création des partitions: + for part in sco_groups.get_partitions_list(orig_formsemestre_id): + if part["partition_name"] is not None: + partname = part["partition_name"] + new_partition_id = sco_groups.partition_create( + formsemestre_id, + partition_name=partname, + numero=part["numero"], + redirect=False, + ) + for group in sco_groups.get_partition_groups(part): + if group["group_name"] != None: + list_groups.append(group) + list_groups_per_part.append([new_partition_id, list_groups]) + list_groups = [] + + # Création des groupes dans les nouvelles partitions: + for newpart in sco_groups.get_partitions_list(formsemestre_id): + for (new_partition_id, list_groups) in list_groups_per_part: + if newpart["partition_id"] == new_partition_id: + for group in list_groups: + new_group_id = sco_groups.create_group( + new_partition_id, group_name=group["group_name"] + ) + groups_old2new[group["group_id"]] = new_group_id + # + if inscrit_etuds: + cnx = ndb.GetDBConnexion() + cursor = cnx.cursor() + for old_group_id, new_group_id in groups_old2new.items(): + cursor.execute( + """ + WITH etuds AS ( + SELECT gm.etudid + FROM group_membership gm, notes_formsemestre_inscription ins + WHERE ins.etudid = gm.etudid + AND ins.formsemestre_id = %(orig_formsemestre_id)s + AND gm.group_id=%(old_group_id)s + ) + INSERT INTO group_membership (etudid, group_id) + SELECT *, %(new_group_id)s FROM etuds + ON CONFLICT DO NOTHING + """, + { + "orig_formsemestre_id": orig_formsemestre_id, + "old_group_id": old_group_id, + "new_group_id": new_group_id, + }, + ) + cnx.commit() diff --git a/app/scodoc/sco_groups_edit.py b/app/scodoc/sco_groups_edit.py index bc419690..d5e09b76 100644 --- a/app/scodoc/sco_groups_edit.py +++ b/app/scodoc/sco_groups_edit.py @@ -42,7 +42,7 @@ def affect_groups(partition_id): partition = sco_groups.get_partition(partition_id) formsemestre_id = partition["formsemestre_id"] if not sco_groups.sco_permissions_check.can_change_groups(formsemestre_id): - raise AccessDenied("vous n'avez pas la permission d'effectuer cette opération") + raise AccessDenied("vous n'avez pas la permission de modifier les groupes") return render_template( "scolar/affect_groups.html", sco_header=html_sco_header.sco_header( diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index 633b7368..c358b25c 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -176,7 +176,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None): current_user, moduleimpl_id, allow_ens=sem["ens_can_edit_eval"] ) caneditnotes = sco_permissions_check.can_edit_notes(current_user, moduleimpl_id) - arrow_up, arrow_down, arrow_none = sco_groups.getArrowIconsTags() + arrow_up, arrow_down, arrow_none = sco_groups.get_arrow_icons_tags() # module_resp = User.query.get(M["responsable_id"]) H = [ diff --git a/app/views/scolar.py b/app/views/scolar.py index 3e5f3c3d..0e06d924 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -669,9 +669,18 @@ sco_publish( sco_publish("/setGroups", sco_groups.setGroups, Permission.ScoView) -sco_publish("/createGroup", sco_groups.createGroup, Permission.ScoView) +sco_publish("/create_group", sco_groups.create_group, Permission.ScoView) + + +@bp.route("/suppressGroup") # backward compat (ScoDoc7 API) +@bp.route("/delete_group") +@scodoc +@permission_required(Permission.ScoView) +@scodoc7func +def delete_group(group_id, partition_id): + sco_groups.delete_group(group_id=group_id, partition_id=partition_id) + return "", 204 -sco_publish("/suppressGroup", sco_groups.suppressGroup, Permission.ScoView) sco_publish( "/group_set_name", diff --git a/tests/unit/test_abs_demijournee.py b/tests/unit/test_abs_demijournee.py index 40a617f9..46a81bba 100644 --- a/tests/unit/test_abs_demijournee.py +++ b/tests/unit/test_abs_demijournee.py @@ -119,7 +119,7 @@ def test_abs_basic(test_client): - sco_abs.get_abs_count(etudid, sem) - ListeAbsEtud - partition_create - - createGroup + - create_group - set_group - EtatAbsenceGr - AddBilletAbsence @@ -268,7 +268,7 @@ def test_abs_basic(test_client): partition_name="Eleve", ) li1 = sco_groups.get_partitions_list(sem["formsemestre_id"]) - _ = sco_groups.createGroup(li1[0]["partition_id"], "Groupe 1") + _ = sco_groups.create_group(li1[0]["partition_id"], "Groupe 1") # --- Affectation des élèves dans des groupes