feat: add DCB User Service API - Authentication system with KEYCLOAK - Modular architecture with services for each feature
This commit is contained in:
parent
b81710fa59
commit
25d99b4edc
@ -200,19 +200,6 @@ export class TransactionDetails implements OnInit {
|
||||
if (diffDays < 7) return `Il y a ${diffDays} j`;
|
||||
return this.formatDate(date);
|
||||
}
|
||||
|
||||
canRefund(): boolean {
|
||||
return this.access.canRefund && this.transaction?.status === 'SUCCESS';
|
||||
}
|
||||
|
||||
canRetry(): boolean {
|
||||
return this.access.canRetry && this.transaction?.status === 'FAILED';
|
||||
}
|
||||
|
||||
canCancel(): boolean {
|
||||
return this.access.canCancel && this.transaction?.status === 'PENDING';
|
||||
}
|
||||
|
||||
// Méthodes pour le template
|
||||
getUserBadgeClass(): string {
|
||||
return this.access.isHubUser ? 'bg-primary' : 'bg-success';
|
||||
|
||||
@ -21,7 +21,8 @@ import {
|
||||
lucideStore,
|
||||
lucideCalendar,
|
||||
lucideRepeat,
|
||||
lucideCreditCard
|
||||
lucideCreditCard,
|
||||
lucideInfo
|
||||
} from '@ng-icons/lucide';
|
||||
import { NgbPaginationModule, NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@ -125,12 +126,9 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
private initializePermissions() {
|
||||
this.access = this.accessService.getTransactionAccess();
|
||||
|
||||
// Ajouter le merchant ID aux filtres si nécessaire
|
||||
// IMPORTANT: Toujours filtrer par merchant pour les merchant users
|
||||
if (this.access.isMerchantUser && this.access.allowedMerchantIds.length > 0) {
|
||||
this.filters.merchantPartnerId = this.access.allowedMerchantIds[0];
|
||||
} else if (this.access.isHubUser && this.access.merchantId) {
|
||||
// Pour les hub users qui veulent voir un merchant spécifique
|
||||
this.filters.merchantPartnerId = this.access.merchantId;
|
||||
}
|
||||
|
||||
// Définir le rôle pour l'affichage
|
||||
@ -147,27 +145,31 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
this.loading = true;
|
||||
this.error = '';
|
||||
|
||||
// Mettre à jour les filtres avec la recherche
|
||||
if (this.searchTerm) {
|
||||
this.filters.search = this.searchTerm;
|
||||
} else {
|
||||
delete this.filters.search;
|
||||
}
|
||||
// Préparer les filtres pour l'API
|
||||
const apiFilters = this.prepareFiltersForApi();
|
||||
|
||||
// Appliquer le tri
|
||||
this.filters.sortBy = this.sortField;
|
||||
this.filters.sortOrder = this.sortDirection;
|
||||
console.log('Chargement transactions avec filtres:', apiFilters);
|
||||
|
||||
// Appliquer les restrictions de merchant pour les non-admin hub users
|
||||
if (!this.access.canManageAll && this.access.allowedMerchantIds.length > 0) {
|
||||
this.filters.merchantPartnerId = this.access.allowedMerchantIds[0];
|
||||
}
|
||||
|
||||
this.transactionsService.getTransactions(this.filters).subscribe({
|
||||
this.transactionsService.getTransactions(apiFilters).subscribe({
|
||||
next: (data) => {
|
||||
this.paginatedData = data;
|
||||
this.transactions = data.data;
|
||||
this.loading = false;
|
||||
|
||||
// Log pour debug
|
||||
if (data.data.length > 0) {
|
||||
console.log(`Chargement réussi: ${data.data.length} transactions`);
|
||||
if (this.access.isMerchantUser && this.currentMerchantId) {
|
||||
// Vérifier que toutes les transactions appartiennent bien au marchand
|
||||
const wrongMerchantTx = data.data.filter(tx =>
|
||||
tx.merchantPartnerId !== this.currentMerchantId
|
||||
);
|
||||
if (wrongMerchantTx.length > 0) {
|
||||
console.warn('ATTENTION: certaines transactions ne sont pas du bon marchand:', wrongMerchantTx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.cdRef.detectChanges();
|
||||
},
|
||||
error: (error) => {
|
||||
@ -179,12 +181,39 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
private prepareFiltersForApi(): TransactionQuery {
|
||||
const apiFilters: TransactionQuery = { ...this.filters };
|
||||
|
||||
// Ajouter la recherche si présente
|
||||
if (this.searchTerm) {
|
||||
apiFilters.search = this.searchTerm;
|
||||
}
|
||||
|
||||
// Appliquer le tri
|
||||
apiFilters.sortBy = this.sortField;
|
||||
apiFilters.sortOrder = this.sortDirection;
|
||||
|
||||
// Nettoyer les filtres (enlever les undefined)
|
||||
Object.keys(apiFilters).forEach(key => {
|
||||
if (apiFilters[key as keyof TransactionQuery] === undefined) {
|
||||
delete apiFilters[key as keyof TransactionQuery];
|
||||
}
|
||||
});
|
||||
|
||||
return apiFilters;
|
||||
}
|
||||
|
||||
// Recherche et filtres
|
||||
onSearch() {
|
||||
this.filters.page = 1;
|
||||
this.loadTransactions();
|
||||
}
|
||||
|
||||
clearSearch() {
|
||||
this.searchTerm = '';
|
||||
this.onSearch();
|
||||
}
|
||||
|
||||
onClearFilters() {
|
||||
this.searchTerm = '';
|
||||
this.filters = {
|
||||
@ -197,7 +226,7 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
sortOrder: 'desc'
|
||||
};
|
||||
|
||||
// Réappliquer les restrictions de merchant
|
||||
// IMPORTANT: Toujours réappliquer le filtrage par marchand pour les merchant users
|
||||
if (this.access.isMerchantUser && this.access.allowedMerchantIds.length > 0) {
|
||||
this.filters.merchantPartnerId = this.access.allowedMerchantIds[0];
|
||||
}
|
||||
@ -225,7 +254,10 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
|
||||
// Permissions pour les filtres
|
||||
canUseMerchantFilter(): boolean {
|
||||
return this.access.canFilterByMerchant && this.access.allowedMerchantIds.length > 1;
|
||||
// Uniquement pour les hub users avec plusieurs merchants autorisés
|
||||
return this.access.canFilterByMerchant &&
|
||||
this.access.isHubUser &&
|
||||
this.access.allowedMerchantIds.length > 0;
|
||||
}
|
||||
|
||||
canUseAllFilters(): boolean {
|
||||
@ -240,6 +272,7 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
this.sortField = field;
|
||||
this.sortDirection = 'desc';
|
||||
}
|
||||
this.filters.page = 1;
|
||||
this.loadTransactions();
|
||||
}
|
||||
|
||||
@ -256,15 +289,7 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
|
||||
// Actions
|
||||
viewTransactionDetails(transactionId: string) {
|
||||
// Vérifier les permissions avant d'afficher
|
||||
this.accessService.canAccessTransaction().subscribe(canAccess => {
|
||||
if (canAccess) {
|
||||
this.transactionSelected.emit(transactionId);
|
||||
} else {
|
||||
this.error = 'Vous n\'avez pas la permission de voir les détails de cette transaction';
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Sélection multiple
|
||||
@ -283,6 +308,7 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
} else {
|
||||
this.selectedTransactions.clear();
|
||||
}
|
||||
this.updateSelectAllState();
|
||||
}
|
||||
|
||||
updateSelectAllState() {
|
||||
@ -290,7 +316,7 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
this.selectedTransactions.size === this.transactions.length;
|
||||
}
|
||||
|
||||
// Utilitaires d'affichage MIS À JOUR
|
||||
// Utilitaires d'affichage
|
||||
getStatusBadgeClass(status: TransactionStatus): string {
|
||||
switch (status) {
|
||||
case 'SUCCESS': return 'badge bg-success';
|
||||
@ -338,101 +364,6 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
formatCurrency(amount: number, currency: Currency = Currency.XOF): string {
|
||||
return TransactionUtils.formatAmount(amount, currency);
|
||||
}
|
||||
|
||||
formatDate(date: Date | string | undefined | null): string {
|
||||
// Si la date est null/undefined, retourner une chaîne vide
|
||||
if (!date) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
// Si c'est déjà une Date valide
|
||||
if (date instanceof Date) {
|
||||
// Vérifier si la Date est valide
|
||||
if (isNaN(date.getTime())) {
|
||||
return 'Date invalide';
|
||||
}
|
||||
return new Intl.DateTimeFormat('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
// Si c'est une chaîne, essayer de la convertir
|
||||
if (typeof date === 'string') {
|
||||
const dateObj = new Date(date);
|
||||
|
||||
// Vérifier si la conversion a réussi
|
||||
if (isNaN(dateObj.getTime())) {
|
||||
// Essayer d'autres formats
|
||||
const alternativeDate = this.parseDateString(date);
|
||||
if (alternativeDate && !isNaN(alternativeDate.getTime())) {
|
||||
return new Intl.DateTimeFormat('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}).format(alternativeDate);
|
||||
}
|
||||
return 'Date invalide';
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}).format(dateObj);
|
||||
}
|
||||
|
||||
// Pour tout autre type, retourner '-'
|
||||
return '-';
|
||||
}
|
||||
|
||||
private parseDateString(dateString: string): Date | null {
|
||||
try {
|
||||
// Essayer différents formats de date
|
||||
const formats = [
|
||||
dateString, // Format ISO original
|
||||
dateString.replace(' ', 'T'), // Remplacer espace par T
|
||||
dateString.split('.')[0], // Enlever les millisecondes
|
||||
];
|
||||
|
||||
for (const format of formats) {
|
||||
const date = new Date(format);
|
||||
if (!isNaN(date.getTime())) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
getAmountColor(amount: number): string {
|
||||
if (amount >= 10000) return 'text-danger fw-bold';
|
||||
if (amount >= 5000) return 'text-warning fw-semibold';
|
||||
return 'text-success';
|
||||
}
|
||||
|
||||
// utilitaires pour les abonnements
|
||||
getStatusDisplayName(status: TransactionStatus): string {
|
||||
return TransactionUtils.getStatusDisplayName(status);
|
||||
}
|
||||
|
||||
getTypeDisplayName(type: TransactionType): string {
|
||||
return TransactionUtils.getTypeDisplayName(type);
|
||||
}
|
||||
|
||||
getPeriodicityDisplayName(periodicity?: string): string {
|
||||
if (!periodicity) return '';
|
||||
|
||||
@ -446,6 +377,43 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
return periodicityNames[periodicity.toLowerCase()] || periodicity;
|
||||
}
|
||||
|
||||
formatCurrency(amount: number, currency: Currency = Currency.XOF): string {
|
||||
return TransactionUtils.formatAmount(amount, currency);
|
||||
}
|
||||
|
||||
formatDate(date: Date | string | undefined | null): string {
|
||||
if (!date) return '-';
|
||||
|
||||
try {
|
||||
const dateObj = date instanceof Date ? date : new Date(date);
|
||||
if (isNaN(dateObj.getTime())) return 'Date invalide';
|
||||
|
||||
return new Intl.DateTimeFormat('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}).format(dateObj);
|
||||
} catch {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
getAmountColor(amount: number): string {
|
||||
if (amount >= 10000) return 'text-danger fw-bold';
|
||||
if (amount >= 5000) return 'text-warning fw-semibold';
|
||||
return 'text-success';
|
||||
}
|
||||
|
||||
getStatusDisplayName(status: TransactionStatus): string {
|
||||
return TransactionUtils.getStatusDisplayName(status);
|
||||
}
|
||||
|
||||
getTypeDisplayName(type: TransactionType): string {
|
||||
return TransactionUtils.getTypeDisplayName(type);
|
||||
}
|
||||
|
||||
// Méthodes pour sécuriser l'accès aux stats
|
||||
getTotal(): number {
|
||||
return this.paginatedData?.stats?.total || 0;
|
||||
@ -482,8 +450,28 @@ export class TransactionsList implements OnInit, OnDestroy {
|
||||
|
||||
getScopeText(): string {
|
||||
if (this.access.isMerchantUser && this.currentMerchantId) {
|
||||
return `Merchant ${this.currentMerchantId}`;
|
||||
return `Marchand ${this.currentMerchantId}`;
|
||||
} else if (this.access.isHubUser && this.filters.merchantPartnerId) {
|
||||
return `Marchand ${this.filters.merchantPartnerId}`;
|
||||
}
|
||||
return this.access.canManageAll ? 'Tous les merchants' : 'Merchants autorisés';
|
||||
return 'Tous les marchands';
|
||||
}
|
||||
|
||||
// Méthode pour recharger les données
|
||||
refreshData() {
|
||||
this.loadTransactions();
|
||||
}
|
||||
|
||||
// Debug
|
||||
showDebugInfo() {
|
||||
console.log('=== DEBUG INFO ===');
|
||||
console.log('Permissions:', {
|
||||
isMerchantUser: this.access.isMerchantUser,
|
||||
isHubUser: this.access.isHubUser,
|
||||
merchantId: this.currentMerchantId,
|
||||
allowedMerchantIds: this.access.allowedMerchantIds,
|
||||
filters: this.filters
|
||||
});
|
||||
console.log('Transactions chargées:', this.transactions.length);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
// [file name]: transactions/services/transaction-access.service.ts
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { RoleManagementService, UserRole } from '@core/services/hub-users-roles-management.service';
|
||||
@ -10,12 +9,6 @@ export interface TransactionAccess {
|
||||
canViewAllTransactions: boolean; // Toutes vs seulement les siennes
|
||||
canViewDetails: boolean;
|
||||
|
||||
// Permissions d'actions
|
||||
canRefund: boolean;
|
||||
canRetry: boolean;
|
||||
canCancel: boolean;
|
||||
canExport: boolean;
|
||||
|
||||
// Permissions administratives
|
||||
canManageAll: boolean; // Toutes les transactions
|
||||
canFilterByMerchant: boolean;
|
||||
@ -41,7 +34,6 @@ export class TransactionAccessService {
|
||||
private roleService: RoleManagementService
|
||||
) {}
|
||||
|
||||
|
||||
getTransactionAccess(): TransactionAccess {
|
||||
if (this.accessCache) {
|
||||
return this.accessCache;
|
||||
@ -57,19 +49,13 @@ export class TransactionAccessService {
|
||||
canViewAllTransactions: this.canViewAllTransactions(userRole, isHubUser),
|
||||
canViewDetails: this.canViewDetails(userRole, isHubUser),
|
||||
|
||||
// Actions selon le rôle
|
||||
canRefund: this.canPerformRefund(userRole, isHubUser),
|
||||
canRetry: this.canPerformRetry(userRole, isHubUser),
|
||||
canCancel: this.canPerformCancel(userRole, isHubUser),
|
||||
canExport: this.canExport(userRole, isHubUser),
|
||||
|
||||
// Permissions administratives
|
||||
canManageAll: this.canManageAll(userRole, isHubUser),
|
||||
canFilterByMerchant: this.canFilterByMerchant(userRole, isHubUser),
|
||||
canViewSensitiveData: this.canViewSensitiveData(userRole, isHubUser),
|
||||
|
||||
// Scope
|
||||
allowedMerchantIds: this.getAllowedMerchantIds(isHubUser, merchantId),
|
||||
allowedMerchantIds: this.getAllowedMerchantIds(isHubUser, merchantId, userRole),
|
||||
isHubUser,
|
||||
isMerchantUser: !isHubUser,
|
||||
|
||||
@ -86,13 +72,26 @@ export class TransactionAccessService {
|
||||
// === MÉTHODES DE DÉTERMINATION DES PERMISSIONS ===
|
||||
|
||||
private canViewTransactions(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Tous les rôles peuvent voir les transactions
|
||||
// Tous les rôles peuvent voir les transactions (marchands et hub)
|
||||
return true;
|
||||
}
|
||||
|
||||
private canViewAllTransactions(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Hub users et DCB_PARTNER_ADMIN peuvent voir toutes les transactions
|
||||
return isHubUser || userRole === UserRole.DCB_PARTNER_ADMIN;
|
||||
if (isHubUser) {
|
||||
return true; // Les utilisateurs hub voient toutes les transactions
|
||||
}
|
||||
|
||||
// Pour les utilisateurs marchands :
|
||||
switch (userRole) {
|
||||
case UserRole.DCB_PARTNER_ADMIN:
|
||||
case UserRole.DCB_PARTNER_MANAGER:
|
||||
case UserRole.DCB_PARTNER_SUPPORT:
|
||||
// Les admins/support du marchand voient toutes les transactions de leur marchand
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private canViewDetails(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
@ -100,32 +99,6 @@ export class TransactionAccessService {
|
||||
return true;
|
||||
}
|
||||
|
||||
private canPerformRefund(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// DCB_ADMIN: peut rembourser toutes les transactions
|
||||
// DCB_SUPPORT: peut rembourser les transactions de son périmètre
|
||||
// DCB_PARTNER_ADMIN: peut rembourser les transactions de son merchant
|
||||
return isHubUser
|
||||
? userRole === UserRole.DCB_ADMIN || userRole === UserRole.DCB_SUPPORT
|
||||
: userRole === UserRole.DCB_PARTNER_ADMIN;
|
||||
}
|
||||
|
||||
private canPerformRetry(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Mêmes permissions que le remboursement
|
||||
return this.canPerformRefund(userRole, isHubUser);
|
||||
}
|
||||
|
||||
private canPerformCancel(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Plus restrictif - seulement les admins peuvent annuler
|
||||
return isHubUser
|
||||
? userRole === UserRole.DCB_ADMIN
|
||||
: userRole === UserRole.DCB_PARTNER_ADMIN;
|
||||
}
|
||||
|
||||
private canExport(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Tous peuvent exporter leurs propres données
|
||||
return true;
|
||||
}
|
||||
|
||||
private canManageAll(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Seulement DCB_ADMIN hub peut tout gérer
|
||||
return isHubUser && userRole === UserRole.DCB_ADMIN;
|
||||
@ -137,8 +110,13 @@ export class TransactionAccessService {
|
||||
}
|
||||
|
||||
private canViewSensitiveData(userRole: UserRole, isHubUser: boolean): boolean {
|
||||
// Hub users et DCB_PARTNER_ADMIN peuvent voir les données sensibles
|
||||
return isHubUser || userRole === UserRole.DCB_PARTNER_ADMIN;
|
||||
if (isHubUser) {
|
||||
// Tous les utilisateurs hub peuvent voir les données sensibles
|
||||
return true;
|
||||
} else {
|
||||
// Pour les marchands, seulement les rôles avec autorisation
|
||||
return userRole === UserRole.DCB_PARTNER_ADMIN || userRole === UserRole.DCB_PARTNER_SUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
// === GESTION DU SCOPE ===
|
||||
@ -156,14 +134,31 @@ export class TransactionAccessService {
|
||||
return isNaN(merchantId) ? undefined : merchantId;
|
||||
}
|
||||
|
||||
private getAllowedMerchantIds(isHubUser: boolean, merchantId?: number): number[] {
|
||||
private getAllowedMerchantIds(isHubUser: boolean, merchantId?: number, userRole?: UserRole): number[] {
|
||||
if (isHubUser) {
|
||||
// Hub users peuvent voir tous les merchants
|
||||
return []; // Tableau vide = tous les merchants
|
||||
} else {
|
||||
// Merchant users: seulement leur merchant
|
||||
return merchantId ? [merchantId] : [];
|
||||
// Mais seulement si l'utilisateur a accès aux transactions
|
||||
if (merchantId && this.hasMerchantAccess(userRole)) {
|
||||
return [merchantId];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private hasMerchantAccess(userRole?: UserRole): boolean {
|
||||
if (!userRole) return false;
|
||||
|
||||
// Rôles marchands qui ont accès aux transactions
|
||||
const merchantRolesWithAccess = [
|
||||
UserRole.DCB_PARTNER_ADMIN,
|
||||
UserRole.DCB_PARTNER_MANAGER,
|
||||
UserRole.DCB_PARTNER_SUPPORT
|
||||
];
|
||||
|
||||
return merchantRolesWithAccess.includes(userRole);
|
||||
}
|
||||
|
||||
// === MÉTHODES PUBLIQUES ===
|
||||
@ -184,6 +179,7 @@ export class TransactionAccessService {
|
||||
|
||||
// Merchant users: seulement leur merchant
|
||||
if (access.isMerchantUser) {
|
||||
// Vérifier si l'utilisateur marchand a accès au merchant de la transaction
|
||||
return of(access.allowedMerchantIds.includes(transactionMerchantId));
|
||||
}
|
||||
|
||||
@ -195,6 +191,22 @@ export class TransactionAccessService {
|
||||
return of(access.allowedMerchantIds.includes(transactionMerchantId));
|
||||
}
|
||||
|
||||
// Obtenir le scope des transactions pour les requêtes API
|
||||
getTransactionScope(): { merchantIds?: number[] } {
|
||||
const access = this.getTransactionAccess();
|
||||
|
||||
if (access.isHubUser) {
|
||||
// Hub users peuvent voir tous les merchants
|
||||
return {};
|
||||
} else {
|
||||
// Merchant users: seulement leur(s) merchant(s)
|
||||
if (access.allowedMerchantIds.length > 0) {
|
||||
return { merchantIds: access.allowedMerchantIds };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Nettoyer le cache
|
||||
clearCache(): void {
|
||||
this.accessCache = null;
|
||||
@ -204,4 +216,10 @@ export class TransactionAccessService {
|
||||
refreshAccess(): void {
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
// Méthode utilitaire pour afficher les permissions (debug)
|
||||
logAccessInfo(): void {
|
||||
const access = this.getTransactionAccess();
|
||||
console.log('Transaction Access Info:', access);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user