Skip to main content

Groupe

Les différents groupes

Il existe 6 types de groupes :

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).

Relations entre les groupes et une structure

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 :

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):

Groupe par discipline

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 ($userId et $groupId).
WHERE 'ManualGroup' IN labels(f) OR 'FunctionalGroup' IN labels(f) 
  • Filtre uniquement certains types de groupes :
    • Soit un ManualGroup
    • Soit un FunctionalGroup
MERGE (u)-[:IN { source: 'MANUAL' }]->(f) 
  • Crée (ou assure l'existence) d'une relation IN entre l'utilisateur u et le groupe f.
  • 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 f est un FunctionalGroup.
  • 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é groups de l'utilisateur u en :
    1. Filtrant les anciens groupes (u.groups) pour supprimer l'ID externe (externalId) de f s'il est déjà présent.
    2. Ajoutant f.externalId à la liste des 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 groups sur l'utilisateur, qui stocke les externalId des groupes de type FunctionalGroup uniquement.

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.groups est mise à jour de :
    ["G1", "G2"]
    à
    ["G1", "G2", "G3"]
    (sans doublon et en supprimant G3 s'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