feat(unionflow): ajout Spec-Kit, constitution, mission mutuelles
- Config Spec-Kit pour Spec-Driven Development - CONSTITUTION.md + .specify/memory/constitution.md - Commandes Cursor /speckit.*, règles projet - Mission: associations + mutuelles d'épargne et de financement - .gitignore: versionner config spec-kit unionflow Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
/// Repository pour la gestion des cotisations via l'API backend
|
||||
library contribution_repository;
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import '../models/contribution_model.dart';
|
||||
|
||||
/// Repository des cotisations - appels API réels vers /api/cotisations
|
||||
class ContributionRepository {
|
||||
final Dio _dio;
|
||||
static const String _baseUrl = '/api/cotisations';
|
||||
|
||||
ContributionRepository(this._dio);
|
||||
|
||||
/// Récupère la liste des cotisations avec pagination
|
||||
Future<ContributionPageResult> getCotisations({
|
||||
int page = 0,
|
||||
int size = 20,
|
||||
String? membreId,
|
||||
String? statut,
|
||||
String? type,
|
||||
int? annee,
|
||||
}) async {
|
||||
final queryParams = <String, dynamic>{
|
||||
'page': page,
|
||||
'size': size,
|
||||
};
|
||||
if (membreId != null) queryParams['membreId'] = membreId;
|
||||
if (statut != null) queryParams['statut'] = statut;
|
||||
if (type != null) queryParams['type'] = type;
|
||||
if (annee != null) queryParams['annee'] = annee;
|
||||
|
||||
final response = await _dio.get(
|
||||
_baseUrl,
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final data = response.data;
|
||||
if (data is List) {
|
||||
final contributions = data
|
||||
.map((json) => ContributionModel.fromJson(json as Map<String, dynamic>))
|
||||
.toList();
|
||||
return ContributionPageResult(
|
||||
contributions: contributions,
|
||||
total: contributions.length,
|
||||
page: page,
|
||||
size: size,
|
||||
totalPages: 1,
|
||||
);
|
||||
} else if (data is Map<String, dynamic>) {
|
||||
final List<dynamic> content = data['content'] ?? data['items'] ?? [];
|
||||
final contributions = content
|
||||
.map((json) => ContributionModel.fromJson(json as Map<String, dynamic>))
|
||||
.toList();
|
||||
return ContributionPageResult(
|
||||
contributions: contributions,
|
||||
total: data['totalElements'] ?? data['total'] ?? contributions.length,
|
||||
page: data['number'] ?? page,
|
||||
size: data['size'] ?? size,
|
||||
totalPages: data['totalPages'] ?? 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
throw Exception('Erreur lors de la récupération des cotisations: ${response.statusCode}');
|
||||
}
|
||||
|
||||
/// Récupère une cotisation par ID
|
||||
Future<ContributionModel> getCotisationById(String id) async {
|
||||
final response = await _dio.get('$_baseUrl/$id');
|
||||
if (response.statusCode == 200) {
|
||||
return ContributionModel.fromJson(response.data as Map<String, dynamic>);
|
||||
}
|
||||
throw Exception('Cotisation non trouvée');
|
||||
}
|
||||
|
||||
/// Crée une nouvelle cotisation
|
||||
Future<ContributionModel> createCotisation(ContributionModel contribution) async {
|
||||
final response = await _dio.post(_baseUrl, data: contribution.toJson());
|
||||
if (response.statusCode == 201 || response.statusCode == 200) {
|
||||
return ContributionModel.fromJson(response.data as Map<String, dynamic>);
|
||||
}
|
||||
throw Exception('Erreur lors de la création: ${response.statusCode}');
|
||||
}
|
||||
|
||||
/// Met à jour une cotisation
|
||||
Future<ContributionModel> updateCotisation(String id, ContributionModel contribution) async {
|
||||
final response = await _dio.put('$_baseUrl/$id', data: contribution.toJson());
|
||||
if (response.statusCode == 200) {
|
||||
return ContributionModel.fromJson(response.data as Map<String, dynamic>);
|
||||
}
|
||||
throw Exception('Erreur lors de la mise à jour: ${response.statusCode}');
|
||||
}
|
||||
|
||||
/// Supprime une cotisation
|
||||
Future<void> deleteCotisation(String id) async {
|
||||
final response = await _dio.delete('$_baseUrl/$id');
|
||||
if (response.statusCode != 200 && response.statusCode != 204) {
|
||||
throw Exception('Erreur lors de la suppression: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
/// Enregistre un paiement
|
||||
Future<ContributionModel> enregistrerPaiement(
|
||||
String cotisationId, {
|
||||
required double montant,
|
||||
required DateTime datePaiement,
|
||||
required String methodePaiement,
|
||||
String? numeroPaiement,
|
||||
String? referencePaiement,
|
||||
}) async {
|
||||
final response = await _dio.post(
|
||||
'$_baseUrl/$cotisationId/paiement',
|
||||
data: {
|
||||
'montant': montant,
|
||||
'datePaiement': datePaiement.toIso8601String(),
|
||||
'methodePaiement': methodePaiement,
|
||||
if (numeroPaiement != null) 'numeroPaiement': numeroPaiement,
|
||||
if (referencePaiement != null) 'referencePaiement': referencePaiement,
|
||||
},
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return ContributionModel.fromJson(response.data as Map<String, dynamic>);
|
||||
}
|
||||
throw Exception('Erreur lors de l\'enregistrement du paiement: ${response.statusCode}');
|
||||
}
|
||||
|
||||
/// Récupère les statistiques des cotisations
|
||||
Future<Map<String, dynamic>> getStatistiques() async {
|
||||
final response = await _dio.get('$_baseUrl/statistiques');
|
||||
if (response.statusCode == 200) {
|
||||
return response.data as Map<String, dynamic>;
|
||||
}
|
||||
throw Exception('Erreur lors de la récupération des statistiques');
|
||||
}
|
||||
|
||||
/// Envoie un rappel de paiement
|
||||
Future<void> envoyerRappel(String cotisationId) async {
|
||||
final response = await _dio.post('$_baseUrl/$cotisationId/rappel');
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Erreur lors de l\'envoi du rappel');
|
||||
}
|
||||
}
|
||||
|
||||
/// Génère les cotisations annuelles
|
||||
Future<int> genererCotisationsAnnuelles(int annee) async {
|
||||
final response = await _dio.post(
|
||||
'$_baseUrl/generer',
|
||||
data: {'annee': annee},
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
return response.data['nombreGenere'] ?? 0;
|
||||
}
|
||||
throw Exception('Erreur lors de la génération');
|
||||
}
|
||||
}
|
||||
|
||||
/// Résultat paginé de cotisations
|
||||
class ContributionPageResult {
|
||||
final List<ContributionModel> contributions;
|
||||
final int total;
|
||||
final int page;
|
||||
final int size;
|
||||
final int totalPages;
|
||||
|
||||
const ContributionPageResult({
|
||||
required this.contributions,
|
||||
required this.total,
|
||||
required this.page,
|
||||
required this.size,
|
||||
required this.totalPages,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user