feat: Add User and UserBalance models with serialization methods

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
This commit is contained in:
Dayron
2025-10-21 16:02:58 +02:00
parent 62eb434548
commit 4edbd1cf34
60 changed files with 1973 additions and 342 deletions

130
lib/models/settlement.dart Normal file
View File

@@ -0,0 +1,130 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';
class Settlement extends Equatable {
final String fromUserId;
final String fromUserName;
final String toUserId;
final String toUserName;
final double amount;
final bool isCompleted;
final DateTime? completedAt;
const Settlement({
required this.fromUserId,
required this.fromUserName,
required this.toUserId,
required this.toUserName,
required this.amount,
this.isCompleted = false,
this.completedAt,
});
// Constructeur factory pour créer depuis une Map
factory Settlement.fromMap(Map<String, dynamic> map) {
return Settlement(
fromUserId: map['fromUserId'] ?? '',
fromUserName: map['fromUserName'] ?? '',
toUserId: map['toUserId'] ?? '',
toUserName: map['toUserName'] ?? '',
amount: (map['amount'] as num?)?.toDouble() ?? 0.0,
isCompleted: map['isCompleted'] ?? false,
completedAt: map['completedAt'] != null
? _parseDateTime(map['completedAt'])
: null,
);
}
// Convertir en Map pour la sérialisation
Map<String, dynamic> toMap() {
return {
'fromUserId': fromUserId,
'fromUserName': fromUserName,
'toUserId': toUserId,
'toUserName': toUserName,
'amount': amount,
'isCompleted': isCompleted,
'completedAt': completedAt != null
? Timestamp.fromDate(completedAt!)
: null,
};
}
// Méthode copyWith étendue pour créer une copie modifiée
Settlement copyWith({
String? fromUserId,
String? fromUserName,
String? toUserId,
String? toUserName,
double? amount,
bool? isCompleted,
DateTime? completedAt,
}) {
return Settlement(
fromUserId: fromUserId ?? this.fromUserId,
fromUserName: fromUserName ?? this.fromUserName,
toUserId: toUserId ?? this.toUserId,
toUserName: toUserName ?? this.toUserName,
amount: amount ?? this.amount,
isCompleted: isCompleted ?? this.isCompleted,
completedAt: completedAt ?? this.completedAt,
);
}
// Constructeur factory pour marquer comme complété
factory Settlement.completed(Settlement settlement) {
return settlement.copyWith(
isCompleted: true,
completedAt: DateTime.now(),
);
}
// Helper pour parser les dates de différents formats
static DateTime _parseDateTime(dynamic value) {
if (value is Timestamp) return value.toDate();
if (value is String) return DateTime.parse(value);
if (value is DateTime) return value;
if (value is int) return DateTime.fromMillisecondsSinceEpoch(value);
return DateTime.now();
}
// Getters utilitaires pour la logique métier
bool get isPending => !isCompleted;
String get formattedAmount => '${amount.toStringAsFixed(2)}';
String get description => '$fromUserName doit ${formattedAmount} à $toUserName';
String get shortDescription => '$fromUserName$toUserName';
String get status => isCompleted ? 'Payé' : 'En attente';
// Durée depuis la completion (si applicable)
Duration? get timeSinceCompletion {
if (completedAt == null) return null;
return DateTime.now().difference(completedAt!);
}
// Formatage de la date de completion
String get formattedCompletedAt {
if (completedAt == null) return 'Non payé';
return 'Payé le ${completedAt!.day}/${completedAt!.month}/${completedAt!.year}';
}
// Méthodes de validation
bool get isValid =>
fromUserId.isNotEmpty &&
toUserId.isNotEmpty &&
fromUserId != toUserId &&
amount > 0;
bool get isSelfSettlement => fromUserId == toUserId;
@override
List<Object?> get props => [fromUserId, toUserId, amount, isCompleted];
@override
String toString() {
return 'Settlement(${shortDescription}: ${formattedAmount}, status: $status)';
}
}