diff --git a/src/main/java/dev/lions/unionflow/server/service/SouscriptionService.java b/src/main/java/dev/lions/unionflow/server/service/SouscriptionService.java index 7efb8f8..a56ff17 100644 --- a/src/main/java/dev/lions/unionflow/server/service/SouscriptionService.java +++ b/src/main/java/dev/lions/unionflow/server/service/SouscriptionService.java @@ -448,56 +448,68 @@ public class SouscriptionService { * Si aucun lien membre-organisation n'existe, tente de créer le lien pour le * caller courant (email JWT) avant d'activer. */ + /** + * Active l'admin de l'organisation après paiement de la souscription. + * + *

Stratégie : identifier le membre qui a payé (via JWT) et le promouvoir + * ORGADMIN. Si le membre n'a pas de lien MembreOrganisation, le créer. + * + *

Cascades : promouvoirAdminOrganisation (DB) + sync Keycloak ADMIN_ORGANISATION. + */ private void activerAdminOrganisation(UUID organisationId) { - List liens = - membreOrganisationRepository.findAllByOrganisationId(organisationId); + // ── 1. Identifier le caller (le membre qui a payé) ───────────────────── + String email = securiteHelper.resolveEmail(); + if (email == null) { + LOG.warnf("activerAdminOrganisation: impossible de résoudre l'email JWT pour org=%s", organisationId); + return; + } - if (liens.isEmpty()) { - LOG.warnf("activerAdminOrganisation: aucun lien membre-organisation trouvé pour org=%s — tentative de liaison via JWT", organisationId); + Membre caller = membreRepository.findByEmail(email).orElse(null); + if (caller == null) { + LOG.warnf("activerAdminOrganisation: aucun membre trouvé pour email=%s", email); + return; + } - // Récupérer l'email du caller depuis le JWT - String email = securiteHelper.resolveEmail(); - if (email == null) { - LOG.warnf("activerAdminOrganisation: impossible de résoudre l'email JWT pour org=%s", organisationId); - return; - } + Organisation org = organisationRepo.findByIdOptional(organisationId).orElse(null); + if (org == null) { + LOG.warnf("activerAdminOrganisation: organisation introuvable org=%s", organisationId); + return; + } - Membre caller = membreRepository.findByEmail(email).orElse(null); - if (caller == null) { - LOG.warnf("activerAdminOrganisation: aucun membre trouvé pour email=%s", email); - return; - } + LOG.infof("activerAdminOrganisation: caller=%s (%s) pour org=%s (%s)", + caller.getId(), email, organisationId, org.getNom()); - Organisation org = organisationRepo.findByIdOptional(organisationId).orElse(null); - if (org == null) { - LOG.warnf("activerAdminOrganisation: organisation introuvable org=%s", organisationId); - return; - } + // ── 2. S'assurer que le caller a un lien MembreOrganisation ──────────── + var lienOpt = membreOrganisationRepository + .findByMembreIdAndOrganisationId(caller.getId(), organisationId); - // Créer le lien MembreOrganisation à la volée + if (lienOpt.isEmpty()) { + LOG.infof("activerAdminOrganisation: pas de lien existant — création pour membre=%s org=%s", caller.getId(), organisationId); membreService.lierMembreOrganisationEtIncrementerQuota(caller, organisationId, "ACTIF"); - LOG.infof("activerAdminOrganisation: lien créé à la volée pour membre=%s org=%s", caller.getId(), organisationId); - - // Recharger et activer - liens = membreOrganisationRepository.findAllByOrganisationId(organisationId); - } - - for (dev.lions.unionflow.server.entity.MembreOrganisation lien : liens) { - Membre m = lien.getMembre(); - if (m != null && !"ACTIF".equals(m.getStatutCompte())) { - // Promouvoir → statut ACTIF + rôle ORGADMIN en base - membreService.promouvoirAdminOrganisation(m.getId()); - // Sync Keycloak : assigner ADMIN_ORGANISATION (non-bloquant) - try { - keycloakSyncService.promouvoirAdminOrganisationDansKeycloak(m.getId()); - } catch (Exception e) { - LOG.warnf("Keycloak sync ORGADMIN échouée pour membre=%s (non-bloquant): %s", m.getId(), e.getMessage()); - } - LOG.infof("Membre admin %s promu ORGADMIN pour organisation %s", m.getId(), organisationId); - return; + } else { + // Activer le lien existant s'il est en attente + var lien = lienOpt.get(); + if (lien.getStatutMembre() != dev.lions.unionflow.server.api.enums.membre.StatutMembre.ACTIF) { + lien.setStatutMembre(dev.lions.unionflow.server.api.enums.membre.StatutMembre.ACTIF); + LOG.infof("activerAdminOrganisation: lien existant activé (statut→ACTIF) pour membre=%s", caller.getId()); } } - LOG.infof("activerAdminOrganisation: tous les membres de org=%s sont déjà ACTIF", organisationId); + + // ── 3. Promouvoir en ORGADMIN (DB + Keycloak) ────────────────────────── + try { + membreService.promouvoirAdminOrganisation(caller.getId()); + LOG.infof("activerAdminOrganisation: membre %s promu ORGADMIN en DB", caller.getId()); + } catch (Exception e) { + LOG.errorf("activerAdminOrganisation: échec promotion DB pour membre=%s : %s", caller.getId(), e.getMessage()); + } + + try { + keycloakSyncService.promouvoirAdminOrganisationDansKeycloak(caller.getId()); + LOG.infof("activerAdminOrganisation: rôle Keycloak ADMIN_ORGANISATION assigné pour membre=%s", caller.getId()); + } catch (Exception e) { + LOG.warnf("activerAdminOrganisation: sync Keycloak ORGADMIN échouée pour membre=%s (non-bloquant): %s", + caller.getId(), e.getMessage()); + } } private void notifierSuperAdmins(SouscriptionOrganisation souscription) {