Files
unionflow-server-api/unionflow/docs/CHANGEMENTS_UX_MENU_APPLIQUES.md
dahoud e8ad874015 feat: WebSocket temps réel + Finance Workflow + corrections
- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics)
  * Backend: KafkaEventProducer, KafkaEventConsumer
  * Mobile: WebSocketService (reconnection, heartbeat, typed events)
  * DashboardBloc: Auto-refresh depuis WebSocket events

- Finance Workflow: approbations + budgets (backend + mobile)
  * Backend: entities, services, resources, migrations Flyway V6
  * Mobile: features finance_workflow complète avec BLoC

- Corrections DI: interfaces IRepository partout
  * IProfileRepository, IOrganizationRepository, IMembreRepository
  * GetIt configuré avec @injectable

- Spec-Kit: constitution + templates mis à jour
  * .specify/memory/constitution.md enrichie
  * Templates agent, plan, spec, tasks, checklist

- Nettoyage: fichiers temporaires supprimés

Signed-off-by: lions dev Team
2026-03-15 02:12:17 +00:00

12 KiB

Changements UX - Menu et Pages par Rôle (Appliqués)

Date: 2026-03-02 Système: UnionFlow - Révision UX Menu et Accès par Rôle Statut: Phase 1 et Phase 2 APPLIQUÉES


Changements Appliqués

Phase 1 : Menu - Retrait MEMBRE_ACTIF de l'Annuaire

Fichier modifié : MenuBean.java

Méthode : isAnnuaireMembresVisible()

Avant

public boolean isAnnuaireMembresVisible() {
    return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "SECRETAIRE", "TRESORIER",
                     "RESPONSABLE_SOCIAL", "RESPONSABLE_EVENEMENTS", "RESPONSABLE_CREDIT",
                     "MEMBRE_BUREAU", "MEMBRE_ACTIF"); // ← PROBLÈME
}

Après

/**
 * Annuaire des Membres - Consultation de la liste (pas de modification)
 * Visible pour les responsables et bureau SEULEMENT (PAS pour MEMBRE_ACTIF)
 *
 * Raison métier: Un membre simple n'a généralement pas besoin de voir la liste complète
 * des autres membres. Cela peut poser des problèmes de:
 * - RGPD: Exposition non justifiée de données personnelles
 * - Sécurité: Risque de spam/phishing entre membres
 * - UX: Surcharge du menu pour un usage limité
 */
public boolean isAnnuaireMembresVisible() {
    return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "SECRETAIRE", "TRESORIER",
                     "RESPONSABLE_SOCIAL", "RESPONSABLE_EVENEMENTS", "RESPONSABLE_CREDIT",
                     "MEMBRE_BUREAU");
    // MEMBRE_ACTIF retiré intentionnellement pour raisons UX et RGPD
}

Résultat :

  • Menu "Annuaire des Membres" masqué pour les utilisateurs avec rôle MEMBRE_ACTIF
  • Menu visible uniquement pour SECRETAIRE, TRESORIER, RESPONSABLES, ADMIN

Phase 2 : Page Liste Membres - Conditionnement par Rôle

Fichier modifié : /pages/secure/membre/liste.xhtml

1. KPI Statistiques (Lignes 31-64)

Avant : KPI visibles pour TOUS

<h:panelGroup id="panelStatistiques" layout="block" styleClass="grid mb-3">

Après : KPI visibles uniquement pour ADMIN

<h:panelGroup id="panelStatistiques" layout="block" styleClass="grid mb-3"
              rendered="#{menuBean.gestionMembresMenuVisible}">

KPI conditionnés :

  • Total Membres
  • Membres Actifs
  • Membres Inactifs/Suspendus
  • Nouveaux Membres (30j)

2. Actions Header (Lignes 21-24)

Avant : Boutons visibles pour TOUS

Après : Boutons visibles uniquement pour ADMIN

<p:button value="Nouveau Membre" icon="pi pi-user-plus"
          rendered="#{menuBean.gestionMembresMenuVisible}" />
<p:commandButton value="Import / Export" icon="pi pi-file-excel"
                 rendered="#{menuBean.gestionMembresMenuVisible}" />

Actions conditionnées :

  • Nouveau Membre
  • Import / Export

3. Actions Groupées (Lignes 129-143)

Avant : Actions groupées visibles pour TOUS si sélection

<h:panelGroup id="panelActionsGroupees"
              rendered="#{not empty membreListeBean.selectedMembres}">

Après : Actions groupées visibles uniquement pour ADMIN

<h:panelGroup id="panelActionsGroupees"
              rendered="#{not empty membreListeBean.selectedMembres and menuBean.gestionMembresMenuVisible}">

Actions conditionnées :

  • Rappel Cotisations Groupé
  • Message Groupé
  • Exporter Sélection

