242 lines
5.6 KiB
Dart
242 lines
5.6 KiB
Dart
/// Entité métier Approbation Transaction
|
|
///
|
|
/// Représente une approbation dans le workflow financier multi-niveaux
|
|
library transaction_approval;
|
|
|
|
import 'package:equatable/equatable.dart';
|
|
|
|
/// Statut de l'approbation
|
|
enum ApprovalStatus {
|
|
/// En attente d'approbation
|
|
pending,
|
|
|
|
/// Approuvée (niveau 1)
|
|
approved,
|
|
|
|
/// Validée (niveau 2 - validation finale)
|
|
validated,
|
|
|
|
/// Rejetée
|
|
rejected,
|
|
|
|
/// Expirée (timeout)
|
|
expired,
|
|
|
|
/// Annulée
|
|
cancelled,
|
|
}
|
|
|
|
/// Niveau d'approbation requis selon montant
|
|
enum ApprovalLevel {
|
|
/// Aucune approbation requise (< seuil)
|
|
none,
|
|
|
|
/// Niveau 1 : Un approbateur requis
|
|
level1,
|
|
|
|
/// Niveau 2 : Deux approbateurs requis
|
|
level2,
|
|
|
|
/// Niveau 3 : Trois approbateurs requis (montants très élevés)
|
|
level3,
|
|
}
|
|
|
|
/// Type de transaction financière
|
|
enum TransactionType {
|
|
/// Cotisation/contribution
|
|
contribution,
|
|
|
|
/// Dépôt épargne
|
|
deposit,
|
|
|
|
/// Retrait épargne
|
|
withdrawal,
|
|
|
|
/// Transfert
|
|
transfer,
|
|
|
|
/// Dépense solidarité
|
|
solidarity,
|
|
|
|
/// Dépense événement
|
|
event,
|
|
|
|
/// Autre dépense
|
|
other,
|
|
}
|
|
|
|
/// Entité Approbation de Transaction
|
|
class TransactionApproval extends Equatable {
|
|
final String id;
|
|
final String transactionId;
|
|
final TransactionType transactionType;
|
|
final double amount;
|
|
final String currency;
|
|
final String requesterId;
|
|
final String requesterName;
|
|
final String? organizationId;
|
|
final ApprovalLevel requiredLevel;
|
|
final ApprovalStatus status;
|
|
final List<ApproverAction> approvers;
|
|
final String? rejectionReason;
|
|
final DateTime createdAt;
|
|
final DateTime? expiresAt;
|
|
final DateTime? completedAt;
|
|
final Map<String, dynamic>? metadata;
|
|
|
|
const TransactionApproval({
|
|
required this.id,
|
|
required this.transactionId,
|
|
required this.transactionType,
|
|
required this.amount,
|
|
this.currency = 'XOF',
|
|
required this.requesterId,
|
|
required this.requesterName,
|
|
this.organizationId,
|
|
required this.requiredLevel,
|
|
required this.status,
|
|
this.approvers = const [],
|
|
this.rejectionReason,
|
|
required this.createdAt,
|
|
this.expiresAt,
|
|
this.completedAt,
|
|
this.metadata,
|
|
});
|
|
|
|
/// Vérifie si l'approbation est en attente
|
|
bool get isPending => status == ApprovalStatus.pending;
|
|
|
|
/// Vérifie si l'approbation est complétée
|
|
bool get isCompleted =>
|
|
status == ApprovalStatus.validated ||
|
|
status == ApprovalStatus.rejected ||
|
|
status == ApprovalStatus.cancelled;
|
|
|
|
/// Vérifie si l'approbation est expirée
|
|
bool get isExpired {
|
|
if (expiresAt == null) return false;
|
|
return DateTime.now().isAfter(expiresAt!);
|
|
}
|
|
|
|
/// Nombre d'approbations reçues
|
|
int get approvalCount =>
|
|
approvers.where((a) => a.decision == ApprovalDecision.approved).length;
|
|
|
|
/// Nombre d'approbations requises
|
|
int get requiredApprovals {
|
|
switch (requiredLevel) {
|
|
case ApprovalLevel.none:
|
|
return 0;
|
|
case ApprovalLevel.level1:
|
|
return 1;
|
|
case ApprovalLevel.level2:
|
|
return 2;
|
|
case ApprovalLevel.level3:
|
|
return 3;
|
|
}
|
|
}
|
|
|
|
/// Vérifie si toutes les approbations sont reçues
|
|
bool get hasAllApprovals => approvalCount >= requiredApprovals;
|
|
|
|
/// Copie avec modifications
|
|
TransactionApproval copyWith({
|
|
String? id,
|
|
String? transactionId,
|
|
TransactionType? transactionType,
|
|
double? amount,
|
|
String? currency,
|
|
String? requesterId,
|
|
String? requesterName,
|
|
String? organizationId,
|
|
ApprovalLevel? requiredLevel,
|
|
ApprovalStatus? status,
|
|
List<ApproverAction>? approvers,
|
|
String? rejectionReason,
|
|
DateTime? createdAt,
|
|
DateTime? expiresAt,
|
|
DateTime? completedAt,
|
|
Map<String, dynamic>? metadata,
|
|
}) {
|
|
return TransactionApproval(
|
|
id: id ?? this.id,
|
|
transactionId: transactionId ?? this.transactionId,
|
|
transactionType: transactionType ?? this.transactionType,
|
|
amount: amount ?? this.amount,
|
|
currency: currency ?? this.currency,
|
|
requesterId: requesterId ?? this.requesterId,
|
|
requesterName: requesterName ?? this.requesterName,
|
|
organizationId: organizationId ?? this.organizationId,
|
|
requiredLevel: requiredLevel ?? this.requiredLevel,
|
|
status: status ?? this.status,
|
|
approvers: approvers ?? this.approvers,
|
|
rejectionReason: rejectionReason ?? this.rejectionReason,
|
|
createdAt: createdAt ?? this.createdAt,
|
|
expiresAt: expiresAt ?? this.expiresAt,
|
|
completedAt: completedAt ?? this.completedAt,
|
|
metadata: metadata ?? this.metadata,
|
|
);
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id,
|
|
transactionId,
|
|
transactionType,
|
|
amount,
|
|
currency,
|
|
requesterId,
|
|
requesterName,
|
|
organizationId,
|
|
requiredLevel,
|
|
status,
|
|
approvers,
|
|
rejectionReason,
|
|
createdAt,
|
|
expiresAt,
|
|
completedAt,
|
|
metadata,
|
|
];
|
|
}
|
|
|
|
/// Décision d'un approbateur
|
|
enum ApprovalDecision {
|
|
/// En attente
|
|
pending,
|
|
|
|
/// Approuvé
|
|
approved,
|
|
|
|
/// Rejeté
|
|
rejected,
|
|
}
|
|
|
|
/// Action d'un approbateur
|
|
class ApproverAction extends Equatable {
|
|
final String approverId;
|
|
final String approverName;
|
|
final String approverRole;
|
|
final ApprovalDecision decision;
|
|
final String? comment;
|
|
final DateTime? decidedAt;
|
|
|
|
const ApproverAction({
|
|
required this.approverId,
|
|
required this.approverName,
|
|
required this.approverRole,
|
|
required this.decision,
|
|
this.comment,
|
|
this.decidedAt,
|
|
});
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
approverId,
|
|
approverName,
|
|
approverRole,
|
|
decision,
|
|
comment,
|
|
decidedAt,
|
|
];
|
|
}
|