Groupe
Les différents groupes
Il existe 6 types de groupes :
- 'ProfileGroup' : Groupes de profil
 - 'FunctionalGroup' : Groupes fonctionnels.
 - 'ManualGroup': Groupes gérés manuellement
 - 'FunctionGroup' : Groupes par fonction, par discipline
 - 'BroadcastGroup' : Liste de diffusion
 - 'Classes'
 
Groupes de profils (ProfileGroup)
Les utilisateurs sont dans un groupes de profils (ProfileGroup).
Chaque groupe est associé à une classe (relation DEPENDS).
Chaque classe est associée à une structure (relation BELONGS).
Chaque groupe a un profil (Teacher, Personnel, Student, Relation) (relation HAS_PROFILE).

Création des profils
// Création du profil Teacher
CREATE (p:Profile {externalId: "PROFILE_TEACHER", name: "Teacher"});
// Création du profil Personnel
CREATE (p:Profile {externalId: "PROFILE_PERSONNEL", name: "Personnel"});
// Création du profil Student
CREATE (p:Profile {externalId: "PROFILE_STUDENT", name: "Student"});
// Création du profil Relative
CREATE (p:Profile {externalId: "PROFILE_RELATIVE", name: "Relative"});
Création des profils group
// Création du profil Teacher
CREATE (p:ProfileGroup {id: "PROFILE_TEACHER", externalId: "PROFILE_TEACHER", name: "Teacher"});
// Création du profil Personnel
CREATE (p:ProfileGroup {id: "PROFILE_PERSONNEL", externalId: "PROFILE_PERSONNEL", name: "Personnel"});
// Création du profil Student
CREATE (p:ProfileGroup {id: "PROFILE_STUDENT", externalId: "PROFILE_STUDENT", name: "Student"});
// Création du profil Relative
CREATE (p:ProfileGroup {id: "PROFILE_RELATIVE", externalId: "PROFILE_RELATIVE", name: "Relative"});
Création des relations
Création de la relation HAS_PROFILE entre ProfileGroup et Profile
// Créer une relation HAS_PROFILE entre ProfileGroup et Profile
:params {
    structureId: 'b3380c81-e5c7-49fa-9058-a5afce4cd1ea',
    profileName: 'Teacher',
    profileGroupName: 'Teacher Group'
}
MATCH (pg:ProfileGroup { name: $profileGroupName })
MERGE (p:Profile { name: $profileName })
CREATE (pg)-[:HAS_PROFILE]->(p)
Création de la relation DEPENDS entre ProfileGroup et Structure
// Creer une relation DEPENDS entre ProfileGroup et Structure
MATCH (s:Structure { id: $structureId })
MATCH (pg:ProfileGroup { name: $profileGroupName })
CREATE (pg)-[:DEPENDS]->(s)
Suppression des relations
// Supprimer une relation DEPENDS entre une structure et un ProfileGroup
MATCH (a:ProfileGroup { name: $profileGroupName })-[r:DEPENDS]->(b:Structure { id: $structureId })
DELETE r;
// Supprimer une relation HAS_PROFILE entre un ProfileGroup et un Profile
MATCH (pg:ProfileGroup { name: $profileGroupName })-[r:HAS_PROFILE]->(p:Profile { name: $profileName })
RETURN r;
Groupes fonctionnels (FunctionalGroup)
On retrouve ici les groupes tels que :
- la direction (
Direction), - le personnel administratif (
SCOLARITE) - les professeurs principaux (
HeadTeacher) 
Exemple de groupe de Direction :

Groupes par fonction (FunctionGroup)
Un des groupes par fonction principal est le groupe permettant de gérer les administrateurs de l'établissement.
(groupe AdminLocal)
Exemple de groupe par discipline (DisciplineGroup):

Information détaillée sur les groupes
Cette requête sert à obtenir des informations détaillées sur les groupes, y compris leurs relations avec les structures et les classes, les labels, et des propriétés spécifiques comme les règles de communication ou le nombre d'utilisateurs. Le résultat final est enrichi en catégorisant le groupe (subType) et en collectant les structures et classes associées.
MATCH (s:Structure)<-[:BELONGS*0..1]-()<-[:DEPENDS]-(g:Group)
OPTIONAL MATCH (g)-[:DEPENDS]->(c:Class)
WITH g, 
     collect({name: c.name, id: c.id}) as classes, 
     collect(distinct {name: s.name, id: s.id}) as structures, 
     [x IN labels(g) WHERE x <> 'Visible' AND x <> 'Group'] AS filteredLabels,
     head([x IN labels(g) WHERE x <> 'Visible' AND x <> 'Group']) as type