4. Colonne Sélection (Ligne 166)

Avant : Checkbox visible pour TOUS

<p:column selectionMode="multiple" headerText="" />

Après : Checkbox visible uniquement pour ADMIN

<p:column selectionMode="multiple" headerText=""
          rendered="#{menuBean.gestionMembresMenuVisible}" />

5. Actions DataTable (Lignes 223-258)

Action "Voir Profil" - TOUS
<!-- Voir le profil - TOUS -->
<p:button icon="pi pi-user" outcome="membreProfilPage" title="Profil" />

Pas de condition : Tous les utilisateurs peuvent consulter un profil

Action "Éditer" - ADMIN SEULEMENT
<!-- Éditer - ADMIN SEULEMENT -->
<p:button icon="pi pi-pencil" outcome="membreModifierPage" title="Modifier"
          rendered="#{menuBean.gestionMembresMenuVisible}" />
Action "Contacter" - TOUS
<!-- Contacter - TOUS -->
<p:commandButton icon="pi pi-envelope" title="Contacter" />
Action "Suspendre" - ADMIN SEULEMENT
<!-- Suspendre - ADMIN SEULEMENT (visible si actif) -->
<p:commandButton icon="pi pi-ban" title="Suspendre"
                 rendered="#{menuBean.gestionMembresMenuVisible and membre.statut == 'ACTIF'}" />
Action "Réactiver" - ADMIN SEULEMENT
<!-- Réactiver - ADMIN SEULEMENT (visible si suspendu) -->
<p:commandButton icon="pi pi-replay" title="Réactiver"
                 rendered="#{menuBean.gestionMembresMenuVisible and membre.statut == 'SUSPENDU'}" />

Résultat UX par Rôle

Pour MEMBRE_ACTIF 👤

Menu :

  • "Annuaire des Membres" → MASQUÉ
  • Uniquement les menus personnels (Mes Finances, Événements, Aide Sociale, etc.)

Page /pages/secure/membre/liste.xhtml (si accessible directement par URL) :

  • KPI statistiques → MASQUÉS
  • Bouton "Nouveau Membre" → MASQUÉ
  • Bouton "Import / Export" → MASQUÉ
  • Actions groupées (Rappel, Message, Export) → MASQUÉES
  • Colonne checkbox sélection → MASQUÉE
  • Bouton "Voir Profil" → VISIBLE
  • Bouton "Éditer" → MASQUÉ
  • Bouton "Contacter" → VISIBLE
  • Bouton "Suspendre/Réactiver" → MASQUÉ

Résultat : Page affichée en mode lecture seule (consultation profil + contact uniquement)


Pour SECRETAIRE / ADMIN_ORGANISATION 🔐

Menu :

  • "Annuaire des Membres" → VISIBLE
  • "Gestion des Membres" → VISIBLE
  • Tous les autres menus selon leur rôle

Page /pages/secure/membre/liste.xhtml :

  • TOUS les éléments visibles (KPI, actions, boutons)
  • Mode administration complète

Principe Métier Respecté

Question Fondamentale Adressée

"Pourquoi un membre d'une mutuelle devrait-il voir la liste des membres ou rechercher un membre ?"

Réponse :

  • Un MEMBRE_ACTIF n'a généralement PAS besoin de ces fonctions
  • C'est le rôle du SECRETAIRE ou ADMIN de gérer les membres
  • Évite les problèmes RGPD (exposition données personnelles)
  • Simplifie le menu et améliore l'UX

Arguments Métier

Critère MEMBRE_ACTIF SECRETAIRE/ADMIN
Voir liste complète Non pertinent Nécessaire
Statistiques membres Non pertinent Nécessaire
Créer/Modifier membres Non autorisé Nécessaire
Actions groupées Non autorisé Nécessaire
Voir profil individuel Pertinent (lien social) Pertinent
Contacter un membre Pertinent (communication) Pertinent

Travaux Restants

Phase 3 : Configuration Optionnelle (À implémenter)

Si une organisation souhaite activer l'annuaire pour les MEMBRE_ACTIF :

  1. Créer table configuration_organisation
CREATE TABLE configuration_organisation (
    id UUID PRIMARY KEY,
    organisation_id UUID REFERENCES organisation(id),
    annuaire_membres_actif BOOLEAN DEFAULT FALSE,
    annuaire_membres_champs_visibles TEXT[], -- ["nom", "prenom", "telephone"]
    annuaire_membres_recherche_avancee BOOLEAN DEFAULT FALSE
);
  1. Créer ConfigurationService
@ApplicationScoped
public class ConfigurationService {
    public boolean isAnnuaireMembresActive() {
        // Lire depuis configuration_organisation
        return config != null && config.isAnnuaireMembresActif();
    }
}
  1. Modifier MenuBean.isAnnuaireMembresVisible()
