274 lines
8.0 KiB
TypeScript
274 lines
8.0 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { Observable, of, BehaviorSubject } from 'rxjs';
|
|
import { map, catchError, switchMap, take, filter, tap } from 'rxjs/operators';
|
|
import { UserRole, RoleManagementService } from '@core/services/hub-users-roles-management.service';
|
|
import { MerchantConfigService } from '@modules/merchant-config/merchant-config.service';
|
|
import { AuthService } from '@core/services/auth.service';
|
|
|
|
export interface DashboardAccess {
|
|
isHubUser: boolean;
|
|
isMerchantUser: boolean;
|
|
userRole: UserRole;
|
|
merchantId?: number;
|
|
}
|
|
|
|
export interface AllowedMerchant {
|
|
id: number | undefined;
|
|
name: string;
|
|
}
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class DashboardAccessService {
|
|
private accessCache: DashboardAccess | null = null;
|
|
private merchantsCache: AllowedMerchant[] | null = null;
|
|
private currentMerchantId: number | null = null;
|
|
private ready$ = new BehaviorSubject<boolean>(false);
|
|
private profileLoaded = false;
|
|
|
|
constructor(
|
|
private roleService: RoleManagementService,
|
|
private merchantService: MerchantConfigService,
|
|
private authService: AuthService
|
|
) {
|
|
// Initialisation simple
|
|
this.initialize();
|
|
}
|
|
|
|
private initialize(): void {
|
|
console.log('🚀 DashboardAccessService: Initialisation');
|
|
|
|
// S'abonner aux changements de profil
|
|
this.authService.getUserProfile().subscribe({
|
|
next: (profile) => {
|
|
if (profile) {
|
|
console.log('✅ DashboardAccessService: Profil chargé', {
|
|
username: profile.username,
|
|
merchantPartnerId: profile.merchantPartnerId,
|
|
userType: profile.userType
|
|
});
|
|
this.profileLoaded = true;
|
|
this.ready$.next(true);
|
|
}
|
|
},
|
|
error: (err) => {
|
|
console.error('❌ DashboardAccessService: Erreur de profil:', err);
|
|
this.profileLoaded = false;
|
|
this.ready$.next(false);
|
|
}
|
|
});
|
|
|
|
// Nettoyer à la déconnexion
|
|
this.authService.getAuthState().subscribe(isAuthenticated => {
|
|
if (!isAuthenticated) {
|
|
console.log('🚨 DashboardAccessService: Déconnexion détectée');
|
|
this.clearCache();
|
|
this.profileLoaded = false;
|
|
this.ready$.next(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Attendre que le service soit prêt AVEC PROFIL CHARGÉ
|
|
waitForReady(): Observable<boolean> {
|
|
return this.ready$.pipe(
|
|
filter(ready => ready && this.profileLoaded),
|
|
take(1),
|
|
tap(() => {
|
|
console.log('✅ DashboardAccessService: waitForReady() - Service vraiment prêt');
|
|
})
|
|
);
|
|
}
|
|
|
|
// Obtenir l'accès dashboard
|
|
getDashboardAccess(): DashboardAccess {
|
|
if (this.accessCache) {
|
|
return this.accessCache;
|
|
}
|
|
|
|
// VÉRIFIER que le profil est chargé
|
|
if (!this.profileLoaded) {
|
|
console.warn('⚠️ DashboardAccessService: Tentative d\'accès avant chargement du profil');
|
|
throw new Error('Profil non chargé');
|
|
}
|
|
|
|
const profile = this.authService.getCurrentUserProfile();
|
|
|
|
// VÉRIFIER que le profil existe
|
|
if (!profile) {
|
|
console.error('❌ DashboardAccessService: Profil null dans getDashboardAccess()');
|
|
throw new Error('Profil utilisateur non disponible');
|
|
}
|
|
|
|
console.log('📊 DashboardAccessService: getDashboardAccess() avec profil:', {
|
|
username: profile.username,
|
|
merchantPartnerId: profile.merchantPartnerId,
|
|
userType: profile.userType
|
|
});
|
|
|
|
const userRole = this.roleService.getCurrentRole();
|
|
const isHubUser = this.roleService.isHubUser();
|
|
|
|
let merchantId: number | undefined = undefined;
|
|
|
|
if (!isHubUser && profile.merchantPartnerId) {
|
|
merchantId = Number(profile.merchantPartnerId);
|
|
if (isNaN(merchantId) || merchantId <= 0) {
|
|
console.warn(`⚠️ DashboardAccessService: merchantPartnerId invalide: ${profile.merchantPartnerId}`);
|
|
merchantId = undefined;
|
|
}
|
|
}
|
|
|
|
this.accessCache = {
|
|
isHubUser,
|
|
isMerchantUser: !isHubUser,
|
|
userRole: userRole || UserRole.DCB_SUPPORT,
|
|
merchantId
|
|
};
|
|
|
|
console.log('🎯 DashboardAccessService: Accès créé:', this.accessCache);
|
|
|
|
return this.accessCache;
|
|
}
|
|
|
|
// Obtenir l'accès dashboard avec attente
|
|
getDashboardAccessAsync(): Observable<DashboardAccess> {
|
|
return this.waitForReady().pipe(
|
|
map(() => this.getDashboardAccess())
|
|
);
|
|
}
|
|
|
|
// Obtenir les marchands disponibles
|
|
getAvailableMerchants(): Observable<AllowedMerchant[]> {
|
|
return this.waitForReady().pipe(
|
|
switchMap(() => {
|
|
if (this.merchantsCache) {
|
|
return of(this.merchantsCache);
|
|
}
|
|
|
|
const access = this.getDashboardAccess();
|
|
|
|
if (access.isHubUser) {
|
|
return this.merchantService.getAllMerchants().pipe(
|
|
map(merchants => {
|
|
const available: AllowedMerchant[] = merchants.items.map(m => ({
|
|
id: m.id,
|
|
name: m.name
|
|
}));
|
|
|
|
// Option globale pour les hub users
|
|
available.unshift({ id: 0, name: '🌐 Données globales' });
|
|
|
|
this.merchantsCache = available;
|
|
return available;
|
|
}),
|
|
catchError(() => {
|
|
return of([{ id: 0, name: '🌐 Données globales' }]);
|
|
})
|
|
);
|
|
} else {
|
|
// Merchant user: seulement son merchant
|
|
const merchantId = access.merchantId;
|
|
if (merchantId) {
|
|
const merchants = [{ id: merchantId, name: `🏪 Merchant ${merchantId}` }];
|
|
this.merchantsCache = merchants;
|
|
return of(merchants);
|
|
}
|
|
return of([]);
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
// Définir le marchand sélectionné (hub users seulement)
|
|
setSelectedMerchantId(merchantId: number): void {
|
|
if (this.getDashboardAccess().isHubUser) {
|
|
this.currentMerchantId = merchantId;
|
|
}
|
|
}
|
|
|
|
// Obtenir le marchand sélectionné
|
|
getSelectedMerchantId(): number | null {
|
|
const access = this.getDashboardAccess();
|
|
|
|
if (access.isMerchantUser) {
|
|
return access.merchantId || null;
|
|
}
|
|
|
|
return this.currentMerchantId;
|
|
}
|
|
|
|
// Nettoyer le cache
|
|
clearCache(): void {
|
|
this.accessCache = null;
|
|
this.merchantsCache = null;
|
|
this.currentMerchantId = null;
|
|
}
|
|
|
|
// ============ MÉTHODES UTILITAIRES SIMPLES ============
|
|
|
|
shouldShowSystemHealth(): boolean {
|
|
return this.getDashboardAccess().isHubUser;
|
|
}
|
|
|
|
shouldShowAlerts(): boolean {
|
|
return true;
|
|
}
|
|
|
|
canTriggerSync(): boolean {
|
|
const access = this.getDashboardAccess();
|
|
return access.isHubUser && access.userRole === UserRole.DCB_ADMIN;
|
|
}
|
|
|
|
canManageMerchants(): boolean {
|
|
const access = this.getDashboardAccess();
|
|
return access.isHubUser && access.userRole === UserRole.DCB_ADMIN;
|
|
}
|
|
|
|
canSelectMerchant(): boolean {
|
|
return this.getDashboardAccess().isHubUser;
|
|
}
|
|
|
|
canEditMerchantFilter(): boolean {
|
|
const access = this.getDashboardAccess();
|
|
if (access.isHubUser) {
|
|
return access.userRole === UserRole.DCB_ADMIN;
|
|
}
|
|
return access.userRole === UserRole.DCB_PARTNER_ADMIN;
|
|
}
|
|
|
|
shouldShowMerchantId(): boolean {
|
|
const access = this.getDashboardAccess();
|
|
return access.isMerchantUser ||
|
|
(access.isHubUser && this.getSelectedMerchantId() !== null);
|
|
}
|
|
|
|
canViewGlobalData(): boolean {
|
|
return this.getDashboardAccess().isHubUser;
|
|
}
|
|
|
|
isViewingGlobalData(): boolean {
|
|
const access = this.getDashboardAccess();
|
|
if (access.isHubUser) {
|
|
return this.currentMerchantId === 0 || this.currentMerchantId === null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
getCurrentMerchantName(): string {
|
|
const access = this.getDashboardAccess();
|
|
|
|
if (access.isMerchantUser && access.merchantId) {
|
|
return `Merchant ${access.merchantId}`;
|
|
}
|
|
|
|
if (access.isHubUser) {
|
|
if (this.currentMerchantId === 0 || this.currentMerchantId === null) {
|
|
return 'Données globales';
|
|
} else if (this.currentMerchantId) {
|
|
return `Merchant ${this.currentMerchantId}`;
|
|
}
|
|
}
|
|
|
|
return 'Inconnu';
|
|
}
|
|
} |