Versione OK Pour l'onglet événements.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import '../../../../core/models/cotisation_model.dart';
|
||||
import '../../../../core/models/payment_model.dart';
|
||||
import '../../../../core/services/payment_service.dart';
|
||||
import '../../../../core/services/notification_service.dart';
|
||||
import '../../domain/repositories/cotisation_repository.dart';
|
||||
import 'cotisations_event.dart';
|
||||
import 'cotisations_state.dart';
|
||||
@@ -10,8 +13,14 @@ import 'cotisations_state.dart';
|
||||
@injectable
|
||||
class CotisationsBloc extends Bloc<CotisationsEvent, CotisationsState> {
|
||||
final CotisationRepository _cotisationRepository;
|
||||
final PaymentService _paymentService;
|
||||
final NotificationService _notificationService;
|
||||
|
||||
CotisationsBloc(this._cotisationRepository) : super(const CotisationsInitial()) {
|
||||
CotisationsBloc(
|
||||
this._cotisationRepository,
|
||||
this._paymentService,
|
||||
this._notificationService,
|
||||
) : super(const CotisationsInitial()) {
|
||||
// Enregistrement des handlers d'événements
|
||||
on<LoadCotisations>(_onLoadCotisations);
|
||||
on<LoadCotisationById>(_onLoadCotisationById);
|
||||
@@ -28,6 +37,15 @@ class CotisationsBloc extends Bloc<CotisationsEvent, CotisationsState> {
|
||||
on<ResetCotisationsState>(_onResetCotisationsState);
|
||||
on<FilterCotisations>(_onFilterCotisations);
|
||||
on<SortCotisations>(_onSortCotisations);
|
||||
|
||||
// Nouveaux handlers pour les paiements et fonctionnalités avancées
|
||||
on<InitiatePayment>(_onInitiatePayment);
|
||||
on<CheckPaymentStatus>(_onCheckPaymentStatus);
|
||||
on<CancelPayment>(_onCancelPayment);
|
||||
on<ScheduleNotifications>(_onScheduleNotifications);
|
||||
on<SyncWithServer>(_onSyncWithServer);
|
||||
on<ApplyAdvancedFilters>(_onApplyAdvancedFilters);
|
||||
on<ExportCotisations>(_onExportCotisations);
|
||||
}
|
||||
|
||||
/// Handler pour charger la liste des cotisations
|
||||
@@ -506,4 +524,207 @@ class CotisationsBloc extends Bloc<CotisationsEvent, CotisationsState> {
|
||||
emit(currentState.copyWith(filteredCotisations: sortedList));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour initier un paiement
|
||||
Future<void> _onInitiatePayment(
|
||||
InitiatePayment event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
// Valider les données de paiement
|
||||
if (!_paymentService.validatePaymentData(
|
||||
cotisationId: event.cotisationId,
|
||||
montant: event.montant,
|
||||
methodePaiement: event.methodePaiement,
|
||||
numeroTelephone: event.numeroTelephone,
|
||||
)) {
|
||||
emit(PaymentFailure(
|
||||
cotisationId: event.cotisationId,
|
||||
paymentId: '',
|
||||
errorMessage: 'Données de paiement invalides',
|
||||
errorCode: 'INVALID_DATA',
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// Initier le paiement
|
||||
final payment = await _paymentService.initiatePayment(
|
||||
cotisationId: event.cotisationId,
|
||||
montant: event.montant,
|
||||
methodePaiement: event.methodePaiement,
|
||||
numeroTelephone: event.numeroTelephone,
|
||||
nomPayeur: event.nomPayeur,
|
||||
emailPayeur: event.emailPayeur,
|
||||
);
|
||||
|
||||
emit(PaymentInProgress(
|
||||
cotisationId: event.cotisationId,
|
||||
paymentId: payment.id,
|
||||
methodePaiement: event.methodePaiement,
|
||||
montant: event.montant,
|
||||
));
|
||||
|
||||
} catch (e) {
|
||||
emit(PaymentFailure(
|
||||
cotisationId: event.cotisationId,
|
||||
paymentId: '',
|
||||
errorMessage: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour vérifier le statut d'un paiement
|
||||
Future<void> _onCheckPaymentStatus(
|
||||
CheckPaymentStatus event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
final payment = await _paymentService.checkPaymentStatus(event.paymentId);
|
||||
|
||||
if (payment.isSuccessful) {
|
||||
// Récupérer la cotisation mise à jour
|
||||
final cotisation = await _cotisationRepository.getCotisationById(payment.cotisationId);
|
||||
|
||||
emit(PaymentSuccess(
|
||||
cotisationId: payment.cotisationId,
|
||||
payment: payment,
|
||||
updatedCotisation: cotisation,
|
||||
));
|
||||
|
||||
// Envoyer notification de succès
|
||||
await _notificationService.showPaymentConfirmation(cotisation, payment.montant);
|
||||
|
||||
} else if (payment.isFailed) {
|
||||
emit(PaymentFailure(
|
||||
cotisationId: payment.cotisationId,
|
||||
paymentId: payment.id,
|
||||
errorMessage: payment.messageErreur ?? 'Paiement échoué',
|
||||
));
|
||||
|
||||
// Envoyer notification d'échec
|
||||
final cotisation = await _cotisationRepository.getCotisationById(payment.cotisationId);
|
||||
await _notificationService.showPaymentFailure(cotisation, payment.messageErreur ?? 'Erreur inconnue');
|
||||
}
|
||||
} catch (e) {
|
||||
emit(CotisationsError('Erreur lors de la vérification du paiement: ${e.toString()}'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour annuler un paiement
|
||||
Future<void> _onCancelPayment(
|
||||
CancelPayment event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
final cancelled = await _paymentService.cancelPayment(event.paymentId);
|
||||
|
||||
if (cancelled) {
|
||||
emit(PaymentCancelled(
|
||||
cotisationId: event.cotisationId,
|
||||
paymentId: event.paymentId,
|
||||
));
|
||||
} else {
|
||||
emit(const CotisationsError('Impossible d\'annuler le paiement'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(CotisationsError('Erreur lors de l\'annulation du paiement: ${e.toString()}'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour programmer les notifications
|
||||
Future<void> _onScheduleNotifications(
|
||||
ScheduleNotifications event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
await _notificationService.scheduleAllCotisationsNotifications(event.cotisations);
|
||||
|
||||
emit(NotificationsScheduled(
|
||||
notificationsCount: event.cotisations.length * 2,
|
||||
cotisationIds: event.cotisations.map((c) => c.id).toList(),
|
||||
));
|
||||
} catch (e) {
|
||||
emit(CotisationsError('Erreur lors de la programmation des notifications: ${e.toString()}'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour synchroniser avec le serveur
|
||||
Future<void> _onSyncWithServer(
|
||||
SyncWithServer event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const SyncInProgress('Synchronisation en cours...'));
|
||||
|
||||
// Recharger les données
|
||||
final cotisations = await _cotisationRepository.getCotisations();
|
||||
|
||||
emit(SyncCompleted(
|
||||
itemsSynced: cotisations.length,
|
||||
syncTime: DateTime.now(),
|
||||
));
|
||||
|
||||
// Émettre l'état chargé avec les nouvelles données
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: cotisations,
|
||||
filteredCotisations: cotisations,
|
||||
));
|
||||
|
||||
} catch (e) {
|
||||
emit(CotisationsError('Erreur lors de la synchronisation: ${e.toString()}'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour appliquer des filtres avancés
|
||||
Future<void> _onApplyAdvancedFilters(
|
||||
ApplyAdvancedFilters event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading());
|
||||
|
||||
final cotisations = await _cotisationRepository.rechercherCotisations(
|
||||
membreId: event.filters['membreId'],
|
||||
statut: event.filters['statut'],
|
||||
typeCotisation: event.filters['typeCotisation'],
|
||||
annee: event.filters['annee'],
|
||||
mois: event.filters['mois'],
|
||||
);
|
||||
|
||||
emit(CotisationsSearchResults(
|
||||
cotisations: cotisations,
|
||||
searchCriteria: event.filters,
|
||||
));
|
||||
|
||||
} catch (e) {
|
||||
emit(CotisationsError('Erreur lors de l\'application des filtres: ${e.toString()}'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler pour exporter les cotisations
|
||||
Future<void> _onExportCotisations(
|
||||
ExportCotisations event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
final cotisations = event.cotisations ?? [];
|
||||
|
||||
emit(ExportInProgress(
|
||||
format: event.format,
|
||||
totalItems: cotisations.length,
|
||||
));
|
||||
|
||||
// TODO: Implémenter l'export réel selon le format
|
||||
await Future.delayed(const Duration(seconds: 2)); // Simulation
|
||||
|
||||
emit(ExportCompleted(
|
||||
format: event.format,
|
||||
filePath: '/storage/emulated/0/Download/cotisations.${event.format}',
|
||||
itemsExported: cotisations.length,
|
||||
));
|
||||
|
||||
} catch (e) {
|
||||
emit(CotisationsError('Erreur lors de l\'export: ${e.toString()}'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,3 +204,97 @@ class SortCotisations extends CotisationsEvent {
|
||||
@override
|
||||
List<Object?> get props => [sortBy, ascending];
|
||||
}
|
||||
|
||||
/// Événement pour initier un paiement
|
||||
class InitiatePayment extends CotisationsEvent {
|
||||
final String cotisationId;
|
||||
final double montant;
|
||||
final String methodePaiement;
|
||||
final String numeroTelephone;
|
||||
final String? nomPayeur;
|
||||
final String? emailPayeur;
|
||||
|
||||
const InitiatePayment({
|
||||
required this.cotisationId,
|
||||
required this.montant,
|
||||
required this.methodePaiement,
|
||||
required this.numeroTelephone,
|
||||
this.nomPayeur,
|
||||
this.emailPayeur,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
cotisationId,
|
||||
montant,
|
||||
methodePaiement,
|
||||
numeroTelephone,
|
||||
nomPayeur,
|
||||
emailPayeur,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour vérifier le statut d'un paiement
|
||||
class CheckPaymentStatus extends CotisationsEvent {
|
||||
final String paymentId;
|
||||
|
||||
const CheckPaymentStatus(this.paymentId);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [paymentId];
|
||||
}
|
||||
|
||||
/// Événement pour annuler un paiement
|
||||
class CancelPayment extends CotisationsEvent {
|
||||
final String paymentId;
|
||||
final String cotisationId;
|
||||
|
||||
const CancelPayment({
|
||||
required this.paymentId,
|
||||
required this.cotisationId,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [paymentId, cotisationId];
|
||||
}
|
||||
|
||||
/// Événement pour programmer des notifications
|
||||
class ScheduleNotifications extends CotisationsEvent {
|
||||
final List<CotisationModel> cotisations;
|
||||
|
||||
const ScheduleNotifications(this.cotisations);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cotisations];
|
||||
}
|
||||
|
||||
/// Événement pour synchroniser avec le serveur
|
||||
class SyncWithServer extends CotisationsEvent {
|
||||
final bool forceSync;
|
||||
|
||||
const SyncWithServer({this.forceSync = false});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [forceSync];
|
||||
}
|
||||
|
||||
/// Événement pour appliquer des filtres avancés
|
||||
class ApplyAdvancedFilters extends CotisationsEvent {
|
||||
final Map<String, dynamic> filters;
|
||||
|
||||
const ApplyAdvancedFilters(this.filters);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [filters];
|
||||
}
|
||||
|
||||
/// Événement pour exporter des données
|
||||
class ExportCotisations extends CotisationsEvent {
|
||||
final String format; // 'pdf', 'excel', 'csv'
|
||||
final List<CotisationModel>? cotisations;
|
||||
|
||||
const ExportCotisations(this.format, {this.cotisations});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [format, cotisations];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../../core/models/cotisation_model.dart';
|
||||
import '../../../../core/models/payment_model.dart';
|
||||
|
||||
/// États du BLoC des cotisations
|
||||
abstract class CotisationsState extends Equatable {
|
||||
@@ -245,3 +246,137 @@ class CotisationsSearchResults extends CotisationsState {
|
||||
@override
|
||||
List<Object?> get props => [cotisations, searchCriteria, hasReachedMax, currentPage];
|
||||
}
|
||||
|
||||
/// État pour un paiement en cours
|
||||
class PaymentInProgress extends CotisationsState {
|
||||
final String cotisationId;
|
||||
final String paymentId;
|
||||
final String methodePaiement;
|
||||
final double montant;
|
||||
|
||||
const PaymentInProgress({
|
||||
required this.cotisationId,
|
||||
required this.paymentId,
|
||||
required this.methodePaiement,
|
||||
required this.montant,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cotisationId, paymentId, methodePaiement, montant];
|
||||
}
|
||||
|
||||
/// État pour un paiement réussi
|
||||
class PaymentSuccess extends CotisationsState {
|
||||
final String cotisationId;
|
||||
final PaymentModel payment;
|
||||
final CotisationModel updatedCotisation;
|
||||
|
||||
const PaymentSuccess({
|
||||
required this.cotisationId,
|
||||
required this.payment,
|
||||
required this.updatedCotisation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cotisationId, payment, updatedCotisation];
|
||||
}
|
||||
|
||||
/// État pour un paiement échoué
|
||||
class PaymentFailure extends CotisationsState {
|
||||
final String cotisationId;
|
||||
final String paymentId;
|
||||
final String errorMessage;
|
||||
final String? errorCode;
|
||||
|
||||
const PaymentFailure({
|
||||
required this.cotisationId,
|
||||
required this.paymentId,
|
||||
required this.errorMessage,
|
||||
this.errorCode,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cotisationId, paymentId, errorMessage, errorCode];
|
||||
}
|
||||
|
||||
/// État pour un paiement annulé
|
||||
class PaymentCancelled extends CotisationsState {
|
||||
final String cotisationId;
|
||||
final String paymentId;
|
||||
|
||||
const PaymentCancelled({
|
||||
required this.cotisationId,
|
||||
required this.paymentId,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cotisationId, paymentId];
|
||||
}
|
||||
|
||||
/// État pour la synchronisation en cours
|
||||
class SyncInProgress extends CotisationsState {
|
||||
final String message;
|
||||
|
||||
const SyncInProgress(this.message);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message];
|
||||
}
|
||||
|
||||
/// État pour la synchronisation terminée
|
||||
class SyncCompleted extends CotisationsState {
|
||||
final int itemsSynced;
|
||||
final DateTime syncTime;
|
||||
|
||||
const SyncCompleted({
|
||||
required this.itemsSynced,
|
||||
required this.syncTime,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [itemsSynced, syncTime];
|
||||
}
|
||||
|
||||
/// État pour l'export en cours
|
||||
class ExportInProgress extends CotisationsState {
|
||||
final String format;
|
||||
final int totalItems;
|
||||
|
||||
const ExportInProgress({
|
||||
required this.format,
|
||||
required this.totalItems,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [format, totalItems];
|
||||
}
|
||||
|
||||
/// État pour l'export terminé
|
||||
class ExportCompleted extends CotisationsState {
|
||||
final String format;
|
||||
final String filePath;
|
||||
final int itemsExported;
|
||||
|
||||
const ExportCompleted({
|
||||
required this.format,
|
||||
required this.filePath,
|
||||
required this.itemsExported,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [format, filePath, itemsExported];
|
||||
}
|
||||
|
||||
/// État pour les notifications programmées
|
||||
class NotificationsScheduled extends CotisationsState {
|
||||
final int notificationsCount;
|
||||
final List<String> cotisationIds;
|
||||
|
||||
const NotificationsScheduled({
|
||||
required this.notificationsCount,
|
||||
required this.cotisationIds,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [notificationsCount, cotisationIds];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user