public boolean isAnnuaireMembresVisible() {
    // Toujours visible pour admins
    if (hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", ...)) {
        return true;
    }
    // Pour MEMBRE_ACTIF: vérifier config
    if (hasAnyRole("MEMBRE_ACTIF")) {
        return configService.isAnnuaireMembresActive(); // false par défaut
    }
    return false;
}
  1. Créer page /pages/secure/membre/annuaire.xhtml (version simplifiée)
  • Pas de KPI
  • Pas d'actions administratives
  • Filtres limités (nom/prénom seulement)
  • Champs limités (pas d'email, pas d'adresse)

Phase 4 : Révision Complète Menu (À implémenter)

Créer des menus séparés par rôle :

  • menu-membre-actif.xhtml (~10 items)
  • menu-secretaire.xhtml (~20 items)
  • menu-tresorier.xhtml (~15 items)
  • menu-admin.xhtml (~50+ items)

Charger dynamiquement dans main-template.xhtml :

<c:choose>
    <c:when test="#{menuBean.membreActif and not menuBean.anyAdminRole}">
        <ui:include src="/templates/components/layout/menu-membre-actif.xhtml" />
    </c:when>
    <c:when test="#{menuBean.secretaire or menuBean.adminOrganisation}">
        <ui:include src="/templates/components/layout/menu-admin.xhtml" />
    </c:when>
    <c:otherwise>
        <ui:include src="/templates/components/layout/menu.xhtml" />
    </c:otherwise>
</c:choose>

Checklist de Validation

  • Phase 1 : Menu "Annuaire des Membres" masqué pour MEMBRE_ACTIF
  • Phase 2 : Page liste.xhtml conditionnée selon le rôle
    • KPI statistiques masqués pour MEMBRE_ACTIF
    • Actions header masquées pour MEMBRE_ACTIF
    • Actions groupées masquées pour MEMBRE_ACTIF
    • Colonne checkbox masquée pour MEMBRE_ACTIF
    • Actions DataTable conditionnées (Éditer, Suspendre, Réactiver)
  • Phase 3 : Configuration optionnelle par organisation
  • Phase 4 : Menus séparés par rôle

Tests à Effectuer

Test 1 : Utilisateur MEMBRE_ACTIF

  1. Se connecter avec un compte MEMBRE_ACTIF (sans autre rôle)
  2. Vérifier menu :
    • "Annuaire des Membres" n'apparaît PAS
    • "Gestion des Membres" n'apparaît PAS
    • Menus personnels visibles (Mes Finances, Événements, etc.)
  3. Accéder directement à /pages/secure/membre/liste.xhtml (via URL)
  4. Vérifier page :
    • Pas de KPI statistiques en haut
    • Pas de bouton "Nouveau Membre"
    • Pas de bouton "Import / Export"
    • Pas de checkbox de sélection
    • Pas d'actions groupées
    • Bouton "Voir Profil" visible
    • Bouton "Éditer" PAS visible
    • Bouton "Contacter" visible
    • Bouton "Suspendre/Réactiver" PAS visible

Test 2 : Utilisateur SECRETAIRE

  1. Se connecter avec un compte SECRETAIRE
  2. Vérifier menu :
    • "Annuaire des Membres" visible
    • "Gestion des Membres" visible
  3. Accéder à /pages/secure/membre/liste.xhtml
  4. Vérifier page :
    • KPI statistiques visibles
    • Bouton "Nouveau Membre" visible
    • Bouton "Import / Export" visible
    • Checkbox de sélection visible
    • Actions groupées visibles (si sélection)
    • Toutes les actions DataTable visibles

Test 3 : Utilisateur ADMIN_ORGANISATION

  1. Se connecter avec un compte ADMIN_ORGANISATION
  2. Vérifier :
    • Tous les éléments visibles (comme SECRETAIRE)
    • Pas de restrictions

Impact RGPD

Avant :

  • Tous les membres voyaient la liste complète (nom, email, téléphone, adresse potentiellement)
  • Exposition non justifiée de données personnelles

Après :

  • Seuls les responsables autorisés voient la liste complète
  • Conforme au principe de minimisation (RGPD Art. 5.1.c)
  • Conforme au principe de limitation des finalités (RGPD Art. 5.1.b)

Contact

Documentation :

  • docs/CHANGEMENTS_UX_MENU_APPLIQUES.md (ce fichier)
  • docs/UX_MENU_PAR_ROLE.md (recommandations complètes)
  • docs/KPI_DASHBOARD_PAR_ROLE.md (matrice KPI)

Code modifié :

  • MenuBean.java (ligne 135)
  • /pages/secure/membre/liste.xhtml (lignes 32, 21-24, 130, 166, 234, 246, 255)