Files
unionflow-server-impl-quarkus/unionflow-mobile-apps/lib/features/analytics/domain/entities/kpi_trend.dart
2025-09-17 17:54:06 +00:00

352 lines
11 KiB
Dart

import 'package:equatable/equatable.dart';
import 'analytics_data.dart';
/// Point de données pour une tendance KPI
class PointDonnee extends Equatable {
const PointDonnee({
required this.date,
required this.valeur,
this.libelle,
this.anomalie = false,
this.prediction = false,
this.metadonnees,
});
final DateTime date;
final double valeur;
final String? libelle;
final bool anomalie;
final bool prediction;
final String? metadonnees;
@override
List<Object?> get props => [
date,
valeur,
libelle,
anomalie,
prediction,
metadonnees,
];
PointDonnee copyWith({
DateTime? date,
double? valeur,
String? libelle,
bool? anomalie,
bool? prediction,
String? metadonnees,
}) {
return PointDonnee(
date: date ?? this.date,
valeur: valeur ?? this.valeur,
libelle: libelle ?? this.libelle,
anomalie: anomalie ?? this.anomalie,
prediction: prediction ?? this.prediction,
metadonnees: metadonnees ?? this.metadonnees,
);
}
}
/// Entité représentant les tendances et évolutions d'un KPI
class KPITrend extends Equatable {
const KPITrend({
required this.id,
required this.typeMetrique,
required this.periodeAnalyse,
this.organisationId,
this.nomOrganisation,
required this.dateDebut,
required this.dateFin,
required this.pointsDonnees,
required this.valeurActuelle,
this.valeurMinimale,
this.valeurMaximale,
this.valeurMoyenne,
this.ecartType,
this.coefficientVariation,
this.tendanceGenerale,
this.coefficientCorrelation,
this.pourcentageEvolutionGlobale,
this.predictionProchainePeriode,
this.margeErreurPrediction,
this.seuilAlerteBas,
this.seuilAlerteHaut,
this.alerteActive = false,
this.typeAlerte,
this.messageAlerte,
this.configurationGraphique,
this.intervalleRegroupement,
this.formatDate,
this.dateDerniereMiseAJour,
this.frequenceMiseAJourMinutes,
});
final String id;
final TypeMetrique typeMetrique;
final PeriodeAnalyse periodeAnalyse;
final String? organisationId;
final String? nomOrganisation;
final DateTime dateDebut;
final DateTime dateFin;
final List<PointDonnee> pointsDonnees;
final double valeurActuelle;
final double? valeurMinimale;
final double? valeurMaximale;
final double? valeurMoyenne;
final double? ecartType;
final double? coefficientVariation;
final double? tendanceGenerale;
final double? coefficientCorrelation;
final double? pourcentageEvolutionGlobale;
final double? predictionProchainePeriode;
final double? margeErreurPrediction;
final double? seuilAlerteBas;
final double? seuilAlerteHaut;
final bool alerteActive;
final String? typeAlerte;
final String? messageAlerte;
final String? configurationGraphique;
final String? intervalleRegroupement;
final String? formatDate;
final DateTime? dateDerniereMiseAJour;
final int? frequenceMiseAJourMinutes;
/// Retourne le libellé de la métrique
String get libelleMetrique => typeMetrique.libelle;
/// Retourne l'unité de mesure
String get unite => typeMetrique.unite;
/// Retourne l'icône de la métrique
String get icone => typeMetrique.icone;
/// Retourne la couleur de la métrique
String get couleur => typeMetrique.couleur;
/// Vérifie si la tendance est positive
bool get isTendancePositive {
return tendanceGenerale != null && tendanceGenerale! > 0;
}
/// Vérifie si la tendance est négative
bool get isTendanceNegative {
return tendanceGenerale != null && tendanceGenerale! < 0;
}
/// Vérifie si la tendance est stable
bool get isTendanceStable {
return tendanceGenerale != null && tendanceGenerale! == 0;
}
/// Retourne la volatilité du KPI
String get volatilite {
if (coefficientVariation == null) return 'inconnue';
if (coefficientVariation! <= 0.1) return 'faible';
if (coefficientVariation! <= 0.3) return 'moyenne';
return 'élevée';
}
/// Vérifie si la prédiction est fiable
bool get isPredictionFiable {
return coefficientCorrelation != null && coefficientCorrelation! >= 0.7;
}
/// Retourne le nombre de points de données
int get nombrePointsDonnees => pointsDonnees.length;
/// Vérifie si des anomalies ont été détectées
bool get hasAnomalies {
return pointsDonnees.any((point) => point.anomalie);
}
/// Retourne les points d'anomalies
List<PointDonnee> get pointsAnomalies {
return pointsDonnees.where((point) => point.anomalie).toList();
}
/// Retourne les points de prédiction
List<PointDonnee> get pointsPredictions {
return pointsDonnees.where((point) => point.prediction).toList();
}
/// Formate la valeur actuelle
String get valeurActuelleFormatee {
switch (typeMetrique.typeValeur) {
case 'amount':
return '${valeurActuelle.toStringAsFixed(0)} ${unite}';
case 'percentage':
return '${valeurActuelle.toStringAsFixed(1)}${unite}';
case 'average':
return valeurActuelle.toStringAsFixed(1);
default:
return valeurActuelle.toStringAsFixed(0);
}
}
/// Formate l'évolution globale
String get evolutionGlobaleFormatee {
if (pourcentageEvolutionGlobale == null) return '';
final signe = pourcentageEvolutionGlobale! >= 0 ? '+' : '';
return '$signe${pourcentageEvolutionGlobale!.toStringAsFixed(1)}%';
}
/// Formate la prédiction
String get predictionFormatee {
if (predictionProchainePeriode == null) return '';
switch (typeMetrique.typeValeur) {
case 'amount':
return '${predictionProchainePeriode!.toStringAsFixed(0)} ${unite}';
case 'percentage':
return '${predictionProchainePeriode!.toStringAsFixed(1)}${unite}';
case 'average':
return predictionProchainePeriode!.toStringAsFixed(1);
default:
return predictionProchainePeriode!.toStringAsFixed(0);
}
}
/// Retourne la description de la tendance
String get descriptionTendance {
if (isTendancePositive) {
return 'Tendance à la hausse';
} else if (isTendanceNegative) {
return 'Tendance à la baisse';
} else {
return 'Tendance stable';
}
}
/// Retourne l'icône de la tendance
String get iconeTendance {
if (isTendancePositive) {
return 'trending_up';
} else if (isTendanceNegative) {
return 'trending_down';
} else {
return 'trending_flat';
}
}
/// Retourne la couleur de la tendance
String get couleurTendance {
if (isTendancePositive) {
return '#4CAF50'; // Vert
} else if (isTendanceNegative) {
return '#F44336'; // Rouge
} else {
return '#FF9800'; // Orange
}
}
/// Retourne le niveau de confiance de la prédiction
String get niveauConfiancePrediction {
if (coefficientCorrelation == null) return 'Inconnu';
if (coefficientCorrelation! >= 0.9) return 'Très élevé';
if (coefficientCorrelation! >= 0.7) return 'Élevé';
if (coefficientCorrelation! >= 0.5) return 'Moyen';
if (coefficientCorrelation! >= 0.3) return 'Faible';
return 'Très faible';
}
@override
List<Object?> get props => [
id,
typeMetrique,
periodeAnalyse,
organisationId,
nomOrganisation,
dateDebut,
dateFin,
pointsDonnees,
valeurActuelle,
valeurMinimale,
valeurMaximale,
valeurMoyenne,
ecartType,
coefficientVariation,
tendanceGenerale,
coefficientCorrelation,
pourcentageEvolutionGlobale,
predictionProchainePeriode,
margeErreurPrediction,
seuilAlerteBas,
seuilAlerteHaut,
alerteActive,
typeAlerte,
messageAlerte,
configurationGraphique,
intervalleRegroupement,
formatDate,
dateDerniereMiseAJour,
frequenceMiseAJourMinutes,
];
KPITrend copyWith({
String? id,
TypeMetrique? typeMetrique,
PeriodeAnalyse? periodeAnalyse,
String? organisationId,
String? nomOrganisation,
DateTime? dateDebut,
DateTime? dateFin,
List<PointDonnee>? pointsDonnees,
double? valeurActuelle,
double? valeurMinimale,
double? valeurMaximale,
double? valeurMoyenne,
double? ecartType,
double? coefficientVariation,
double? tendanceGenerale,
double? coefficientCorrelation,
double? pourcentageEvolutionGlobale,
double? predictionProchainePeriode,
double? margeErreurPrediction,
double? seuilAlerteBas,
double? seuilAlerteHaut,
bool? alerteActive,
String? typeAlerte,
String? messageAlerte,
String? configurationGraphique,
String? intervalleRegroupement,
String? formatDate,
DateTime? dateDerniereMiseAJour,
int? frequenceMiseAJourMinutes,
}) {
return KPITrend(
id: id ?? this.id,
typeMetrique: typeMetrique ?? this.typeMetrique,
periodeAnalyse: periodeAnalyse ?? this.periodeAnalyse,
organisationId: organisationId ?? this.organisationId,
nomOrganisation: nomOrganisation ?? this.nomOrganisation,
dateDebut: dateDebut ?? this.dateDebut,
dateFin: dateFin ?? this.dateFin,
pointsDonnees: pointsDonnees ?? this.pointsDonnees,
valeurActuelle: valeurActuelle ?? this.valeurActuelle,
valeurMinimale: valeurMinimale ?? this.valeurMinimale,
valeurMaximale: valeurMaximale ?? this.valeurMaximale,
valeurMoyenne: valeurMoyenne ?? this.valeurMoyenne,
ecartType: ecartType ?? this.ecartType,
coefficientVariation: coefficientVariation ?? this.coefficientVariation,
tendanceGenerale: tendanceGenerale ?? this.tendanceGenerale,
coefficientCorrelation: coefficientCorrelation ?? this.coefficientCorrelation,
pourcentageEvolutionGlobale: pourcentageEvolutionGlobale ?? this.pourcentageEvolutionGlobale,
predictionProchainePeriode: predictionProchainePeriode ?? this.predictionProchainePeriode,
margeErreurPrediction: margeErreurPrediction ?? this.margeErreurPrediction,
seuilAlerteBas: seuilAlerteBas ?? this.seuilAlerteBas,
seuilAlerteHaut: seuilAlerteHaut ?? this.seuilAlerteHaut,
alerteActive: alerteActive ?? this.alerteActive,
typeAlerte: typeAlerte ?? this.typeAlerte,
messageAlerte: messageAlerte ?? this.messageAlerte,
configurationGraphique: configurationGraphique ?? this.configurationGraphique,
intervalleRegroupement: intervalleRegroupement ?? this.intervalleRegroupement,
formatDate: formatDate ?? this.formatDate,
dateDerniereMiseAJour: dateDerniereMiseAJour ?? this.dateDerniereMiseAJour,
frequenceMiseAJourMinutes: frequenceMiseAJourMinutes ?? this.frequenceMiseAJourMinutes,
);
}
}