import 'dart:io'; import '../models/expense.dart'; import '../repositories/expense_repository.dart'; import 'error_service.dart'; import 'storage_service.dart'; // Pour upload des reçus class ExpenseService { final ExpenseRepository _expenseRepository; final ErrorService _errorService; final StorageService _storageService; ExpenseService({ required ExpenseRepository expenseRepository, ErrorService? errorService, StorageService? storageService, }) : _expenseRepository = expenseRepository, _errorService = errorService ?? ErrorService(), _storageService = storageService ?? StorageService(); // Création avec validation et upload d'image Future createExpenseWithValidation(Expense expense, File? receiptImage) async { try { // Validation métier _validateExpenseData(expense); // Upload du reçu si présent String? receiptUrl; if (receiptImage != null) { receiptUrl = await _storageService.uploadReceiptImage( expense.groupId, receiptImage, ); } // Créer l'expense avec l'URL du reçu final expenseWithReceipt = expense.copyWith(receiptUrl: receiptUrl); return await _expenseRepository.createExpense(expenseWithReceipt); } catch (e) { _errorService.logError('ExpenseService', 'Erreur création expense: $e'); rethrow; } } // Mise à jour avec validation Future updateExpenseWithValidation(Expense expense, File? newReceiptImage) async { try { _validateExpenseData(expense); // Gérer le nouvel upload si nécessaire String? receiptUrl = expense.receiptUrl; if (newReceiptImage != null) { receiptUrl = await _storageService.uploadReceiptImage( expense.groupId, newReceiptImage, ); } final expenseWithReceipt = expense.copyWith( receiptUrl: receiptUrl, editedAt: DateTime.now(), isEdited: true, ); await _expenseRepository.updateExpense(expenseWithReceipt); } catch (e) { _errorService.logError('ExpenseService', 'Erreur update expense: $e'); rethrow; } } // Validation des données void _validateExpenseData(Expense expense) { if (expense.description.trim().isEmpty) { throw Exception('La description est requise'); } if (expense.amount <= 0) { throw Exception('Le montant doit être positif'); } if (expense.splits.isEmpty) { throw Exception('Au moins un participant est requis'); } final totalSplits = expense.splits.fold(0.0, (sum, split) => sum + split.amount); if ((totalSplits - expense.amountInEur).abs() > 0.01) { throw Exception('La somme des répartitions ne correspond pas au montant total'); } } }