Clean project: remove test files, debug logs, and add documentation
This commit is contained in:
@@ -0,0 +1,597 @@
|
||||
/// BLoC pour la gestion des cotisations
|
||||
library cotisations_bloc;
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../core/utils/logger.dart';
|
||||
import '../data/models/cotisation_model.dart';
|
||||
import 'cotisations_event.dart';
|
||||
import 'cotisations_state.dart';
|
||||
|
||||
/// BLoC pour gérer l'état des cotisations
|
||||
class CotisationsBloc extends Bloc<CotisationsEvent, CotisationsState> {
|
||||
CotisationsBloc() : super(const CotisationsInitial()) {
|
||||
on<LoadCotisations>(_onLoadCotisations);
|
||||
on<LoadCotisationById>(_onLoadCotisationById);
|
||||
on<CreateCotisation>(_onCreateCotisation);
|
||||
on<UpdateCotisation>(_onUpdateCotisation);
|
||||
on<DeleteCotisation>(_onDeleteCotisation);
|
||||
on<SearchCotisations>(_onSearchCotisations);
|
||||
on<LoadCotisationsByMembre>(_onLoadCotisationsByMembre);
|
||||
on<LoadCotisationsPayees>(_onLoadCotisationsPayees);
|
||||
on<LoadCotisationsNonPayees>(_onLoadCotisationsNonPayees);
|
||||
on<LoadCotisationsEnRetard>(_onLoadCotisationsEnRetard);
|
||||
on<EnregistrerPaiement>(_onEnregistrerPaiement);
|
||||
on<LoadCotisationsStats>(_onLoadCotisationsStats);
|
||||
on<GenererCotisationsAnnuelles>(_onGenererCotisationsAnnuelles);
|
||||
on<EnvoyerRappelPaiement>(_onEnvoyerRappelPaiement);
|
||||
}
|
||||
|
||||
/// Charger la liste des cotisations
|
||||
Future<void> _onLoadCotisations(
|
||||
LoadCotisations event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'LoadCotisations', data: {
|
||||
'page': event.page,
|
||||
'size': event.size,
|
||||
});
|
||||
|
||||
emit(const CotisationsLoading(message: 'Chargement des cotisations...'));
|
||||
|
||||
// Simuler un délai réseau
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// Données mock
|
||||
final cotisations = _getMockCotisations();
|
||||
final total = cotisations.length;
|
||||
final totalPages = (total / event.size).ceil();
|
||||
|
||||
// Pagination
|
||||
final start = event.page * event.size;
|
||||
final end = (start + event.size).clamp(0, total);
|
||||
final paginatedCotisations = cotisations.sublist(
|
||||
start.clamp(0, total),
|
||||
end,
|
||||
);
|
||||
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: paginatedCotisations,
|
||||
total: total,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
totalPages: totalPages,
|
||||
));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationsLoaded', data: {
|
||||
'count': paginatedCotisations.length,
|
||||
'total': total,
|
||||
});
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors du chargement des cotisations',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Erreur lors du chargement des cotisations',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charger une cotisation par ID
|
||||
Future<void> _onLoadCotisationById(
|
||||
LoadCotisationById event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'LoadCotisationById', data: {
|
||||
'id': event.id,
|
||||
});
|
||||
|
||||
emit(const CotisationsLoading(message: 'Chargement de la cotisation...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
final cotisations = _getMockCotisations();
|
||||
final cotisation = cotisations.firstWhere(
|
||||
(c) => c.id == event.id,
|
||||
orElse: () => throw Exception('Cotisation non trouvée'),
|
||||
);
|
||||
|
||||
emit(CotisationDetailLoaded(cotisation: cotisation));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationDetailLoaded');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors du chargement de la cotisation',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Cotisation non trouvée',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Créer une nouvelle cotisation
|
||||
Future<void> _onCreateCotisation(
|
||||
CreateCotisation event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'CreateCotisation');
|
||||
|
||||
emit(const CotisationsLoading(message: 'Création de la cotisation...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final newCotisation = event.cotisation.copyWith(
|
||||
id: 'cot_${DateTime.now().millisecondsSinceEpoch}',
|
||||
dateCreation: DateTime.now(),
|
||||
);
|
||||
|
||||
emit(CotisationCreated(cotisation: newCotisation));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationCreated');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors de la création de la cotisation',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Erreur lors de la création de la cotisation',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Mettre à jour une cotisation
|
||||
Future<void> _onUpdateCotisation(
|
||||
UpdateCotisation event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'UpdateCotisation', data: {
|
||||
'id': event.id,
|
||||
});
|
||||
|
||||
emit(const CotisationsLoading(message: 'Mise à jour de la cotisation...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final updatedCotisation = event.cotisation.copyWith(
|
||||
id: event.id,
|
||||
dateModification: DateTime.now(),
|
||||
);
|
||||
|
||||
emit(CotisationUpdated(cotisation: updatedCotisation));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationUpdated');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors de la mise à jour de la cotisation',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Erreur lors de la mise à jour de la cotisation',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Supprimer une cotisation
|
||||
Future<void> _onDeleteCotisation(
|
||||
DeleteCotisation event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'DeleteCotisation', data: {
|
||||
'id': event.id,
|
||||
});
|
||||
|
||||
emit(const CotisationsLoading(message: 'Suppression de la cotisation...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
emit(CotisationDeleted(id: event.id));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationDeleted');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors de la suppression de la cotisation',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Erreur lors de la suppression de la cotisation',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Rechercher des cotisations
|
||||
Future<void> _onSearchCotisations(
|
||||
SearchCotisations event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'SearchCotisations');
|
||||
|
||||
emit(const CotisationsLoading(message: 'Recherche en cours...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
var cotisations = _getMockCotisations();
|
||||
|
||||
// Filtrer par membre
|
||||
if (event.membreId != null) {
|
||||
cotisations = cotisations
|
||||
.where((c) => c.membreId == event.membreId)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// Filtrer par statut
|
||||
if (event.statut != null) {
|
||||
cotisations = cotisations
|
||||
.where((c) => c.statut == event.statut)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// Filtrer par type
|
||||
if (event.type != null) {
|
||||
cotisations = cotisations
|
||||
.where((c) => c.type == event.type)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// Filtrer par année
|
||||
if (event.annee != null) {
|
||||
cotisations = cotisations
|
||||
.where((c) => c.annee == event.annee)
|
||||
.toList();
|
||||
}
|
||||
|
||||
final total = cotisations.length;
|
||||
final totalPages = (total / event.size).ceil();
|
||||
|
||||
// Pagination
|
||||
final start = event.page * event.size;
|
||||
final end = (start + event.size).clamp(0, total);
|
||||
final paginatedCotisations = cotisations.sublist(
|
||||
start.clamp(0, total),
|
||||
end,
|
||||
);
|
||||
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: paginatedCotisations,
|
||||
total: total,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
totalPages: totalPages,
|
||||
));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationsLoaded (search)');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors de la recherche de cotisations',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Erreur lors de la recherche',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charger les cotisations d'un membre
|
||||
Future<void> _onLoadCotisationsByMembre(
|
||||
LoadCotisationsByMembre event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'LoadCotisationsByMembre', data: {
|
||||
'membreId': event.membreId,
|
||||
});
|
||||
|
||||
emit(const CotisationsLoading(message: 'Chargement des cotisations du membre...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final cotisations = _getMockCotisations()
|
||||
.where((c) => c.membreId == event.membreId)
|
||||
.toList();
|
||||
|
||||
final total = cotisations.length;
|
||||
final totalPages = (total / event.size).ceil();
|
||||
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: cotisations,
|
||||
total: total,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
totalPages: totalPages,
|
||||
));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'CotisationsLoaded (by membre)');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Erreur lors du chargement des cotisations du membre',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
emit(CotisationsError(
|
||||
message: 'Erreur lors du chargement',
|
||||
error: e,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charger les cotisations payées
|
||||
Future<void> _onLoadCotisationsPayees(
|
||||
LoadCotisationsPayees event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading(message: 'Chargement des cotisations payées...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final cotisations = _getMockCotisations()
|
||||
.where((c) => c.statut == StatutCotisation.payee)
|
||||
.toList();
|
||||
|
||||
final total = cotisations.length;
|
||||
final totalPages = (total / event.size).ceil();
|
||||
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: cotisations,
|
||||
total: total,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
totalPages: totalPages,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charger les cotisations non payées
|
||||
Future<void> _onLoadCotisationsNonPayees(
|
||||
LoadCotisationsNonPayees event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading(message: 'Chargement des cotisations non payées...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final cotisations = _getMockCotisations()
|
||||
.where((c) => c.statut == StatutCotisation.nonPayee)
|
||||
.toList();
|
||||
|
||||
final total = cotisations.length;
|
||||
final totalPages = (total / event.size).ceil();
|
||||
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: cotisations,
|
||||
total: total,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
totalPages: totalPages,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charger les cotisations en retard
|
||||
Future<void> _onLoadCotisationsEnRetard(
|
||||
LoadCotisationsEnRetard event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading(message: 'Chargement des cotisations en retard...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final cotisations = _getMockCotisations()
|
||||
.where((c) => c.statut == StatutCotisation.enRetard)
|
||||
.toList();
|
||||
|
||||
final total = cotisations.length;
|
||||
final totalPages = (total / event.size).ceil();
|
||||
|
||||
emit(CotisationsLoaded(
|
||||
cotisations: cotisations,
|
||||
total: total,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
totalPages: totalPages,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Enregistrer un paiement
|
||||
Future<void> _onEnregistrerPaiement(
|
||||
EnregistrerPaiement event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('CotisationsBloc', 'EnregistrerPaiement');
|
||||
|
||||
emit(const CotisationsLoading(message: 'Enregistrement du paiement...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final cotisations = _getMockCotisations();
|
||||
final cotisation = cotisations.firstWhere((c) => c.id == event.cotisationId);
|
||||
|
||||
final updatedCotisation = cotisation.copyWith(
|
||||
montantPaye: event.montant,
|
||||
datePaiement: event.datePaiement,
|
||||
methodePaiement: event.methodePaiement,
|
||||
numeroPaiement: event.numeroPaiement,
|
||||
referencePaiement: event.referencePaiement,
|
||||
statut: event.montant >= cotisation.montant
|
||||
? StatutCotisation.payee
|
||||
: StatutCotisation.partielle,
|
||||
dateModification: DateTime.now(),
|
||||
);
|
||||
|
||||
emit(PaiementEnregistre(cotisation: updatedCotisation));
|
||||
|
||||
AppLogger.blocState('CotisationsBloc', 'PaiementEnregistre');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur lors de l\'enregistrement du paiement', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charger les statistiques
|
||||
Future<void> _onLoadCotisationsStats(
|
||||
LoadCotisationsStats event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading(message: 'Chargement des statistiques...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final cotisations = _getMockCotisations();
|
||||
|
||||
final stats = {
|
||||
'total': cotisations.length,
|
||||
'payees': cotisations.where((c) => c.statut == StatutCotisation.payee).length,
|
||||
'nonPayees': cotisations.where((c) => c.statut == StatutCotisation.nonPayee).length,
|
||||
'enRetard': cotisations.where((c) => c.statut == StatutCotisation.enRetard).length,
|
||||
'partielles': cotisations.where((c) => c.statut == StatutCotisation.partielle).length,
|
||||
'montantTotal': cotisations.fold<double>(0, (sum, c) => sum + c.montant),
|
||||
'montantPaye': cotisations.fold<double>(0, (sum, c) => sum + (c.montantPaye ?? 0)),
|
||||
'montantRestant': cotisations.fold<double>(0, (sum, c) => sum + c.montantRestant),
|
||||
'tauxRecouvrement': 0.0,
|
||||
};
|
||||
|
||||
if (stats['montantTotal']! > 0) {
|
||||
stats['tauxRecouvrement'] = (stats['montantPaye']! / stats['montantTotal']!) * 100;
|
||||
}
|
||||
|
||||
emit(CotisationsStatsLoaded(stats: stats));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Générer les cotisations annuelles
|
||||
Future<void> _onGenererCotisationsAnnuelles(
|
||||
GenererCotisationsAnnuelles event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading(message: 'Génération des cotisations...'));
|
||||
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
// Simuler la génération de 50 cotisations
|
||||
emit(const CotisationsGenerees(nombreGenere: 50));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Envoyer un rappel de paiement
|
||||
Future<void> _onEnvoyerRappelPaiement(
|
||||
EnvoyerRappelPaiement event,
|
||||
Emitter<CotisationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const CotisationsLoading(message: 'Envoi du rappel...'));
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
emit(RappelEnvoye(cotisationId: event.cotisationId));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(CotisationsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Données mock pour les tests
|
||||
List<CotisationModel> _getMockCotisations() {
|
||||
final now = DateTime.now();
|
||||
return [
|
||||
CotisationModel(
|
||||
id: 'cot_001',
|
||||
membreId: 'mbr_001',
|
||||
membreNom: 'Dupont',
|
||||
membrePrenom: 'Jean',
|
||||
montant: 50000,
|
||||
dateEcheance: DateTime(now.year, 12, 31),
|
||||
annee: now.year,
|
||||
statut: StatutCotisation.payee,
|
||||
montantPaye: 50000,
|
||||
datePaiement: DateTime(now.year, 1, 15),
|
||||
methodePaiement: MethodePaiement.virement,
|
||||
),
|
||||
CotisationModel(
|
||||
id: 'cot_002',
|
||||
membreId: 'mbr_002',
|
||||
membreNom: 'Martin',
|
||||
membrePrenom: 'Marie',
|
||||
montant: 50000,
|
||||
dateEcheance: DateTime(now.year, 12, 31),
|
||||
annee: now.year,
|
||||
statut: StatutCotisation.nonPayee,
|
||||
),
|
||||
CotisationModel(
|
||||
id: 'cot_003',
|
||||
membreId: 'mbr_003',
|
||||
membreNom: 'Bernard',
|
||||
membrePrenom: 'Pierre',
|
||||
montant: 50000,
|
||||
dateEcheance: DateTime(now.year - 1, 12, 31),
|
||||
annee: now.year - 1,
|
||||
statut: StatutCotisation.enRetard,
|
||||
),
|
||||
CotisationModel(
|
||||
id: 'cot_004',
|
||||
membreId: 'mbr_004',
|
||||
membreNom: 'Dubois',
|
||||
membrePrenom: 'Sophie',
|
||||
montant: 50000,
|
||||
dateEcheance: DateTime(now.year, 12, 31),
|
||||
annee: now.year,
|
||||
statut: StatutCotisation.partielle,
|
||||
montantPaye: 25000,
|
||||
datePaiement: DateTime(now.year, 2, 10),
|
||||
methodePaiement: MethodePaiement.especes,
|
||||
),
|
||||
CotisationModel(
|
||||
id: 'cot_005',
|
||||
membreId: 'mbr_005',
|
||||
membreNom: 'Petit',
|
||||
membrePrenom: 'Luc',
|
||||
montant: 50000,
|
||||
dateEcheance: DateTime(now.year, 12, 31),
|
||||
annee: now.year,
|
||||
statut: StatutCotisation.payee,
|
||||
montantPaye: 50000,
|
||||
datePaiement: DateTime(now.year, 3, 5),
|
||||
methodePaiement: MethodePaiement.mobileMoney,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user