import 'package:cloud_firestore/cloud_firestore.dart'; enum DeviationType { dailyMax, weeklyMax, dailyRest, weeklyRest, averageExceeded, nightWork, } enum DeviationSeverity { warning, violation, } class DeviationMetadata { final double actualValue; final double limitValue; final String? period; DeviationMetadata({ required this.actualValue, required this.limitValue, this.period, }); factory DeviationMetadata.fromMap(Map map) { return DeviationMetadata( actualValue: (map['actualValue'] ?? 0).toDouble(), limitValue: (map['limitValue'] ?? 0).toDouble(), period: map['period'], ); } Map toMap() { return { 'actualValue': actualValue, 'limitValue': limitValue, 'period': period, }; } } class Deviation { final String id; final String userId; final String organizationId; final String timeRegistrationId; final DeviationType type; final DeviationSeverity severity; final String description; final DateTime detectedAt; final DateTime? acknowledgedAt; final String? acknowledgedBy; final DeviationMetadata metadata; Deviation({ required this.id, required this.userId, required this.organizationId, required this.timeRegistrationId, required this.type, required this.severity, required this.description, required this.detectedAt, this.acknowledgedAt, this.acknowledgedBy, required this.metadata, }); factory Deviation.fromFirestore(DocumentSnapshot doc) { final data = doc.data() as Map; return Deviation( id: doc.id, userId: data['userId'] ?? '', organizationId: data['organizationId'] ?? '', timeRegistrationId: data['timeRegistrationId'] ?? '', type: _parseType(data['type']), severity: _parseSeverity(data['severity']), description: data['description'] ?? '', detectedAt: (data['detectedAt'] as Timestamp).toDate(), acknowledgedAt: data['acknowledgedAt'] != null ? (data['acknowledgedAt'] as Timestamp).toDate() : null, acknowledgedBy: data['acknowledgedBy'], metadata: DeviationMetadata.fromMap(data['metadata'] ?? {}), ); } Map toFirestore() { return { 'userId': userId, 'organizationId': organizationId, 'timeRegistrationId': timeRegistrationId, 'type': type.name, 'severity': severity.name, 'description': description, 'detectedAt': Timestamp.fromDate(detectedAt), 'acknowledgedAt': acknowledgedAt != null ? Timestamp.fromDate(acknowledgedAt!) : null, 'acknowledgedBy': acknowledgedBy, 'metadata': metadata.toMap(), }; } static DeviationType _parseType(String? typeString) { switch (typeString) { case 'dailyMax': return DeviationType.dailyMax; case 'weeklyMax': return DeviationType.weeklyMax; case 'dailyRest': return DeviationType.dailyRest; case 'weeklyRest': return DeviationType.weeklyRest; case 'averageExceeded': return DeviationType.averageExceeded; case 'nightWork': return DeviationType.nightWork; default: return DeviationType.dailyMax; } } static DeviationSeverity _parseSeverity(String? severityString) { switch (severityString) { case 'violation': return DeviationSeverity.violation; default: return DeviationSeverity.warning; } } String get typeDisplayName { switch (type) { case DeviationType.dailyMax: return 'Maks daglig arbeidstid'; case DeviationType.weeklyMax: return 'Maks ukentlig arbeidstid'; case DeviationType.dailyRest: return 'Daglig hviletid'; case DeviationType.weeklyRest: return 'Ukentlig hviletid'; case DeviationType.averageExceeded: return 'Gjennomsnittsberegning overskredet'; case DeviationType.nightWork: return 'Nattarbeid'; } } bool get isAcknowledged => acknowledgedAt != null; Deviation copyWith({ String? userId, String? organizationId, String? timeRegistrationId, DeviationType? type, DeviationSeverity? severity, String? description, DateTime? detectedAt, DateTime? acknowledgedAt, String? acknowledgedBy, DeviationMetadata? metadata, }) { return Deviation( id: id, userId: userId ?? this.userId, organizationId: organizationId ?? this.organizationId, timeRegistrationId: timeRegistrationId ?? this.timeRegistrationId, type: type ?? this.type, severity: severity ?? this.severity, description: description ?? this.description, detectedAt: detectedAt ?? this.detectedAt, acknowledgedAt: acknowledgedAt ?? this.acknowledgedAt, acknowledgedBy: acknowledgedBy ?? this.acknowledgedBy, metadata: metadata ?? this.metadata, ); } }