204 Zeilen
6.8 KiB
Python
204 Zeilen
6.8 KiB
Python
"""
|
|
Report Value Object - Strukturierte Berichte für Analytics
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime, timedelta
|
|
from typing import List, Dict, Any, Optional
|
|
from enum import Enum
|
|
|
|
|
|
class ReportType(Enum):
|
|
"""Typen von verfügbaren Berichten"""
|
|
DAILY = "daily"
|
|
WEEKLY = "weekly"
|
|
MONTHLY = "monthly"
|
|
CUSTOM = "custom"
|
|
REAL_TIME = "real_time"
|
|
|
|
|
|
class MetricType(Enum):
|
|
"""Typen von Metriken in Berichten"""
|
|
SUCCESS_RATE = "success_rate"
|
|
ERROR_RATE = "error_rate"
|
|
AVG_DURATION = "avg_duration"
|
|
TOTAL_ACCOUNTS = "total_accounts"
|
|
ACCOUNTS_PER_HOUR = "accounts_per_hour"
|
|
RETRY_RATE = "retry_rate"
|
|
RECOVERY_RATE = "recovery_rate"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Metric:
|
|
"""Einzelne Metrik im Bericht"""
|
|
name: str
|
|
value: float
|
|
unit: str
|
|
trend: float = 0.0 # Prozentuale Veränderung zum Vorperiode
|
|
|
|
@property
|
|
def is_improving(self) -> bool:
|
|
"""Prüft ob sich die Metrik verbessert"""
|
|
positive_metrics = ["success_rate", "recovery_rate", "accounts_per_hour"]
|
|
if self.name in positive_metrics:
|
|
return self.trend > 0
|
|
return self.trend < 0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class PlatformStats:
|
|
"""Statistiken für eine spezifische Plattform"""
|
|
platform: str
|
|
total_attempts: int
|
|
successful_accounts: int
|
|
failed_attempts: int
|
|
avg_duration_seconds: float
|
|
error_distribution: Dict[str, int]
|
|
|
|
@property
|
|
def success_rate(self) -> float:
|
|
"""Berechnet die Erfolgsrate"""
|
|
if self.total_attempts > 0:
|
|
return self.successful_accounts / self.total_attempts
|
|
return 0.0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TimeSeriesData:
|
|
"""Zeitreihen-Daten für Graphen"""
|
|
timestamps: List[datetime]
|
|
values: List[float]
|
|
label: str
|
|
|
|
def get_average(self) -> float:
|
|
"""Berechnet den Durchschnitt der Werte"""
|
|
if self.values:
|
|
return sum(self.values) / len(self.values)
|
|
return 0.0
|
|
|
|
def get_trend(self) -> float:
|
|
"""Berechnet den Trend (vereinfacht: Vergleich erste/letzte Hälfte)"""
|
|
if len(self.values) < 2:
|
|
return 0.0
|
|
mid = len(self.values) // 2
|
|
first_half_avg = sum(self.values[:mid]) / mid
|
|
second_half_avg = sum(self.values[mid:]) / (len(self.values) - mid)
|
|
if first_half_avg > 0:
|
|
return ((second_half_avg - first_half_avg) / first_half_avg) * 100
|
|
return 0.0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Report:
|
|
"""
|
|
Strukturierter Bericht für Analytics.
|
|
Frozen dataclass macht es unveränderlich (Value Object).
|
|
"""
|
|
|
|
report_id: str
|
|
report_type: ReportType
|
|
start_date: datetime
|
|
end_date: datetime
|
|
generated_at: datetime
|
|
|
|
# Zusammenfassende Metriken
|
|
total_accounts_created: int
|
|
total_attempts: int
|
|
overall_success_rate: float
|
|
avg_creation_time: float # in Sekunden
|
|
|
|
# Detaillierte Metriken
|
|
metrics: List[Metric]
|
|
platform_stats: List[PlatformStats]
|
|
error_summaries: List[Dict[str, Any]] # ErrorSummary als Dict
|
|
|
|
# Zeitreihen-Daten
|
|
success_rate_timeline: Optional[TimeSeriesData] = None
|
|
creation_rate_timeline: Optional[TimeSeriesData] = None
|
|
error_rate_timeline: Optional[TimeSeriesData] = None
|
|
|
|
# Top-Erkenntnisse
|
|
insights: List[str] = field(default_factory=list)
|
|
recommendations: List[str] = field(default_factory=list)
|
|
|
|
def __post_init__(self):
|
|
"""Validierung der Report-Daten"""
|
|
if self.start_date > self.end_date:
|
|
raise ValueError("Start date kann nicht nach end date liegen")
|
|
if not 0.0 <= self.overall_success_rate <= 1.0:
|
|
raise ValueError("Success rate muss zwischen 0.0 und 1.0 liegen")
|
|
if self.avg_creation_time < 0:
|
|
raise ValueError("Average creation time kann nicht negativ sein")
|
|
|
|
@property
|
|
def duration(self) -> timedelta:
|
|
"""Dauer des Berichtszeitraums"""
|
|
return self.end_date - self.start_date
|
|
|
|
@property
|
|
def accounts_per_day(self) -> float:
|
|
"""Durchschnittliche Accounts pro Tag"""
|
|
days = self.duration.days or 1
|
|
return self.total_accounts_created / days
|
|
|
|
def get_metric(self, metric_type: MetricType) -> Optional[Metric]:
|
|
"""Holt eine spezifische Metrik"""
|
|
for metric in self.metrics:
|
|
if metric.name == metric_type.value:
|
|
return metric
|
|
return None
|
|
|
|
def get_platform_stats(self, platform: str) -> Optional[PlatformStats]:
|
|
"""Holt Statistiken für eine spezifische Plattform"""
|
|
for stats in self.platform_stats:
|
|
if stats.platform.lower() == platform.lower():
|
|
return stats
|
|
return None
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Konvertiert zu Dictionary für Serialisierung"""
|
|
return {
|
|
'report_id': self.report_id,
|
|
'report_type': self.report_type.value,
|
|
'start_date': self.start_date.isoformat(),
|
|
'end_date': self.end_date.isoformat(),
|
|
'generated_at': self.generated_at.isoformat(),
|
|
'duration_days': self.duration.days,
|
|
'total_accounts_created': self.total_accounts_created,
|
|
'total_attempts': self.total_attempts,
|
|
'overall_success_rate': self.overall_success_rate,
|
|
'avg_creation_time': self.avg_creation_time,
|
|
'accounts_per_day': self.accounts_per_day,
|
|
'metrics': [
|
|
{
|
|
'name': m.name,
|
|
'value': m.value,
|
|
'unit': m.unit,
|
|
'trend': m.trend,
|
|
'is_improving': m.is_improving
|
|
}
|
|
for m in self.metrics
|
|
],
|
|
'platform_stats': [
|
|
{
|
|
'platform': ps.platform,
|
|
'total_attempts': ps.total_attempts,
|
|
'successful_accounts': ps.successful_accounts,
|
|
'failed_attempts': ps.failed_attempts,
|
|
'success_rate': ps.success_rate,
|
|
'avg_duration_seconds': ps.avg_duration_seconds,
|
|
'error_distribution': ps.error_distribution
|
|
}
|
|
for ps in self.platform_stats
|
|
],
|
|
'error_summaries': self.error_summaries,
|
|
'success_rate_timeline': {
|
|
'timestamps': [t.isoformat() for t in self.success_rate_timeline.timestamps],
|
|
'values': self.success_rate_timeline.values,
|
|
'label': self.success_rate_timeline.label,
|
|
'average': self.success_rate_timeline.get_average(),
|
|
'trend': self.success_rate_timeline.get_trend()
|
|
} if self.success_rate_timeline else None,
|
|
'insights': self.insights,
|
|
'recommendations': self.recommendations
|
|
} |