feat(v3.0): implémentation Phases 0-8 — RBAC, lifecycle, multi-org, plans, dashboards
Phase 0 : @RolesAllowed SUPER_ADMIN sur POST/DELETE organisations ; AuthenticationFilter pages super-admin Phase 2 : OrganisationModuleService, @RequiresModule, ModuleAccessFilter, RoleService, PermissionChecker Phase 3 : multi-org context switching (OrganisationContextFilter, headers X-Active-Organisation-Id / X-Active-Role) Phase 4 : feature-gating navigation par typeOrganisation (web MenuBean + mobile MorePage) Phase 5 : MemberLifecycleService — 8 transitions (activer/suspendre/radier/archiver/inviter/accepter/expirer/rappels) Phase 6 : FormuleAbonnement Option C (planCommercial, apiAccess, federationAccess, quotas) + SouscriptionOrganisation méthodes quota Phase 7 : DashboardResource SUPER_ADMIN ajouté ; DashboardBean.checkAccessAndRedirect() ; dashboards distincts par rôle Phase 8 : MembreResourceLifecycleRbacTest, SouscriptionQuotaOptionCTest, OrganisationContextHolderTest, OrganisationContextFilterMultiOrgTest, MemberLifecycleServiceTest
This commit is contained in:
@@ -7,6 +7,7 @@ import dev.lions.unionflow.server.api.dto.membre.response.MembreSummaryResponse;
|
||||
import dev.lions.unionflow.server.api.dto.membre.MembreSearchCriteria;
|
||||
import dev.lions.unionflow.server.api.dto.membre.MembreSearchResultDTO;
|
||||
|
||||
import dev.lions.unionflow.server.entity.FormuleAbonnement;
|
||||
import dev.lions.unionflow.server.entity.Membre;
|
||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||
import io.quarkus.panache.common.Page;
|
||||
@@ -200,6 +201,29 @@ public class MembreService {
|
||||
Membre membre = membreRepository.findByIdOptional(membreId)
|
||||
.orElseThrow(() -> new jakarta.ws.rs.NotFoundException("Membre non trouvé avec l'ID: " + membreId));
|
||||
|
||||
// Vérifier le quota d'administrateurs selon la formule souscrite
|
||||
membreOrganisationRepository.findFirstByMembreId(membreId).ifPresent(mo -> {
|
||||
UUID orgId = mo.getOrganisation().getId();
|
||||
entityManager.createQuery(
|
||||
"SELECT s FROM SouscriptionOrganisation s WHERE s.organisation.id = :orgId AND s.statut = 'ACTIVE'",
|
||||
dev.lions.unionflow.server.entity.SouscriptionOrganisation.class)
|
||||
.setParameter("orgId", orgId)
|
||||
.getResultStream().findFirst().ifPresent(souscription -> {
|
||||
FormuleAbonnement formule = souscription.getFormule();
|
||||
if (formule != null && formule.getMaxAdmins() != null) {
|
||||
long adminCount = entityManager.createQuery(
|
||||
"SELECT COUNT(mr) FROM MembreRole mr WHERE mr.organisation.id = :orgId " +
|
||||
"AND mr.role.code = 'ORGADMIN' AND mr.actif = true", Long.class)
|
||||
.setParameter("orgId", orgId).getSingleResult();
|
||||
if (adminCount >= formule.getMaxAdmins()) {
|
||||
throw new jakarta.ws.rs.ForbiddenException(
|
||||
"Le quota d'administrateurs de votre plan (" + formule.getMaxAdmins() +
|
||||
") est atteint. Mettez à niveau votre abonnement pour ajouter plus d'administrateurs.");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
membre.setStatutCompte("ACTIF");
|
||||
membre.setActif(true);
|
||||
membreRepository.persist(membre);
|
||||
@@ -432,7 +456,7 @@ public class MembreService {
|
||||
dev.lions.unionflow.server.entity.MembreOrganisation mo = membre.getMembresOrganisations().get(0);
|
||||
if (mo.getOrganisation() != null) {
|
||||
dto.setOrganisationId(mo.getOrganisation().getId());
|
||||
dto.setAssociationNom(mo.getOrganisation().getNom());
|
||||
dto.setOrganisationNom(mo.getOrganisation().getNom());
|
||||
}
|
||||
dto.setDateAdhesion(mo.getDateAdhesion());
|
||||
} else if (membre.getDateCreation() != null) {
|
||||
@@ -498,12 +522,12 @@ public class MembreService {
|
||||
}
|
||||
|
||||
UUID organisationId = null;
|
||||
String associationNom = null;
|
||||
String organisationNom = null;
|
||||
if (membre.getMembresOrganisations() != null && !membre.getMembresOrganisations().isEmpty()) {
|
||||
dev.lions.unionflow.server.entity.MembreOrganisation mo = membre.getMembresOrganisations().get(0);
|
||||
if (mo.getOrganisation() != null) {
|
||||
organisationId = mo.getOrganisation().getId();
|
||||
associationNom = mo.getOrganisation().getNom();
|
||||
organisationNom = mo.getOrganisation().getNom();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,7 +545,7 @@ public class MembreService {
|
||||
membre.getActif(),
|
||||
rolesNames,
|
||||
organisationId,
|
||||
associationNom);
|
||||
organisationNom);
|
||||
}
|
||||
|
||||
/** Convertit un CreateMembreRequest en entité Membre */
|
||||
@@ -1183,16 +1207,33 @@ public class MembreService {
|
||||
// Assigner le rôle SIMPLEMEMBER par défaut
|
||||
assignerRoleDefaut(membreOrganisation, "SIMPLEMEMBER");
|
||||
|
||||
// Incrémenter quota si souscription existe
|
||||
// Vérifier quota et expiration avant d'incrémenter
|
||||
if (souscriptionOpt.isPresent()) {
|
||||
dev.lions.unionflow.server.entity.SouscriptionOrganisation souscription = souscriptionOpt.get();
|
||||
|
||||
// Vérifier que la souscription n'est pas expirée
|
||||
if (!souscription.isActive()) {
|
||||
throw new jakarta.ws.rs.ForbiddenException(
|
||||
"La souscription de l'organisation est expirée ou inactive. " +
|
||||
"Veuillez renouveler votre abonnement avant d'ajouter de nouveaux membres.");
|
||||
}
|
||||
|
||||
// Vérifier que le quota n'est pas dépassé
|
||||
if (souscription.isQuotaDepasse()) {
|
||||
Integer max = souscription.getQuotaMax();
|
||||
throw new jakarta.ws.rs.ForbiddenException(
|
||||
"Le quota de membres de votre plan est atteint (" + max + "/" + max + "). " +
|
||||
"Veuillez mettre à niveau votre formule d'abonnement.");
|
||||
}
|
||||
|
||||
souscription.incrementerQuota();
|
||||
entityManager.persist(souscription);
|
||||
LOG.infof("Quota souscription incrémenté (utilise: %d/%s)",
|
||||
souscription.getQuotaUtilise(),
|
||||
souscription.getQuotaMax() != null ? souscription.getQuotaMax().toString() : "∞");
|
||||
} else {
|
||||
LOG.warn("Aucune souscription active trouvée pour organisation " + organisationId);
|
||||
LOG.warn("Aucune souscription active trouvée pour organisation " + organisationId +
|
||||
" — ajout du membre sans vérification de quota");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user