import 'package:freezed_annotation/freezed_annotation.dart'; part 'maintenance_stats_dto.freezed.dart'; part 'maintenance_stats_dto.g.dart'; @freezed class MaintenanceStatsDto with _$MaintenanceStatsDto { const factory MaintenanceStatsDto({ // 기본 계약 통계 @JsonKey(name: 'active_contracts') @Default(0) int activeContracts, @JsonKey(name: 'total_contracts') @Default(0) int totalContracts, // 만료 기간별 통계 (사용자 요구사항) @JsonKey(name: 'expiring_60_days') @Default(0) int expiring60Days, @JsonKey(name: 'expiring_30_days') @Default(0) int expiring30Days, @JsonKey(name: 'expiring_7_days') @Default(0) int expiring7Days, @JsonKey(name: 'expired_contracts') @Default(0) int expiredContracts, // 유지보수 타입별 통계 (V/R 시스템) @JsonKey(name: 'visit_contracts') @Default(0) int visitContracts, @JsonKey(name: 'remote_contracts') @Default(0) int remoteContracts, // 예정된 작업 통계 @JsonKey(name: 'upcoming_visits') @Default(0) int upcomingVisits, @JsonKey(name: 'overdue_maintenances') @Default(0) int overdueMaintenances, // 추가 메트릭 @JsonKey(name: 'total_revenue_at_risk') @Default(0.0) double totalRevenueAtRisk, @JsonKey(name: 'completion_rate') @Default(0.0) double completionRate, // 마지막 업데이트 시간 @JsonKey(name: 'updated_at') DateTime? updatedAt, }) = _MaintenanceStatsDto; factory MaintenanceStatsDto.fromJson(Map json) => _$MaintenanceStatsDtoFromJson(json); } // 대시보드 상태별 카드 데이터 @freezed class MaintenanceStatusCardData with _$MaintenanceStatusCardData { const factory MaintenanceStatusCardData({ required String title, required int count, required String subtitle, required MaintenanceCardStatus status, String? actionLabel, }) = _MaintenanceStatusCardData; factory MaintenanceStatusCardData.fromJson(Map json) => _$MaintenanceStatusCardDataFromJson(json); } // 카드 상태 열거형 enum MaintenanceCardStatus { @JsonValue('active') active, @JsonValue('warning') warning, @JsonValue('urgent') urgent, @JsonValue('critical') critical, @JsonValue('expired') expired, } // 카드 상태별 정보 헬퍼 class MaintenanceCardHelper { static Map> get statusConfig => { MaintenanceCardStatus.active: { 'color': '#059669', // Green 'icon': 'assignment', 'description': '정상 활성' }, MaintenanceCardStatus.warning: { 'color': '#F59E0B', // Amber 'icon': 'warning', 'description': '주의 필요' }, MaintenanceCardStatus.urgent: { 'color': '#EA580C', // Orange 'icon': 'schedule', 'description': '긴급 처리' }, MaintenanceCardStatus.critical: { 'color': '#DC2626', // Red 'icon': 'alert_circle', 'description': '즉시 조치' }, MaintenanceCardStatus.expired: { 'color': '#991B1B', // Dark Red 'icon': 'error', 'description': '만료됨' }, }; static String getColorForStatus(MaintenanceCardStatus status) { return statusConfig[status]?['color'] ?? '#6B7280'; } static String getIconForStatus(MaintenanceCardStatus status) { return statusConfig[status]?['icon'] ?? 'info'; } static String getDescriptionForStatus(MaintenanceCardStatus status) { return statusConfig[status]?['description'] ?? '상태 정보 없음'; } } // 대시보드 카드 생성 헬퍼 extension MaintenanceStatsDashboard on MaintenanceStatsDto { List get dashboardCards => [ // 60일 내 만료 예정 MaintenanceStatusCardData( title: '60일 내', count: expiring60Days, subtitle: '만료 예정', status: expiring60Days > 0 ? MaintenanceCardStatus.warning : MaintenanceCardStatus.active, actionLabel: '계획하기', ), // 30일 내 만료 예정 MaintenanceStatusCardData( title: '30일 내', count: expiring30Days, subtitle: '만료 예정', status: expiring30Days > 0 ? MaintenanceCardStatus.urgent : MaintenanceCardStatus.active, actionLabel: '예약하기', ), // 7일 내 만료 예정 MaintenanceStatusCardData( title: '7일 내', count: expiring7Days, subtitle: '만료 임박', status: expiring7Days > 0 ? MaintenanceCardStatus.critical : MaintenanceCardStatus.active, actionLabel: '즉시 처리', ), // 만료된 계약 MaintenanceStatusCardData( title: '만료됨', count: expiredContracts, subtitle: '조치 필요', status: expiredContracts > 0 ? MaintenanceCardStatus.expired : MaintenanceCardStatus.active, actionLabel: '갱신하기', ), ]; // 추가 요약 정보 Map get summaryStats => { '총 활성 계약': activeContracts, '방문 계약': visitContracts, '원격 계약': remoteContracts, '예정된 방문': upcomingVisits, '연체 유지보수': overdueMaintenances, }; // 위험도 계산 double get riskScore { double score = 0.0; if (totalContracts == 0) return 0.0; score += (expiredContracts / totalContracts) * 0.4; // 40% 가중치 score += (expiring7Days / totalContracts) * 0.3; // 30% 가중치 score += (expiring30Days / totalContracts) * 0.2; // 20% 가중치 score += (expiring60Days / totalContracts) * 0.1; // 10% 가중치 return score.clamp(0.0, 1.0); } // 위험도 상태 MaintenanceCardStatus get riskStatus { final risk = riskScore; if (risk >= 0.7) return MaintenanceCardStatus.critical; if (risk >= 0.5) return MaintenanceCardStatus.urgent; if (risk >= 0.3) return MaintenanceCardStatus.warning; return MaintenanceCardStatus.active; } }