RETURN DISTINCT g.id as id, 
       g.name as name, 
       g.displayName as displayName, 
       g.filter as filter, 
       labels(g) as labels, 
       g.autolinkTargetAllStructs as autolinkTargetAllStructs, 
       g.autolinkTargetStructs as autolinkTargetStructs,
       g.autolinkUsersFromGroups as autolinkUsersFromGroups, 
       type, 
       g.users as internalCommunicationRule, 
       g.lockDelete AS lockDelete, 
       coalesce(g.nbUsers, 0) as nbUsers, 
       CASE WHEN any(x IN classes WHERE x.name IS NOT NULL AND x.id IS NOT NULL) THEN classes END as classes,
       CASE WHEN any(x IN structures WHERE x.name IS NOT NULL AND x.id IS NOT NULL) THEN structures END as structures,
       CASE 
           WHEN (g:ProfileGroup)-[:DEPENDS]-(:Structure) THEN 'StructureGroup'
           WHEN (g:ProfileGroup)-[:DEPENDS]->(:Class) THEN 'ClassGroup'
           WHEN EXISTS(g.subType) THEN g.subType
           WHEN (g:ManualGroup) AND (
               g.autolinkTargetAllStructs = true OR 
               size(coalesce(g.autolinkUsersFromGroups, [])) > 0 OR 
               size(coalesce(g.autolinkTargetStructs, [])) > 0
           ) THEN 'BroadcastGroup'
       END as subType;
Utilisateur dans un groupe
MATCH (g:Group) 
WHERE g.id = 68171
MATCH (u:User)-[:IN]->(g) 
RETURN u
Ajouter des utilisateurs à un groupe
MATCH (u:User { id: $userId }), (f:Group { id: $groupId }) 
WHERE 'ManualGroup' IN labels(f) OR 'FunctionalGroup' IN labels(f) 
MERGE (u)-[:IN { source: 'MANUAL' }]->(f) 
WITH f, u 
WHERE 'FunctionalGroup' IN labels(f) 
SET u.groups = [gId IN coalesce(u.groups, []) WHERE gId <> f.externalId] + f.externalId
Cette requête Cypher a pour but d'ajouter un utilisateur (User) à un groupe (Group) sous certaines conditions, tout en maintenant une liste des groupes auxquels il appartient.
Explication détaillée de la requête
MATCH (u:User { id: $userId }), (f:Group { id: $groupId }) 
- Recherche un utilisateur (
User) et un groupe (Group) en fonction de leurs identifiants respectifs ($userIdet$groupId). 
WHERE 'ManualGroup' IN labels(f) OR 'FunctionalGroup' IN labels(f) 
- Filtre uniquement certains types de groupes :
- Soit un 
ManualGroup - Soit un 
FunctionalGroup 
 - Soit un 
 
MERGE (u)-[:IN { source: 'MANUAL' }]->(f) 
- Crée (ou assure l'existence) d'une relation 
INentre l'utilisateuruet le groupef. - La relation a un attribut 
source: 'MANUAL', indiquant que l'ajout est fait manuellement. 
WITH f, u 
WHERE 'FunctionalGroup' IN labels(f) 
- Continue uniquement si 
fest unFunctionalGroup. - Cela signifie que la mise à jour des groupes ne se fait que pour ce type de groupe.
 
SET u.groups = [gId IN coalesce(u.groups, []) WHERE gId <> f.externalId] + f.externalId
- Met à jour la propriété 
groupsde l'utilisateuruen :- Filtrant les anciens groupes (
u.groups) pour supprimer l'ID externe (externalId) defs'il est déjà présent. - Ajoutant 
f.externalIdà la liste des groupes. 
 - Filtrant les anciens groupes (
 
Objectif fonctionnel
- Cette requête ajoute un utilisateur à un groupe, mais ne duplique pas l'ajout s'il est déjà dans le groupe.
 - Elle maintient une liste 
groupssur l'utilisateur, qui stocke lesexternalIddes groupes de typeFunctionalGroupuniquement. 
Exemple concret
Données initiales
CREATE (:User { id: "123", groups: ["G1", "G2"] })
CREATE (:Group { id: "456", externalId: "G3", labels: ["FunctionalGroup"] })
Exécution de la requête avec
$userId = "123"
$groupId = "456"
Résultat attendu
- La relation 
(:User)-[:IN]->(:Group)est créée. - La liste 
u.groupsest mise à jour de :à["G1", "G2"](sans doublon et en supprimant["G1", "G2", "G3"]G3s'il était déjà présent). 
Récupération des informations d'un groupe
MATCH (g:ProfileGroup|FunctionGroup {id: 68171})
OPTIONAL MATCH (g)-[:DEPENDS]->(s:Structure)
OPTIONAL MATCH (g)-[:DEPENDS]->(c:Class)
OPTIONAL MATCH (g)<-[:IN]-(u:User)
RETURN 
    g.id AS groupId,
    g.name AS groupName,
    g.filter AS groupType,
    labels(g) AS groupLabels,
    s.id AS structureId,
    s.name AS structureName,
    c.id AS classId,
    c.name AS className,
    count(u) AS memberCount
Ajouter manuellement un groupe à un utilisateur
MATCH (u:User { id: $userId }), (f:Group { id: $groupId }) 
WHERE 'ManualGroup' IN labels(f) OR 'FunctionalGroup' IN labels(f) 
MERGE (u)-[:IN { source: 'MANUAL' }]->(f) 
WITH f, u 
WHERE 'FunctionalGroup' IN labels(f) 
SET u.groups = [gId IN coalesce(u.groups, []) WHERE gId <> f.externalId] + f.externalId