feat: Implement BalanceRepository for group balance calculations feat: Create ExpenseRepository for managing expenses feat: Add services for handling expenses and storage operations fix: Update import paths for models in repositories and services refactor: Rename CountContent to AccountContent in HomePage chore: Add StorageService for image upload and management
113 lines
3.4 KiB
Dart
113 lines
3.4 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import '../models/expense.dart';
|
|
import '../services/error_service.dart';
|
|
|
|
class ExpenseRepository {
|
|
final FirebaseFirestore _firestore;
|
|
final ErrorService _errorService;
|
|
|
|
ExpenseRepository({
|
|
FirebaseFirestore? firestore,
|
|
ErrorService? errorService,
|
|
}) : _firestore = firestore ?? FirebaseFirestore.instance,
|
|
_errorService = errorService ?? ErrorService();
|
|
|
|
CollectionReference get _expensesCollection => _firestore.collection('expenses');
|
|
|
|
// Stream des dépenses d'un groupe
|
|
Stream<List<Expense>> getExpensesStream(String groupId) {
|
|
return _expensesCollection
|
|
.where('groupId', isEqualTo: groupId)
|
|
.where('isArchived', isEqualTo: false)
|
|
.orderBy('createdAt', descending: true)
|
|
.snapshots()
|
|
.map((snapshot) {
|
|
return snapshot.docs
|
|
.map((doc) => Expense.fromMap(doc.data() as Map<String, dynamic>, doc.id))
|
|
.toList();
|
|
}).handleError((error) {
|
|
_errorService.logError('ExpenseRepository', 'Erreur stream expenses: $error');
|
|
return <Expense>[];
|
|
});
|
|
}
|
|
|
|
// Créer une dépense
|
|
Future<String> createExpense(Expense expense) async {
|
|
try {
|
|
final docRef = await _expensesCollection.add(expense.toMap());
|
|
return docRef.id;
|
|
} catch (e) {
|
|
_errorService.logError('ExpenseRepository', 'Erreur création expense: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// Mettre à jour une dépense
|
|
Future<void> updateExpense(Expense expense) async {
|
|
try {
|
|
final updateData = expense.toMap();
|
|
updateData['editedAt'] = FieldValue.serverTimestamp();
|
|
updateData['isEdited'] = true;
|
|
|
|
await _expensesCollection.doc(expense.id).update(updateData);
|
|
} catch (e) {
|
|
_errorService.logError('ExpenseRepository', 'Erreur update expense: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// Supprimer une dépense
|
|
Future<void> deleteExpense(String expenseId) async {
|
|
try {
|
|
await _expensesCollection.doc(expenseId).delete();
|
|
} catch (e) {
|
|
_errorService.logError('ExpenseRepository', 'Erreur delete expense: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// Marquer un split comme payé
|
|
Future<void> markSplitAsPaid(String expenseId, String userId) async {
|
|
try {
|
|
await _firestore.runTransaction((transaction) async {
|
|
final expenseDoc = await transaction.get(_expensesCollection.doc(expenseId));
|
|
|
|
if (!expenseDoc.exists) {
|
|
throw Exception('Dépense non trouvée');
|
|
}
|
|
|
|
final expense = Expense.fromMap(
|
|
expenseDoc.data() as Map<String, dynamic>,
|
|
expenseDoc.id
|
|
);
|
|
|
|
final updatedSplits = expense.splits.map((split) {
|
|
if (split.userId == userId) {
|
|
return split.copyWith(isPaid: true, paidAt: DateTime.now());
|
|
}
|
|
return split;
|
|
}).toList();
|
|
|
|
transaction.update(expenseDoc.reference, {
|
|
'splits': updatedSplits.map((s) => s.toMap()).toList(),
|
|
});
|
|
});
|
|
} catch (e) {
|
|
_errorService.logError('ExpenseRepository', 'Erreur mark split paid: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// Archiver une dépense
|
|
Future<void> archiveExpense(String expenseId) async {
|
|
try {
|
|
await _expensesCollection.doc(expenseId).update({
|
|
'isArchived': true,
|
|
'archivedAt': FieldValue.serverTimestamp(),
|
|
});
|
|
} catch (e) {
|
|
_errorService.logError('ExpenseRepository', 'Erreur archive expense: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
} |