From cdcdb374591d3bcaa2640f98486a66159a74a1dd Mon Sep 17 00:00:00 2001 From: dahoud <41957584+DahoudG@users.noreply.github.com> Date: Sat, 25 Apr 2026 14:34:11 +0000 Subject: [PATCH] refactor(sprint-12 web 2026-04-25): centralisation navigation outcomes via ViewPaths constants + ViewPathsBean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRY strict appliqué pour la maintenance — outcomes de navigation centralisés en un lieu unique au lieu de paths hardcodés disséminés dans 13+ fichiers. Architecture - constants.ViewPaths : classe finale + ~80 constantes public static final String, organisées par module (Dashboard, Membres, Adhésions, Cotisations, Finance, Crédit, Évènements, Aide, Communication, Documents, Organisation, Conformité, Admin, Rapports, Souscription, Super-Admin) - view.ViewPathsBean (@Named "paths" @ApplicationScoped) : expose les constantes en EL aux XHTML Migration menu.xhtml (65 edits, 0 path orphelin) - outcome="/pages/secure/dashboard" → outcome="#{paths.dashboard}" - outcome="/pages/secure/conformite/dashboard" → outcome="#{paths.conformiteDashboard}" - ... 60+ autres mappings Migration autres XHTML (13 edits, 12 fichiers) - index, error/viewExpired, topbar, admin × 4, evenement × 2, organisation × 2, reports Migration beans Java (4 fichiers, 18 returns) - NavigationBean : goToProfile, goToSettings (super-admin / admin / membre), getDashboardUrlForUserType - DashboardMembreBean : 5 méthodes navigation (cotisations, événement, aide, profil) - MembreDashboardBean : voirEvenement, payerCotisations - OrganisationsBean : retour vers liste Test cohérence (3 tests, 100%) - chaquePathExisteCommeFichier : reflectif sur ViewPaths, vérifie xhtml en classpath - redirectSuffixFormat : structure REDIRECT_SUFFIX - aucuneConstanteVide : non-null, non-blank Dette détectée (3 pages référencées mais inexistantes — flaggées KNOWN_MISSING_PAGES) - /pages/secure/evenement/bilan-detail.xhtml - /pages/admin/parametres.xhtml - /pages/membre/parametres.xhtml Bénéfices - 1 seul lieu pour renommer/déplacer une page - Type-safety compile-time côté Java - Tests détectent automatiquement les paths orphelins - IDE complétion sur les getters paths.xxx --- .../unionflow/client/constants/ViewPaths.java | 143 ++++++++++++++++ .../client/view/DashboardMembreBean.java | 11 +- .../client/view/MembreDashboardBean.java | 5 +- .../unionflow/client/view/NavigationBean.java | 21 ++- .../client/view/OrganisationsBean.java | 3 +- .../unionflow/client/view/ViewPathsBean.java | 138 ++++++++++++++++ .../resources/error/viewExpired.xhtml | 4 +- .../resources/META-INF/resources/index.xhtml | 2 +- .../resources/pages/admin/audit.xhtml | 2 +- .../resources/pages/admin/backup.xhtml | 2 +- .../resources/pages/admin/settings.xhtml | 2 +- .../resources/pages/admin/users.xhtml | 2 +- .../pages/secure/evenement/bilan.xhtml | 2 +- .../pages/secure/evenement/calendrier.xhtml | 2 +- .../pages/secure/organisation/detail.xhtml | 2 +- .../pages/secure/organisation/liste.xhtml | 2 +- .../resources/pages/secure/reports.xhtml | 2 +- .../templates/components/layout/menu.xhtml | 154 +++++++++--------- .../templates/components/layout/topbar.xhtml | 2 +- .../constants/ViewPathsConsistencyTest.java | 85 ++++++++++ 20 files changed, 477 insertions(+), 109 deletions(-) create mode 100644 src/main/java/dev/lions/unionflow/client/constants/ViewPaths.java create mode 100644 src/main/java/dev/lions/unionflow/client/view/ViewPathsBean.java create mode 100644 src/test/java/dev/lions/unionflow/client/constants/ViewPathsConsistencyTest.java diff --git a/src/main/java/dev/lions/unionflow/client/constants/ViewPaths.java b/src/main/java/dev/lions/unionflow/client/constants/ViewPaths.java new file mode 100644 index 0000000..ebf272a --- /dev/null +++ b/src/main/java/dev/lions/unionflow/client/constants/ViewPaths.java @@ -0,0 +1,143 @@ +package dev.lions.unionflow.client.constants; + +/** + * Centralisation des chemins de vues JSF. + * + *
Lieu unique pour tous les outcomes de navigation. À utiliser depuis : + *
Convention de nommage : {@code MODULE_PAGE} en MAJ avec underscore + * (ex: {@code COTISATION_PAIEMENT}, {@code SUPER_ADMIN_DASHBOARD}). + * + * @since 2026-04-25 (Sprint 12 — centralisation navigation DRY) + */ +public final class ViewPaths { + + private ViewPaths() { + // Classe utilitaire non instantiable + } + + // ─── Suffixes ──────────────────────────────────────────────────────────── + public static final String REDIRECT_SUFFIX = "?faces-redirect=true"; + + // ─── Index / racine / erreur ───────────────────────────────────────────── + public static final String ROOT = "/"; + public static final String INDEX = "/index"; + + // ─── Dashboard ─────────────────────────────────────────────────────────── + public static final String DASHBOARD = "/pages/secure/dashboard"; + public static final String DASHBOARD_MEMBRE = "/pages/secure/dashboard-membre"; + + // ─── Profil personnel ──────────────────────────────────────────────────── + public static final String PROFILE = "/pages/secure/profile"; + public static final String PERSONNEL_PROFIL = "/pages/secure/personnel/profil"; + public static final String PERSONNEL_PARAMETRES = "/pages/secure/personnel/parametres"; + public static final String PERSONNEL_PREFERENCES = "/pages/secure/personnel/preferences"; + public static final String PERSONNEL_NOTIFICATIONS = "/pages/secure/personnel/notifications"; + + // ─── Membres ───────────────────────────────────────────────────────────── + public static final String MEMBRE_LISTE = "/pages/secure/membre/liste"; + public static final String MEMBRE_INSCRIPTION = "/pages/secure/membre/inscription"; + public static final String MEMBRE_VALIDATION = "/pages/secure/membre/validation"; + public static final String MEMBRE_IMPORT = "/pages/secure/membre/import"; + public static final String MEMBRE_EXPORT = "/pages/secure/membre/export"; + public static final String MEMBRE_RECHERCHE = "/pages/secure/membre/recherche"; + public static final String MEMBRE_COTISATIONS = "/pages/secure/membre/cotisations"; + public static final String MEMBRE_PROFIL = "/pages/secure/membre/profil"; + public static final String MEMBRE_PAIEMENT_COTISATIONS = "/pages/secure/membre/paiement-mes-cotisations"; + + // ─── Adhésions ─────────────────────────────────────────────────────────── + public static final String ADHESION_LISTE = "/pages/secure/adhesion/liste"; + public static final String ADHESION_DEMANDE = "/pages/secure/adhesion/demande"; + public static final String ADHESION_VALIDATION = "/pages/secure/adhesion/validation"; + public static final String ADHESION_HISTORIQUE = "/pages/secure/adhesion/historique"; + public static final String ADHESION_RENOUVELLEMENT = "/pages/secure/adhesion/renouvellement"; + + // ─── Cotisations ───────────────────────────────────────────────────────── + public static final String COTISATIONS_GESTION_ADMIN = "/pages/admin/cotisations/gestion"; + public static final String COTISATION_PAIEMENT = "/pages/secure/cotisation/paiement"; + public static final String COTISATION_HISTORIQUE = "/pages/secure/cotisation/historique"; + public static final String COTISATION_RELANCES = "/pages/secure/cotisation/relances"; + + // ─── Finance ───────────────────────────────────────────────────────────── + public static final String FINANCE_TRESORERIE = "/pages/secure/finance/tresorerie"; + public static final String FINANCE_BUDGETS = "/pages/secure/finance/budgets"; + public static final String FINANCE_BILANS = "/pages/secure/finance/bilans"; + public static final String FINANCE_APPROBATIONS = "/pages/secure/finance/approbations"; + public static final String COMPTABILITE_GESTION = "/pages/secure/comptabilite/gestion"; + + // ─── Épargne / Crédit ──────────────────────────────────────────────────── + public static final String EPARGNE_COMPTES = "/pages/secure/epargne/comptes"; + public static final String CREDIT_DEMANDES = "/pages/secure/credit/demandes"; + public static final String CREDIT_EVALUATION = "/pages/secure/credit/evaluation"; + public static final String CREDIT_SUIVI = "/pages/secure/credit/suivi"; + public static final String CREDIT_REMBOURSEMENTS = "/pages/secure/credit/remboursements"; + public static final String CREDIT_STATISTIQUES = "/pages/secure/credit/statistiques"; + + // ─── Événements ────────────────────────────────────────────────────────── + public static final String EVENEMENT_GESTION = "/pages/secure/evenement/gestion"; + public static final String EVENEMENT_CREATION = "/pages/secure/evenement/creation"; + public static final String EVENEMENT_CALENDRIER = "/pages/secure/evenement/calendrier"; + public static final String EVENEMENT_PARTICIPANTS = "/pages/secure/evenement/participants"; + public static final String EVENEMENT_PLANIFICATION = "/pages/secure/evenement/planification"; + public static final String EVENEMENT_LOGISTIQUE = "/pages/secure/evenement/logistique"; + public static final String EVENEMENT_BILAN = "/pages/secure/evenement/bilan"; + public static final String EVENEMENT_BILAN_DETAIL = "/pages/secure/evenement/bilan-detail"; + + // ─── Aide / support ────────────────────────────────────────────────────── + public static final String AIDE_DEMANDE = "/pages/secure/aide/demande"; + public static final String AIDE_REQUESTS = "/pages/secure/aide/requests"; + public static final String AIDE_APPROVED = "/pages/secure/aide/approved"; + public static final String AIDE_TRAITEMENT = "/pages/secure/aide/traitement"; + public static final String AIDE_HISTORIQUE = "/pages/secure/aide/historique"; + public static final String AIDE_STATISTIQUES = "/pages/secure/aide/statistiques"; + public static final String AIDE_FAQ = "/pages/secure/aide/faq"; + public static final String AIDE_SUPPORT = "/pages/secure/aide/support"; + public static final String AIDE_APROPOS = "/pages/secure/aide/apropos"; + + // ─── Communication / Documents ─────────────────────────────────────────── + public static final String COMMUNICATION_CONVERSATIONS = "/pages/secure/communication/conversations"; + public static final String COMMUNICATION_NOTIFICATIONS = "/pages/secure/communication/notifications"; + public static final String DOCUMENTS_MES_DOCUMENTS = "/pages/secure/documents/mes-documents"; + + // ─── Organisation ──────────────────────────────────────────────────────── + public static final String ORGANISATION_LISTE = "/pages/secure/organisation/liste"; + public static final String ORGANISATION_DETAIL = "/pages/secure/organisation/detail"; + public static final String ORGANISATION_NOUVELLE = "/pages/secure/organisation/nouvelle"; + public static final String ORGANISATION_STATISTIQUES = "/pages/secure/organisation/statistiques"; + + // ─── Conformité (Sprints 8, 11) ────────────────────────────────────────── + public static final String CONFORMITE_DASHBOARD = "/pages/secure/conformite/dashboard"; + public static final String CONFORMITE_RAPPORTS_TRIMESTRIELS = "/pages/secure/conformite/rapports-trimestriels"; + public static final String CONFORMITE_BENEFICIAIRES_EFFECTIFS = "/pages/secure/conformite/beneficiaires-effectifs"; + public static final String CONFORMITE_AUDIT_TRAIL = "/pages/secure/conformite/audit-trail"; + + // ─── Admin technique ───────────────────────────────────────────────────── + public static final String ADMIN_PISPI_READINESS = "/pages/secure/admin/pispi-readiness"; + public static final String ADMIN_ROLE_DELEGATIONS = "/pages/secure/admin/role-delegations"; + public static final String ADMIN_SAUVEGARDE = "/pages/secure/admin/sauvegarde"; + public static final String ADMIN_AUDIT_JOURNAL = "/pages/admin/audit/journal"; + public static final String ADMIN_LOGS_SYSTEME = "/pages/admin/logs/systeme"; + public static final String ADMIN_PARAMETRES = "/pages/admin/parametres"; + public static final String MEMBRE_PARAMETRES = "/pages/membre/parametres"; + + // ─── Rapports ──────────────────────────────────────────────────────────── + public static final String RAPPORT_FINANCES = "/pages/secure/rapport/finances"; + public static final String RAPPORT_MEMBRES = "/pages/secure/rapport/membres"; + public static final String RAPPORT_ACTIVITES = "/pages/secure/rapport/activites"; + public static final String RAPPORT_TABLEAUX_BORD = "/pages/secure/rapport/tableaux-bord"; + public static final String RAPPORT_EXPORT = "/pages/secure/rapport/export"; + + // ─── Souscription ──────────────────────────────────────────────────────── + public static final String SOUSCRIPTION_DASHBOARD = "/pages/secure/souscription/dashboard"; + + // ─── Super-Admin ───────────────────────────────────────────────────────── + public static final String SUPER_ADMIN_DASHBOARD = "/pages/super-admin/dashboard"; + public static final String SUPER_ADMIN_ROLES_GESTION = "/pages/super-admin/roles/gestion"; + public static final String SUPER_ADMIN_TYPES_ORGANISATIONS = "/pages/super-admin/types/organisations"; + public static final String SUPER_ADMIN_CONFIGURATION_SYSTEME = "/pages/super-admin/configuration/systeme"; +} diff --git a/src/main/java/dev/lions/unionflow/client/view/DashboardMembreBean.java b/src/main/java/dev/lions/unionflow/client/view/DashboardMembreBean.java index e702adf..1f7fb8b 100644 --- a/src/main/java/dev/lions/unionflow/client/view/DashboardMembreBean.java +++ b/src/main/java/dev/lions/unionflow/client/view/DashboardMembreBean.java @@ -1,5 +1,6 @@ package dev.lions.unionflow.client.view; +import dev.lions.unionflow.client.constants.ViewPaths; import dev.lions.unionflow.server.api.dto.cotisation.response.CotisationResponse; import dev.lions.unionflow.client.api.dto.MembreDashboardResponse; import dev.lions.unionflow.client.service.CotisationService; @@ -175,23 +176,23 @@ public class DashboardMembreBean implements Serializable { // ═══════════════════════════════════════════════════════════════════════ public String allerAuxCotisations() { - return "/pages/secure/membre/paiement-mes-cotisations.xhtml?faces-redirect=true"; + return ViewPaths.MEMBRE_PAIEMENT_COTISATIONS + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } public String inscrireEvenement() { - return "/pages/secure/evenement/calendrier.xhtml?faces-redirect=true"; + return ViewPaths.EVENEMENT_CALENDRIER + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } public String demanderAide() { - return "/pages/secure/aide/demande.xhtml?faces-redirect=true"; + return ViewPaths.AIDE_DEMANDE + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } public String allerAMonProfil() { - return "/pages/secure/membre/profil.xhtml?faces-redirect=true"; + return ViewPaths.MEMBRE_PROFIL + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } public String allerAuxEvenements() { - return "/pages/secure/evenement/calendrier.xhtml?faces-redirect=true"; + return ViewPaths.EVENEMENT_CALENDRIER + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } // ═══════════════════════════════════════════════════════════════════════ diff --git a/src/main/java/dev/lions/unionflow/client/view/MembreDashboardBean.java b/src/main/java/dev/lions/unionflow/client/view/MembreDashboardBean.java index b69eb4b..aff32b9 100644 --- a/src/main/java/dev/lions/unionflow/client/view/MembreDashboardBean.java +++ b/src/main/java/dev/lions/unionflow/client/view/MembreDashboardBean.java @@ -1,5 +1,6 @@ package dev.lions.unionflow.client.view; +import dev.lions.unionflow.client.constants.ViewPaths; import dev.lions.unionflow.server.api.dto.membre.response.MembreResponse; import dev.lions.unionflow.server.api.dto.cotisation.response.CotisationResponse; import dev.lions.unionflow.server.api.dto.evenement.response.EvenementResponse; @@ -363,7 +364,7 @@ public class MembreDashboardBean implements Serializable { } public String voirEvenement(Evenement evenement) { - return "/pages/secure/evenement/gestion.xhtml?faces-redirect=true"; + return ViewPaths.EVENEMENT_GESTION + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } public void annulerInscription(Evenement evenement) { @@ -373,7 +374,7 @@ public class MembreDashboardBean implements Serializable { } public String payerCotisations() { - return "/pages/secure/cotisation/paiement.xhtml?faces-redirect=true"; + return ViewPaths.COTISATION_PAIEMENT + ".xhtml" + ViewPaths.REDIRECT_SUFFIX; } public void actualiser() { diff --git a/src/main/java/dev/lions/unionflow/client/view/NavigationBean.java b/src/main/java/dev/lions/unionflow/client/view/NavigationBean.java index d89487d..1e95d25 100644 --- a/src/main/java/dev/lions/unionflow/client/view/NavigationBean.java +++ b/src/main/java/dev/lions/unionflow/client/view/NavigationBean.java @@ -1,5 +1,6 @@ package dev.lions.unionflow.client.view; +import dev.lions.unionflow.client.constants.ViewPaths; import jakarta.enterprise.context.RequestScoped; import jakarta.faces.context.FacesContext; import jakarta.inject.Inject; @@ -62,7 +63,7 @@ public class NavigationBean implements Serializable { return redirectToLogin(); } - return "/pages/secure/profile?faces-redirect=true"; + return ViewPaths.PROFILE + ViewPaths.REDIRECT_SUFFIX; } public String goToSettings() { @@ -71,11 +72,11 @@ public class NavigationBean implements Serializable { } if (userSession.isSuperAdmin()) { - return "/pages/super-admin/configuration/systeme?faces-redirect=true"; + return ViewPaths.SUPER_ADMIN_CONFIGURATION_SYSTEME + ViewPaths.REDIRECT_SUFFIX; } else if (userSession.isAdmin()) { - return "/pages/admin/parametres?faces-redirect=true"; + return ViewPaths.ADMIN_PARAMETRES + ViewPaths.REDIRECT_SUFFIX; } else { - return "/pages/membre/parametres?faces-redirect=true"; + return ViewPaths.MEMBRE_PARAMETRES + ViewPaths.REDIRECT_SUFFIX; } } @@ -87,23 +88,21 @@ public class NavigationBean implements Serializable { private String getDashboardUrlForUserType() { if (userSession == null || userSession.getTypeCompte() == null) { - return "/pages/secure/dashboard.xhtml"; + return ViewPaths.DASHBOARD + ".xhtml"; } switch (userSession.getTypeCompte()) { case "SUPER_ADMIN": - return "/pages/super-admin/dashboard.xhtml"; + return ViewPaths.SUPER_ADMIN_DASHBOARD + ".xhtml"; case "ADMIN_ORGANISATION": - return "/pages/secure/dashboard.xhtml"; case "MODERATEUR": - return "/pages/secure/dashboard.xhtml"; + return ViewPaths.DASHBOARD + ".xhtml"; case "MEMBRE_ACTIF": - return "/pages/secure/dashboard-membre.xhtml"; case "MEMBRE": - return "/pages/secure/dashboard-membre.xhtml"; + return ViewPaths.DASHBOARD_MEMBRE + ".xhtml"; default: LOGGER.warning("Type de compte non reconnu: " + userSession.getTypeCompte()); - return "/pages/secure/dashboard.xhtml"; + return ViewPaths.DASHBOARD + ".xhtml"; } } diff --git a/src/main/java/dev/lions/unionflow/client/view/OrganisationsBean.java b/src/main/java/dev/lions/unionflow/client/view/OrganisationsBean.java index 9f09f3c..ff16d07 100644 --- a/src/main/java/dev/lions/unionflow/client/view/OrganisationsBean.java +++ b/src/main/java/dev/lions/unionflow/client/view/OrganisationsBean.java @@ -1,6 +1,7 @@ package dev.lions.unionflow.client.view; import dev.lions.unionflow.client.constants.StatutOrganisationConstants; +import dev.lions.unionflow.client.constants.ViewPaths; import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationResponse; import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationSummaryResponse; import dev.lions.unionflow.server.api.dto.common.PagedResponse; @@ -245,7 +246,7 @@ public class OrganisationsBean implements Serializable { chargerOrganisations(); chargerStatistiques(); - return "/pages/secure/organisation/liste?faces-redirect=true"; + return ViewPaths.ORGANISATION_LISTE + ViewPaths.REDIRECT_SUFFIX; } catch (RestClientExceptionMapper.ConflictException e) { errorHandler.handleException(e, "lors de la création d'une organisation", diff --git a/src/main/java/dev/lions/unionflow/client/view/ViewPathsBean.java b/src/main/java/dev/lions/unionflow/client/view/ViewPathsBean.java new file mode 100644 index 0000000..5b49a3f --- /dev/null +++ b/src/main/java/dev/lions/unionflow/client/view/ViewPathsBean.java @@ -0,0 +1,138 @@ +package dev.lions.unionflow.client.view; + +import dev.lions.unionflow.client.constants.ViewPaths; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Named; +import java.io.Serializable; + +/** + * Bean exposant {@link ViewPaths} aux pages JSF via expressions EL. + * + *
Usage XHTML : {@code outcome="#{paths.uboList}"}. + * + *
Le bean est {@code @ApplicationScoped} car les chemins sont immuables et identiques pour
+ * tous les utilisateurs — un seul instance suffit.
+ *
+ * @since 2026-04-25 (Sprint 12)
+ */
+@Named("paths")
+@ApplicationScoped
+public class ViewPathsBean implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ // ─── Index / Dashboard ───────────────────────────────────────────────────
+ public String getRoot() { return ViewPaths.ROOT; }
+ public String getIndex() { return ViewPaths.INDEX; }
+ public String getDashboard() { return ViewPaths.DASHBOARD; }
+ public String getDashboardMembre() { return ViewPaths.DASHBOARD_MEMBRE; }
+
+ // ─── Profil personnel ────────────────────────────────────────────────────
+ public String getProfile() { return ViewPaths.PROFILE; }
+ public String getPersonnelProfil() { return ViewPaths.PERSONNEL_PROFIL; }
+ public String getPersonnelParametres() { return ViewPaths.PERSONNEL_PARAMETRES; }
+ public String getPersonnelPreferences() { return ViewPaths.PERSONNEL_PREFERENCES; }
+ public String getPersonnelNotifications() { return ViewPaths.PERSONNEL_NOTIFICATIONS; }
+
+ // ─── Membres ─────────────────────────────────────────────────────────────
+ public String getMembreListe() { return ViewPaths.MEMBRE_LISTE; }
+ public String getMembreInscription() { return ViewPaths.MEMBRE_INSCRIPTION; }
+ public String getMembreValidation() { return ViewPaths.MEMBRE_VALIDATION; }
+ public String getMembreImport() { return ViewPaths.MEMBRE_IMPORT; }
+ public String getMembreExport() { return ViewPaths.MEMBRE_EXPORT; }
+ public String getMembreRecherche() { return ViewPaths.MEMBRE_RECHERCHE; }
+ public String getMembreCotisations() { return ViewPaths.MEMBRE_COTISATIONS; }
+ public String getMembreProfil() { return ViewPaths.MEMBRE_PROFIL; }
+ public String getMembrePaiementCotisations() { return ViewPaths.MEMBRE_PAIEMENT_COTISATIONS; }
+
+ // ─── Adhésions ───────────────────────────────────────────────────────────
+ public String getAdhesionListe() { return ViewPaths.ADHESION_LISTE; }
+ public String getAdhesionDemande() { return ViewPaths.ADHESION_DEMANDE; }
+ public String getAdhesionValidation() { return ViewPaths.ADHESION_VALIDATION; }
+ public String getAdhesionHistorique() { return ViewPaths.ADHESION_HISTORIQUE; }
+ public String getAdhesionRenouvellement() { return ViewPaths.ADHESION_RENOUVELLEMENT; }
+
+ // ─── Cotisations ─────────────────────────────────────────────────────────
+ public String getCotisationsGestionAdmin() { return ViewPaths.COTISATIONS_GESTION_ADMIN; }
+ public String getCotisationPaiement() { return ViewPaths.COTISATION_PAIEMENT; }
+ public String getCotisationHistorique() { return ViewPaths.COTISATION_HISTORIQUE; }
+ public String getCotisationRelances() { return ViewPaths.COTISATION_RELANCES; }
+
+ // ─── Finance ─────────────────────────────────────────────────────────────
+ public String getFinanceTresorerie() { return ViewPaths.FINANCE_TRESORERIE; }
+ public String getFinanceBudgets() { return ViewPaths.FINANCE_BUDGETS; }
+ public String getFinanceBilans() { return ViewPaths.FINANCE_BILANS; }
+ public String getFinanceApprobations() { return ViewPaths.FINANCE_APPROBATIONS; }
+ public String getComptabiliteGestion() { return ViewPaths.COMPTABILITE_GESTION; }
+
+ // ─── Épargne / Crédit ────────────────────────────────────────────────────
+ public String getEpargneComptes() { return ViewPaths.EPARGNE_COMPTES; }
+ public String getCreditDemandes() { return ViewPaths.CREDIT_DEMANDES; }
+ public String getCreditEvaluation() { return ViewPaths.CREDIT_EVALUATION; }
+ public String getCreditSuivi() { return ViewPaths.CREDIT_SUIVI; }
+ public String getCreditRemboursements() { return ViewPaths.CREDIT_REMBOURSEMENTS; }
+ public String getCreditStatistiques() { return ViewPaths.CREDIT_STATISTIQUES; }
+
+ // ─── Événements ──────────────────────────────────────────────────────────
+ public String getEvenementGestion() { return ViewPaths.EVENEMENT_GESTION; }
+ public String getEvenementCreation() { return ViewPaths.EVENEMENT_CREATION; }
+ public String getEvenementCalendrier() { return ViewPaths.EVENEMENT_CALENDRIER; }
+ public String getEvenementParticipants() { return ViewPaths.EVENEMENT_PARTICIPANTS; }
+ public String getEvenementPlanification() { return ViewPaths.EVENEMENT_PLANIFICATION; }
+ public String getEvenementLogistique() { return ViewPaths.EVENEMENT_LOGISTIQUE; }
+ public String getEvenementBilan() { return ViewPaths.EVENEMENT_BILAN; }
+ public String getEvenementBilanDetail() { return ViewPaths.EVENEMENT_BILAN_DETAIL; }
+
+ // ─── Aide / Support ──────────────────────────────────────────────────────
+ public String getAideDemande() { return ViewPaths.AIDE_DEMANDE; }
+ public String getAideRequests() { return ViewPaths.AIDE_REQUESTS; }
+ public String getAideApproved() { return ViewPaths.AIDE_APPROVED; }
+ public String getAideTraitement() { return ViewPaths.AIDE_TRAITEMENT; }
+ public String getAideHistorique() { return ViewPaths.AIDE_HISTORIQUE; }
+ public String getAideStatistiques() { return ViewPaths.AIDE_STATISTIQUES; }
+ public String getAideFaq() { return ViewPaths.AIDE_FAQ; }
+ public String getAideSupport() { return ViewPaths.AIDE_SUPPORT; }
+ public String getAideApropos() { return ViewPaths.AIDE_APROPOS; }
+
+ // ─── Communication / Documents ───────────────────────────────────────────
+ public String getCommunicationConversations() { return ViewPaths.COMMUNICATION_CONVERSATIONS; }
+ public String getCommunicationNotifications() { return ViewPaths.COMMUNICATION_NOTIFICATIONS; }
+ public String getDocumentsMesDocuments() { return ViewPaths.DOCUMENTS_MES_DOCUMENTS; }
+
+ // ─── Organisation ────────────────────────────────────────────────────────
+ public String getOrganisationListe() { return ViewPaths.ORGANISATION_LISTE; }
+ public String getOrganisationDetail() { return ViewPaths.ORGANISATION_DETAIL; }
+ public String getOrganisationNouvelle() { return ViewPaths.ORGANISATION_NOUVELLE; }
+ public String getOrganisationStatistiques() { return ViewPaths.ORGANISATION_STATISTIQUES; }
+
+ // ─── Conformité (Sprints 8, 11) ──────────────────────────────────────────
+ public String getConformiteDashboard() { return ViewPaths.CONFORMITE_DASHBOARD; }
+ public String getConformiteRapportsTrimestriels() { return ViewPaths.CONFORMITE_RAPPORTS_TRIMESTRIELS; }
+ public String getConformiteBeneficiairesEffectifs() { return ViewPaths.CONFORMITE_BENEFICIAIRES_EFFECTIFS; }
+ public String getConformiteAuditTrail() { return ViewPaths.CONFORMITE_AUDIT_TRAIL; }
+
+ // ─── Admin technique ─────────────────────────────────────────────────────
+ public String getAdminPispiReadiness() { return ViewPaths.ADMIN_PISPI_READINESS; }
+ public String getAdminRoleDelegations() { return ViewPaths.ADMIN_ROLE_DELEGATIONS; }
+ public String getAdminSauvegarde() { return ViewPaths.ADMIN_SAUVEGARDE; }
+ public String getAdminAuditJournal() { return ViewPaths.ADMIN_AUDIT_JOURNAL; }
+ public String getAdminLogsSysteme() { return ViewPaths.ADMIN_LOGS_SYSTEME; }
+ public String getAdminParametres() { return ViewPaths.ADMIN_PARAMETRES; }
+ public String getMembreParametres() { return ViewPaths.MEMBRE_PARAMETRES; }
+
+ // ─── Rapports ────────────────────────────────────────────────────────────
+ public String getRapportFinances() { return ViewPaths.RAPPORT_FINANCES; }
+ public String getRapportMembres() { return ViewPaths.RAPPORT_MEMBRES; }
+ public String getRapportActivites() { return ViewPaths.RAPPORT_ACTIVITES; }
+ public String getRapportTableauxBord() { return ViewPaths.RAPPORT_TABLEAUX_BORD; }
+ public String getRapportExport() { return ViewPaths.RAPPORT_EXPORT; }
+
+ // ─── Souscription ────────────────────────────────────────────────────────
+ public String getSouscriptionDashboard() { return ViewPaths.SOUSCRIPTION_DASHBOARD; }
+
+ // ─── Super-Admin ─────────────────────────────────────────────────────────
+ public String getSuperAdminDashboard() { return ViewPaths.SUPER_ADMIN_DASHBOARD; }
+ public String getSuperAdminRolesGestion() { return ViewPaths.SUPER_ADMIN_ROLES_GESTION; }
+ public String getSuperAdminTypesOrganisations() { return ViewPaths.SUPER_ADMIN_TYPES_ORGANISATIONS; }
+ public String getSuperAdminConfigurationSysteme() { return ViewPaths.SUPER_ADMIN_CONFIGURATION_SYSTEME; }
+}
diff --git a/src/main/resources/META-INF/resources/error/viewExpired.xhtml b/src/main/resources/META-INF/resources/error/viewExpired.xhtml
index 99638d7..01a5077 100644
--- a/src/main/resources/META-INF/resources/error/viewExpired.xhtml
+++ b/src/main/resources/META-INF/resources/error/viewExpired.xhtml
@@ -63,11 +63,11 @@
Page d'administration en cours de développement...
-Page d'administration en cours de développement...
-Page d'administration en cours de développement...
-Garantie de non-régression : tout outcome utilisé en navigation existe physiquement.
+ */
+class ViewPathsConsistencyTest {
+
+ /** Constantes auxquelles aucun fichier physique n'est attaché (suffixes / racines techniques). */
+ private static final java.util.Set Action : créer les xhtml correspondants dans un sprint dédié, puis retirer cette liste.
+ * Le fait de centraliser via {@link ViewPaths} a permis de détecter ces pages fantômes.
+ */
+ private static final java.util.Set