# Admin organisation : gestion des membres et import massif Excel avec quota

## Contexte

- Un **administrateur d’organisation** (ADMIN_ORGANISATION) doit pouvoir **gérer les membres de son organisation** (liste, création unitaire, modification).
- Il doit pouvoir **créer des membres en masse** via un **fichier Excel strictement formaté**.
- Le nombre de créations doit être **plafonné** par le **quota de la souscription** (tranche/forme d’abonnement) de l’organisation.

## Règles métier

1. **Droits**
   - ADMIN_ORGANISATION : accès limité aux membres des organisations qu’il gère (liste, détail, création, mise à jour, import).
   - ADMIN / SUPER_ADMIN : accès à tous les membres (comportement actuel).

2. **Import massif**
   - Format : **Excel (.xlsx)** (et optionnellement CSV) avec colonnes obligatoires strictes (ex. nom, prénom, email, téléphone).
   - **organisationId** obligatoire pour un org admin ; les membres créés sont rattachés à cette organisation (création de `MembreOrganisation`).
   - **Quota** : avant d’accepter l’import, vérifier que  
     `quota_utilise + nombre de nouveaux membres à créer ≤ quota_max`  
     (ou pas de limite si `quota_max` est null, ex. formule Crystal).
   - À chaque membre **nouvellement créé** (pas les mises à jour) : créer le lien `MembreOrganisation` et incrémenter `quota_utilise` de la souscription.
   - Si le quota est dépassé en cours d’import : rejeter la requête (ou arrêter et retourner les erreurs selon le choix métier).

3. **Souscription**
   - Une organisation (racine) a au plus une souscription active (`souscriptions_organisation`).
   - `quota_max` = snapshot de la formule (ex. 50 pour Starter, null pour Crystal).
   - `quota_utilise` = nombre de membres comptabilisés pour cette souscription (incrémenté à chaque adhésion validée / membre créé dans l’org).

## Existant (WOU/DRY)

- **Backend**
  - `MembreResource` : GET list, GET /recherche, POST create, POST /import, GET /import/modele — existants ; à sécuriser et à scoper pour ADMIN_ORGANISATION.
  - `MembreImportExportService.importerMembres` : import Excel/CSV existant ; prend déjà `organisationId` ; **manque** : création de `MembreOrganisation`, vérification et incrément du quota.
  - Entités : `SouscriptionOrganisation` (quota_max, quota_utilise, incrementerQuota), `FormuleAbonnement` (max_membres), `MembreOrganisation` (lien membre–organisation).
- **Mobile**
  - Annuaire membres : critères de recherche avec `organisationIds` ; pour org admin, passer les IDs de “mes organisations” (déjà possible côté app si l’API les filtre).

## Implémentation préconisée

### Backend

1. **Sécurité et périmètre**
   - Sur `MembreResource` : ajouter `@RolesAllowed` adaptés (ex. MEMBRE, ADMIN, ADMIN_ORGANISATION pour liste/création/import).
   - Pour un utilisateur avec rôle ADMIN_ORGANISATION (et sans ADMIN/SUPER_ADMIN) :  
     - Lister les organisations du membre connecté (ex. `OrganisationService.listerOrganisationsPourUtilisateur(email)`).  
     - **Liste / recherche** : filtrer les membres par ces `organisationIds` (via `MembreOrganisation`).  
     - **Création** : exiger un `organisationId` dans le corps (ou le déduire) et vérifier qu’il appartient à ses organisations ; créer le `MembreOrganisation` après création du membre.  
     - **Import** : exiger `organisationId` et vérifier qu’il appartient à ses organisations ; appliquer la règle de quota et créer les `MembreOrganisation` + incrément de quota.

2. **Quota et import**
   - **Repository** : `SouscriptionOrganisationRepository` avec `findByOrganisationId(UUID)` (souscription active si besoin).
   - **Import** (dans `MembreImportExportService` ou service appelant) :  
     - Si `organisationId != null` : charger la souscription active de l’organisation.  
     - Pour chaque ligne du fichier : si c’est un **nouveau** membre (création, pas mise à jour) :  
       - Vérifier `souscription.getPlacesRestantes() > 0` (ou pas de limite si `quota_max == null`).  
       - Si dépassement : erreur explicite (ex. “Quota souscription atteint (max N membres)”) et arrêt ou rapport d’erreur.  
       - Après `creerMembre` : créer `MembreOrganisation` (membre, organisation, statut, dateAdhesion), persister, puis `souscription.incrementerQuota()` et persister la souscription.

3. **Modèle Excel**
   - Conserver le modèle actuel (GET `/api/membres/import/modele`) ; documenter les colonnes obligatoires et le fait que le fichier doit être strict (pas de colonnes en plus / types cohérents si besoin).
   - Optionnel : endpoint GET pour “quota actuel / places restantes” par organisation (pour affichage côté client).

### Mobile (optionnel dans un second temps)

- Pour un org admin : envoyer en requête liste/recherche les `organisationIds` (ses organisations) pour n’afficher que les membres de son périmètre.
- Écran “Import membres” : choix de l’organisation (pré-rempli si une seule), upload du fichier Excel, affichage du quota restant (si l’API le fournit) et du résultat d’import (succès / erreurs).

## Critères d’acceptation

- [ ] Un admin d’organisation ne voit que les membres de ses organisations (liste, recherche).
- [ ] Un admin d’organisation peut créer un membre dans une de ses organisations (et le lien MembreOrganisation est créé).
- [ ] Un admin d’organisation peut lancer un import Excel avec `organisationId` ; le fichier est validé (format strict), le quota souscription est vérifié avant/pendant l’import.
- [ ] Les nouveaux membres créés lors de l’import sont rattachés à l’organisation et le quota souscription est incrémenté.
- [ ] Si le quota est dépassé (fichier trop gros ou quota déjà saturé), l’import est refusé ou s’arrête avec un message clair (quota max N, X demandés, etc.).
