fix(souscription): réécrire activerAdminOrganisation — promouvoir le payeur, pas un membre aléatoire
Problème : après paiement Wave, le membre restait SIMPLEMEMBER car : 1. La méthode bouclait sur TOUS les liens de l'org et promouvait le premier non-ACTIF (pas forcément le payeur) 2. Si aucun lien n'existait, créait un lien avec SIMPLEMEMBER sans promotion 3. Early return après la première promotion → si le mauvais membre était promu, le payeur restait bloqué Nouvelle logique : 1. Identifier le caller (JWT email) = le membre qui a réellement payé 2. Vérifier/créer son lien MembreOrganisation (activer si en attente) 3. Promouvoir ce membre spécifique en ORGADMIN (DB) 4. Syncer Keycloak ADMIN_ORGANISATION (non-bloquant) Résultat : après paiement, le payeur est automatiquement promu ORGADMIN avec statut ACTIF et accède directement à son dashboard.
This commit is contained in:
@@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>Cascades : promouvoirAdminOrganisation (DB) + sync Keycloak ADMIN_ORGANISATION.
|
||||
*/
|
||||
private void activerAdminOrganisation(UUID organisationId) {
|
||||
List<dev.lions.unionflow.server.entity.MembreOrganisation> 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) {
|
||||
|
||||
Reference in New Issue
Block a user