feat: auto-activation après paiement Wave — plus de page d'attente

- auth_bloc: quand onboardingState==VALIDATED, refresh token et vérifier
  si statutCompte==ACTIF → dashboard direct (pas d'écran d'attente)
- Edge case: si activation backend échouée, fallback vers AwaitingValidationPage
  avec polling 15s
- onboarding_bloc: séparer VALIDATED de AWAITING_VALIDATION dans le switch
This commit is contained in:
dahoud
2026-04-18 08:07:30 +00:00
parent f96ab6e86e
commit 33f5b5a707
2 changed files with 57 additions and 7 deletions

View File

@@ -74,7 +74,7 @@ class AuthAccountNotActive extends AuthState {
/// Compte EN_ATTENTE_VALIDATION — l'OrgAdmin doit compléter l'onboarding.
/// On ne déconnecte PAS pour permettre les appels API de souscription.
class AuthPendingOnboarding extends AuthState {
final String onboardingState; // NO_SUBSCRIPTION | AWAITING_PAYMENT | PAYMENT_INITIATED | AWAITING_VALIDATION
final String onboardingState; // NO_SUBSCRIPTION | AWAITING_PAYMENT | PAYMENT_INITIATED | AWAITING_VALIDATION | VALIDATED
final String? souscriptionId;
final String? organisationId;
final String? typeOrganisation;
@@ -145,6 +145,29 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
if (status != null && status.isPendingOnboarding) {
// Souscription VALIDATED = paiement confirmé, activation imminente.
// Rafraîchir le token : si le backend a déjà activé le membre,
// les rôles MEMBRE/MEMBRE_ACTIF seront dans le nouveau token → dashboard.
if (status.onboardingState == 'VALIDATED') {
await _authService.refreshToken();
final refreshedStatus = await _authService.getAuthStatus(AppConfig.apiBaseUrl);
if (refreshedStatus != null && refreshedStatus.isActive) {
// Activation effective → procéder au dashboard
final refreshedRawUser = await _authService.getCurrentUser();
final user = await _enrichUserWithOrgContext(refreshedRawUser ?? rawUser);
final permissions = await PermissionEngine.getEffectivePermissions(user);
final token = await _authService.getValidToken();
await DashboardCacheManager.invalidateForRole(user.primaryRole);
emit(AuthAuthenticated(
user: user,
effectiveRole: user.primaryRole,
effectivePermissions: permissions,
accessToken: token ?? '',
));
return;
}
// Activation pas encore effective (edge case) → afficher page d'attente avec polling
}
// OrgAdmin en attente → rediriger vers l'onboarding (sans déconnecter)
final user = await _enrichUserWithOrgContext(rawUser);
final orgId = status.organisationId ??
@@ -244,6 +267,26 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
if (status != null && status.isPendingOnboarding) {
// Souscription VALIDATED : vérifier si le backend a finalisé l'activation
if (status.onboardingState == 'VALIDATED') {
await _authService.refreshToken();
final refreshedStatus = await _authService.getAuthStatus(AppConfig.apiBaseUrl);
if (refreshedStatus != null && refreshedStatus.isActive) {
final refreshedRawUser = await _authService.getCurrentUser();
final userActive = await _enrichUserWithOrgContext(refreshedRawUser ?? rawUser);
final permissions = await PermissionEngine.getEffectivePermissions(userActive);
final token = await _authService.getValidToken();
await DashboardCacheManager.invalidateForRole(userActive.primaryRole);
emit(AuthAuthenticated(
user: userActive,
effectiveRole: userActive.primaryRole,
effectivePermissions: permissions,
accessToken: token ?? '',
));
return;
}
// Activation pas encore effective → continuer vers la page d'attente
}
final user = await _enrichUserWithOrgContext(rawUser);
final orgId = status.organisationId ??
(user.organizationContexts.isNotEmpty